<aside> 🧭
Module 07 · Secrets & Ansible Vault
Keeping passwords, keys and tokens out of Git without making automation impossible. Module 06 left you with a group_vars/vault.yml sitting there in plaintext — this module fixes that.
🧠 concept → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (answers hidden)
Prerequisite: Modules 01–06.
</aside>
<aside> 📖
Official docs: Encrypting content with Ansible Vault · ansible-vault CLI · Protecting sensitive data
</aside>
<aside> 📓
The analogy. Think of a diary with a small lock on it. It genuinely stops your brother reading it, which is exactly what you wanted — so it is not a toy. But notice its three limits, because they are the same three Vault has. The one little key opens the whole diary, so you cannot let someone read March but not April. It keeps no record of who opened it. And changing the lock today does not un-read the pages he saw last year.
Ansible Vault is that diary lock: good at the job it has, and honest about the jobs it does not do. The third limit is the one that matters most in practice — when someone leaves the team, you have to rotate the actual passwords, not just the vault password, because they already read the pages.
</aside>
Ansible Vault is symmetric AES256 encryption for files in your repository. One password encrypts, the same password decrypts. That is the entire model.
| Vault is | Vault is not |
|---|---|
| Encryption at rest — safe to commit to Git | A secrets manager — no rotation, no audit log, no access policy |
| Built in, no infrastructure to run | Per-user access control — one password, everyone who has it sees everything |
| Transparent at run time — playbooks just work | Protection at run time — values are plaintext in memory and can leak to logs |
| Good enough for most teams | A substitute for HashiCorp Vault or AWS Secrets Manager at scale |
<aside> 🚨
The threat model, stated plainly. Vault protects against someone reading your Git repository. It does not protect against someone who can run your playbooks — they have the password by definition. It does not protect against a secret being printed into a CI log by a task without no_log. And revoking access means rotating the password and re-encrypting every file, because anyone who ever had it can decrypt any commit in your history.
Saying this out loud in an interview is worth more than reciting the commands.
</aside>
ansible-vault create secrets.yml # create a new encrypted file in $EDITOR
ansible-vault edit secrets.yml # ⭐ decrypt, open in $EDITOR, re-encrypt on save
ansible-vault view secrets.yml # ⭐ print decrypted, do not modify
ansible-vault encrypt existing.yml # encrypt a file that already exists
ansible-vault decrypt secrets.yml # ⚠️ permanently decrypt on disk
ansible-vault rekey secrets.yml # ⭐ change the password
ansible-vault encrypt_string 'value' # ⭐ encrypt ONE value for pasting inline
<aside> ⚠️
Never decrypt a file you intend to keep. It writes plaintext to disk, and the next git add -A commits it. Use view to read and edit to change — both keep the file encrypted at rest. decrypt exists for deliberately retiring a file from Vault, not for looking at it.
</aside>
ansible-playbook site.yml --ask-vault-pass # prompt
ansible-playbook site.yml --vault-password-file ~/.vault-pass # ⭐ a file
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault-pass # ⭐ env var
# ansible.cfg — the everyday convention
[defaults]
vault_password_file = ~/.ansible-vault-pass # path is committed; the FILE is not
<aside> 🔑
The password file must never be in the repository. Put it in your home directory, chmod 600, and add the pattern to .gitignore as a second line of defence. Committing the path in ansible.cfg is fine and useful — committing the file is a breach.
</aside>
<aside> 📬
The analogy. Think of two ways to keep something in a document private. You can seal the whole page inside an envelope — nobody sees anything at all, including the fact that only one line changed since last week. Or you can hand the page over with a black bar drawn across the sensitive line, so the structure stays readable and anyone reviewing it can see which line was covered and that the rest is untouched.
Whole-file encryption is the envelope; encrypt_string is the black bar. That is precisely why a reviewer can look at git diff on an encrypt_string file and see that exactly one secret rotated, while an encrypted whole file shows up as an unreadable wall of changed characters every single time.
</aside>