unit 7 · Secrets & scale
Ansible Vault & vault IDs
Secrets you can commit
you may want to read 16 · Variables & the precedence that matters first — but nothing is locked
tl;dr
- ansible-vault encrypts secrets at rest so they can live in Git; encrypt, decrypt, edit, view are the verbs.
- Encrypt whole var files or single values (!vault); unlock runs with --ask-vault-pass or a password file.
- Vault IDs label multiple keys, so dev and prod secrets can use different passwords in one run.
why it matters Lesson 16 banned secrets from -e because they leak into logs; Vault is where they go instead — encrypted in the repo, decrypted only at run time.
Lesson 16 banned secrets from -e:
extra vars ride the command line into shell history, process
listings and CI logs. This lesson is the promised answer.
Vault is Ansible’s built-in encryption for secrets at
rest. You encrypt a file with a password and commit the ciphertext. Any run
that has the password decrypts it in memory — never on disk, never in the log.
The tool is ansible-vault; its subcommands are the verbs you’d guess:
ansible-vault encrypt group_vars/prod/secrets.yml # scramble in place
ansible-vault view group_vars/prod/secrets.yml # decrypt to screen only
ansible-vault edit group_vars/prod/secrets.yml # decrypt, open $EDITOR, re-encrypt
ansible-vault decrypt group_vars/prod/secrets.yml # back to plaintext (rare)After encrypt, the file on disk is unreadable ciphertext:
$ANSIBLE_VAULT;1.1;AES256
66386439653236336462626566653063336164663966303231363934
65356136396436383331366264316265363035303762333634383265That header is the tell: one glance at a diff says the file is vaulted.
So where do secrets live? Right where lesson 9 put every other variable.
Vaulted files sit in group_vars/ and next to playbooks, committed to Git
like everything else. The repo can hold the secret because it never holds
the plaintext.
Encrypting a single value
Encrypting a whole file has a cost: git grep db_password finds nothing, and
reviewers can’t see which keys changed. The alternative: encrypt only the
value with ansible-vault encrypt_string, and paste its output into a
plain YAML file under the !vault tag:
db_user: app_svc # plain — searchable, reviewable
db_password: !vault | # only this value is ciphertext
$ANSIBLE_VAULT;1.1;AES256
6231336539666234306139346433616338373634373764613633Both styles are legitimate; teams pick one convention and stick to it. Either
way, {{ db_password }} works in tasks and templates as if the value were
plaintext — decryption happens transparently when the variable loads.
Supplying the key at run time
Encryption is only half the transaction. Every run that touches vaulted content needs the password:
ansible-playbook site.yml --ask-vault-pass # prompts you
ansible-playbook site.yml --vault-password-file ~/.vault_pass # reads a file--ask-vault-pass is for humans at a terminal. --vault-password-file is
for automation: in a Jenkins pipeline the password lives in the credential
store and is written to a temp file for the run, never hardcoded.
Keep the password file itself out of Git.
Vault IDs: more than one key
One password for the whole repo means anyone who can decrypt dev can
decrypt prod. A vault ID fixes that. Each key gets a
label as label@source, so different files can use different passwords
and one run can supply several:
ansible-vault encrypt --vault-id prod@prompt group_vars/prod/secrets.yml
ansible-playbook site.yml --vault-id dev@~/.dev_pass --vault-id prod@promptThe source half says where the password comes from — prompt asks
interactively, a path reads a file. The label is stamped into the encrypted
header, so Ansible knows which key opens which file.
Where Vault stops
Ansible Vault is the right tool when secrets live alongside playbooks in Git —
most of what a config-management repo needs. At larger scale, teams reach for
dedicated secret managers: HashiCorp Vault (queried live via the
community.hashi_vault lookup), CyberArk Conjur, or a cloud KMS/Key Vault.
The dividing line: file-based Ansible Vault for secrets that version with
your code, HashiCorp Vault for large-scale dynamic secrets that rotate out
from under it. Your Azure instinct — nothing sensitive outside Key Vault —
maps cleanly. Here the vault is a file, and the habit at work is three
words: we vault that.
at work, this sounds like
- “We vault that.”
- That value is stored encrypted in Ansible Vault, not in plaintext.
self-check — recall, not a test
1 Why is a vaulted secrets file safe to commit to Git?
2 A playbook that loads vaulted group_vars fails immediately with a decryption error. What is missing?
3 When would you reach for HashiCorp Vault instead of Ansible Vault?
lab (optional — never required)
Put a fake password in a vars file, ansible-vault encrypt it, view it, then print it from a one-task debug play run with --ask-vault-pass.
needs: The control node from lesson 5.