Ansible Vault Secret Management
Securely manage secrets in Ansible with Vault encryption — encrypt files and strings, use vault IDs for multi-environment passwords, integrate with external secret managers, and set up CI/CD pipelines with proper vault password handling.
Content
Overview
Ansible Vault encrypts sensitive data — passwords, API keys, TLS certificates, database credentials — so they can live safely in version control alongside your playbooks. Vault uses AES-256 symmetric encryption and supports both file-level and string-level encryption, multiple passwords per project via vault IDs, and integration with external secret managers for password retrieval.
The Vault/Vars Split Pattern
The most important organizational decision is separating encrypted values from plaintext variable references. This is the standard pattern used by most production Ansible codebases:
The vault_ prefix convention makes it immediately clear which values are secrets. When you grep for db_password in your codebase, you find the reference in vars.yml and know the actual value lives in the encrypted vault file. Reviewers can see exactly what variables a playbook uses without needing the vault password.
File-Level Encryption
Use file-level encryption when the entire file contains sensitive data:
When you run ansible-vault edit, Vault decrypts the file to a temporary location, opens your editor, and re-encrypts when you save and close. The plaintext never touches disk in your project directory — it goes to a tmpfs-backed temporary file on Linux.
String-Level Encryption
String-level encryption (via encrypt_string) lets you embed encrypted values directly in otherwise-plaintext YAML files. This is the preferred approach for most projects because it keeps everything in one file while protecting only the sensitive values:
The echo -n with stdin approach is important for security: passing the secret directly as a command argument puts it in your shell history file. Using stdin or the --prompt flag avoids this. On shared systems, also be aware that /proc/<pid>/cmdline exposes command arguments to other users.
Paste the output directly into your vars file. Ansible automatically decrypts !vault tagged values at runtime.
Multi-Environment Vault IDs
Vault IDs solve the problem of managing different secrets for different environments. Without them, you'd either use one password for everything (dangerous — a leaked dev password exposes production) or manually specify which password file to use each time.
The format is <vault-id>@<source>, where source can be:
- -
prompt— ask interactively - -
/path/to/file— read from a file - -
/path/to/script.sh— execute a script that prints the password
When multiple vault IDs are provided, Ansible tries each one until it finds a match. The vault ID is embedded in the encrypted data header, so Ansible can efficiently select the right password.
Vault Password Scripts
For automation and team workflows, a password script retrieves the vault password from an external source at runtime:
This pattern keeps vault passwords out of files on disk entirely. The script can pull from AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, 1Password CLI, or any other secret backend your team uses.
External Secret Manager Integration
For organizations that already have a centralized secret manager, you can bypass Ansible Vault entirely and fetch secrets at runtime using lookup plugins:
The external lookup approach has advantages for large organizations: secrets are centrally managed, rotated, and audited in one place. The tradeoff is a runtime dependency — your playbook fails if the secret manager is unreachable. Ansible Vault works fully offline.
CI/CD Pipeline Integration
For GitLab CI, Jenkins, and other platforms, the pattern is the same: store the vault password as a pipeline secret, write it to a temporary file or pipe it via stdin, and clean up after the run.
Rekeying and Rotation
Rotate vault passwords when team members leave, when passwords may have been exposed, or on a regular schedule for compliance:
After rekeying, commit the re-encrypted files. The actual secret values don't change — only the encryption password wrapping them. Distribute the new vault password through your team's secure channel.
Best Practices
- -Use the vault/vars split pattern — separate encrypted vault files from plaintext variable references
- -Prefix vault variables with `vault_` — makes encrypted values instantly identifiable
- -Use vault IDs for environment separation — different passwords for dev, staging, production
- -Store vault passwords in a secret manager — never in flat files on disk or in version control
- -Always set `no_log: true` on tasks that use vault variables — prevents secrets from appearing in Ansible output and logs
- -Use stdin for `encrypt_string` — avoids exposing secrets in shell history
- -Configure vault identity list in `ansible.cfg` — reduces command-line boilerplate for the team
Common Mistakes
- -Committing unencrypted secrets: Always encrypt before the first
git add. Use a pre-commit hook to scan for unencrypted secrets - -Same vault password for all environments: A compromised dev password should never expose production secrets
- -Forgetting `no_log: true`: Secrets appear in plaintext in Ansible output, CI logs, and tower job output
- -Editing vault files with a regular editor: Opening an encrypted file in vim without
ansible-vault editcorrupts the encryption envelope - -Vault password files in the repo: Even if gitignored, they risk accidental inclusion. Use scripts or environment variables instead
- -Not rekeying after team changes: Former team members retain access to all secrets encrypted with the old password
FAQ
Discussion
Loading comments...