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
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_stringfor 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.ymlif it’s genuinely meant to be overridable by whoever uses the role. - Verify indentation carefully when pasting
encrypt_stringoutput, and run--syntax-checkafterward to catch YAML formatting mistakes before they cause a confusing failure later.