Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
Before you start
- ▸Ansible 2.8 or later installed on the control node
- ▸An existing Ansible project with at least one playbook and inventory
- ▸Basic familiarity with YAML variable files and group_vars layout
Hardcoding passwords, API keys, and certificates in Ansible playbooks is a fast path to a credentials leak. Ansible Vault encrypts sensitive data at rest using AES-256 so secrets travel safely in version control. This guide covers encrypting individual files and variables, using password files for automation, and organizing group-level secrets that different teams or environments need separately.
How Ansible Vault Works
Vault encrypts any YAML or arbitrary file with a symmetric AES-256-CBC key derived from a password you supply. The encrypted blob is valid YAML, so it can live inside a vars file, a host_vars directory, or inline with !vault tagged strings. Ansible decrypts transparently at runtime when you pass the password. You can maintain multiple vault IDs—useful when separate teams own separate secrets.
Prerequisites and Installation
Ansible Vault is bundled with Ansible core; no extra package is needed. Verify your version first, since vault IDs require Ansible 2.4+ and the --encrypt-vault-id flag requires 2.8+.
ansible --version
Install or upgrade if needed:
# Debian / Ubuntu
sudo apt update && sudo apt install ansible
# Fedora / RHEL / Rocky
sudo dnf install ansible
# Arch
sudo pacman -S ansible
# Any distro — latest via pip (recommended for current releases)
pip install --upgrade ansible
Encrypting a File
The most straightforward use is encrypting an entire variable file. Create a plain YAML secrets file, then encrypt it in place.
cat > group_vars/production/vault.yml << 'EOF'
db_password: "s3cur3P@ssword"
api_key: "abc123secretkey"
EOF
ansible-vault encrypt group_vars/production/vault.yml
Vault prompts for a new password and confirmation. The file becomes a block starting with $ANSIBLE_VAULT;1.1;AES256. Commit it to git safely—without the password it is useless.
Editing, Viewing, and Decrypting
View without decrypting to disk
ansible-vault view group_vars/production/vault.yml
Edit in place
Vault decrypts to a temp file, opens your $EDITOR, then re-encrypts on save. Set your preferred editor if needed.
EDITOR=nano ansible-vault edit group_vars/production/vault.yml
Decrypt permanently
Only do this locally when you need to inspect or migrate the file. Never leave decrypted secrets on shared hosts.
ansible-vault decrypt group_vars/production/vault.yml
Re-key: change the vault password
ansible-vault rekey group_vars/production/vault.yml
Running Playbooks with Vault-Encrypted Files
Pass the password interactively during a run:
ansible-playbook site.yml --ask-vault-pass
For automated pipelines use a password file instead of interactive prompts.
Using a Password File
A password file contains exactly one line: the vault password, no trailing newline is necessary but harmless. Lock it down hard.
echo 'MyVaultPassword123!' > ~/.vault_pass
chmod 600 ~/.vault_pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass
To avoid repeating the flag, set it in ansible.cfg:
cat >> ansible.cfg << 'EOF'
[defaults]
vault_password_file = ~/.vault_pass
EOF
In CI/CD pipelines, inject the password as an environment variable and use a script that prints it:
cat > vault_pass_script.sh << 'EOF'
#!/bin/sh
echo "$VAULT_PASSWORD"
EOF
chmod 700 vault_pass_script.sh
ansible-playbook site.yml --vault-password-file ./vault_pass_script.sh
Encrypting Individual Variables (Inline Vault)
When only one or two values in a file are sensitive, encrypt just those strings. This keeps most of the file human-readable.
ansible-vault encrypt_string 's3cur3P@ssword' --name 'db_password'
Output looks like:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386134306565383338353534...
Paste the entire block, including the !vault | tag, into any variable file. Ansible decrypts it at task execution time.
Group-Level Secrets with Multiple Vault IDs
Large environments often need different teams to own different secrets. Vault IDs let you label encrypted content and supply the matching password at runtime without exposing other vaults.
Create vaults with named IDs
# Encrypt the production secrets with the 'prod' ID
ansible-vault encrypt --vault-id prod@prompt group_vars/production/vault.yml
# Encrypt staging secrets with the 'staging' ID
ansible-vault encrypt --vault-id staging@prompt group_vars/staging/vault.yml
Run providing both passwords
ansible-playbook site.yml \
--vault-id prod@~/.vault_pass_prod \
--vault-id staging@~/.vault_pass_staging
Each password file is only known to the team responsible for that tier. A developer with only ~/.vault_pass_staging cannot decrypt production secrets.
Recommended directory layout
group_vars/
production/
vars.yml # plain variables
vault.yml # vault-encrypted (vault-id: prod)
staging/
vars.yml
vault.yml # vault-encrypted (vault-id: staging)
host_vars/
db-primary.example.com/
vault.yml # host-specific secrets
The convention of separating vars.yml (readable) from vault.yml (encrypted) makes code reviews practical—reviewers see variable names without touching secrets.
Verification
Confirm encryption is intact and the password works before committing:
ansible-vault view group_vars/production/vault.yml --vault-password-file ~/.vault_pass
Run a syntax check against your playbook to ensure Ansible can decrypt and parse all vars:
ansible-playbook site.yml --syntax-check --vault-password-file ~/.vault_pass
Grep for any accidental plaintext secrets before pushing:
grep -r 'ANSIBLE_VAULT' group_vars/ host_vars/
Every file that should be encrypted will match. Anything that doesn't appear in this output but contains a password is a problem.
Troubleshooting
- ERROR! Decryption failed (no vault secrets would unlock): The supplied password is wrong, or you forgot to pass
--vault-idfor a labeled vault. Double-check which ID was used during encryption. - Playbook hangs waiting for vault password: You have encrypted vars but no
--ask-vault-passor password file configured. Setvault_password_fileinansible.cfg. - ansible-vault edit opens vi unexpectedly: Set
export EDITOR=nano(or your preferred editor) in your shell profile. - Encrypted file committed but others can't decrypt: Team members need the password out-of-band (a secrets manager like HashiCorp Vault, a shared password manager, or a CI/CD secret). The vault password itself is never committed to git.
- Mixed vault IDs in a single run fail: You must supply a
--vault-idflag for every distinct ID used across all encrypted files loaded in that play. Use password files rather than@promptin automation to avoid interactive blocking.
Frequently asked questions
- Can I store the vault password inside the repository?
- No. The vault password must be distributed out-of-band—through a secrets manager, CI/CD environment variable, or a shared password manager. Committing it defeats the entire purpose of encryption.
- What is the difference between encrypting a whole file and using encrypt_string?
- Encrypting a whole file hides every value in it, making diffs in code review uninformative. encrypt_string encrypts only the sensitive value and leaves variable names visible, which is better for reviewability but requires more care to not miss a sensitive field.
- Does Ansible Vault protect secrets in memory or only at rest?
- Vault only protects secrets at rest and in transit in the repository. During playbook execution, decrypted values exist in memory on the control node and may appear in verbose output or log files if you use -vvv or log_path.
- How do vault IDs differ from using separate password files without IDs?
- Without IDs, Ansible tries every supplied password against every encrypted blob, which works but is slow and error-prone at scale. Vault IDs tag each encrypted object so Ansible immediately knows which password to try, and they enforce access separation by environment or team.
- Can I use Ansible Vault with HashiCorp Vault or AWS Secrets Manager?
- Yes. Write a vault password script that fetches the password from your external secrets manager at runtime, then pass it with --vault-password-file ./your_script.sh. This combines Vault's encryption with centralized secret rotation.
Related guides
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.
How to Audit Linux Hardening with Lynis
Run Lynis to audit your Linux server, interpret the hardening index and warning output, and work through findings from critical to low-effort wins.