Skip to content

Encrypting Variables


Whole-file encryption from earlier in this section has a real practical downside worth naming directly. This chapter covers the alternative — encrypting and directly using just the one value that actually needs it.

The Limitation Of Whole-File Encryption

Encrypt an entire vars file, and every value in it becomes unreadable at rest — even values that were never sensitive to begin with, sitting right next to the one that genuinely is. This makes reviewing changes in git meaningfully harder: a diff on a fully-encrypted file shows you nothing useful, since the entire encrypted blob changes completely even for a one-character edit to a completely non-sensitive value.

ansible-vault encrypt_string: Encrypting Just One Value

ansible-vault encrypt_string 'supersecret123' --name 'db_password'

Outputs a YAML-formatted, encrypted representation of just that one value — ready to paste directly into an otherwise plaintext vars file.

The !vault Tag

db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236336462626566653063336164663966303231363934653561
          ...

!vault is a YAML tag telling Ansible “this specific value is encrypted — decrypt it before use.” Everything else in the surrounding file is read as ordinary, plain YAML, exactly as normal.

A Realistic Example: A Mostly-Plaintext Vars File

vars/db_config.yaml
db_host: "10.0.0.5"
db_port: 5432
db_user: "app_user"
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236336462626566653063336164663966303231363934653561
          ...

db_host, db_port, and db_user stay genuinely readable and diffable in plaintext, while db_password specifically stays protected — the practical middle ground between “everything encrypted” and “nothing encrypted.”

Where This Fits Into defaults//vars/

Recall the roles section’s defaults/main.yml-versus-vars/main.yml distinction — whether a value belongs there is decided purely by whether it’s genuinely user-configurable or genuinely internal to the role, and that’s still true regardless of encryption.

db_password is a good example of where instinct might mislead: it feels like something to hide away in vars/main.yml since it’s sensitive — but if different environments or different users of the role genuinely need to supply their own value, it belongs in defaults/main.yml, encrypted inline with !vault, not vars/main.yml. Sensitivity and configurability are two separate axes — encrypting a value doesn’t change which category it falls into, and conflating the two is a subtle, easy mistake.

A Gotcha: encrypt_string Output Must Be Indented Correctly

The output is a multi-line YAML block scalar, and it has to be indented consistently and correctly relative to its key for YAML to parse it at all. Careless copy-pasting — wrong indentation level, mixed tabs and spaces — can break the file’s YAML entirely, or worse, silently fail to be recognized as the vault-tagged value it’s supposed to be.

Use the --name flag as shown, which produces output already formatted as a ready-to-paste snippet, and verify afterward with ansible-playbook site.yaml --syntax-check — a flag that checks a playbook’s YAML and syntax validity without actually running anything, worth knowing about specifically for catching exactly this kind of formatting mistake early.

Best Practices

  • Use encrypt_string for individual sensitive values inside an otherwise-plaintext file, keeping the rest of the file genuinely readable and diffable in version control.
  • Remember sensitivity and configurability are separate concerns — an encrypted value can still belong in defaults/main.yml if it’s genuinely meant to be overridable by whoever uses the role.
  • Verify indentation carefully when pasting encrypt_string output, and run --syntax-check afterward to catch YAML formatting mistakes before they cause a confusing failure later.
Last updated on