Introduction
Ansible Vault encrypts sensitive data — passwords, API keys, certificates, and configuration files — so you can safely store them in version control alongside your playbooks. It uses AES-256 symmetric encryption and integrates seamlessly into playbook execution.
This guide covers all Vault operations: encrypting strings, files, using multiple vault passwords, and best practices for managing secrets in production.
How Ansible Vault Works
Vault encrypts data using AES-256 in CTR mode with HMAC-SHA256 authentication. The encrypted content is stored as ASCII-armored text prefixed with $ANSIBLE_VAULT;1.1;AES256.
Key concepts:
- Vault encrypts at rest — decryption happens in memory during playbook execution
- A single vault password (passphrase) encrypts/decrypts the content
- Multiple vault IDs allow different passwords for different secrets
- Vault integrates with
ansible-playbook,ansible, andansible-vaultCLI tools
Basic Operations
Encrypt a File
# Interactive password prompt
$ ansible-vault encrypt vars/secrets.yml
New Vault password:
Confirm New Vault password:
Encryption successful
# Using a password file
$ ansible-vault encrypt vars/secrets.yml --vault-password-file ~/.vault_pass
Encryption successful
Before encryption:
---
db_password: "SuperSecret123!"
api_key: "sk-abc123def456"
ssl_private_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
After encryption:
$ANSIBLE_VAULT;1.1;AES256
36353832316130613239633365656232653262353632...
Decrypt a File
# View decrypted content (doesn't modify file)
$ ansible-vault view vars/secrets.yml
# Decrypt file back to plaintext (modifies file)
$ ansible-vault decrypt vars/secrets.yml
# Decrypt to stdout
$ ansible-vault decrypt vars/secrets.yml --output -
Edit an Encrypted File
# Opens in $EDITOR, re-encrypts on save
$ ansible-vault edit vars/secrets.yml
Change Vault Password
$ ansible-vault rekey vars/secrets.yml
Vault password (current):
New Vault password:
Confirm New Vault password:
Rekey successful
Encrypt Individual Strings (encrypt_string)
For encrypting a single variable value without encrypting the entire file:
# Encrypt a string for use in YAML
$ ansible-vault encrypt_string 'SuperSecret123!' --name 'db_password'
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62313637323663343764643830...
# From stdin (avoids password in shell history)
$ echo -n 'SuperSecret123!' | ansible-vault encrypt_string --stdin-name 'db_password'
# With a vault ID
$ ansible-vault encrypt_string 'mykey123' --name 'api_key' --vault-id prod@~/.vault_pass_prod
Use in Variable Files
---
# vars/secrets.yml - mix of plain and encrypted values
app_name: myapp
app_port: 8080
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62313637323663343764643830353433363938636431626563653531376533306662
3237366261616130323035353163613436393337326137360a643931613762363130
63396332363736363236623139326233383262356337633464306439613138663235
3530336538346637650a393263303931333233313632366363643062653262356365
6264
api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
35376233393338613463616430303334...
Using Vault in Playbooks
Running a Playbook with Vault
# Interactive password prompt
$ ansible-playbook deploy.yml --ask-vault-pass
# Password file
$ ansible-playbook deploy.yml --vault-password-file ~/.vault_pass
# Environment variable pointing to password file
$ export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
$ ansible-playbook deploy.yml
Playbook Example
---
- name: Deploy with encrypted secrets
hosts: dbservers
become: true
vars_files:
- vars/common.yml
- vars/secrets.yml # Can be fully encrypted
tasks:
- name: Configure database password
ansible.builtin.template:
src: db.conf.j2
dest: /etc/myapp/db.conf
mode: '0600'
# {{ db_password }} is decrypted automatically
- name: Set environment variable
ansible.builtin.lineinfile:
path: /etc/myapp/env
line: "API_KEY={{ api_key }}"
mode: '0600'
Multiple Vault Passwords (Vault IDs)
For organizations managing secrets across environments:
# Encrypt with vault ID "prod"
$ ansible-vault encrypt vars/prod-secrets.yml --vault-id prod@~/.vault_pass_prod
# Encrypt with vault ID "dev"
$ ansible-vault encrypt vars/dev-secrets.yml --vault-id dev@~/.vault_pass_dev
# Run playbook with multiple vault IDs
$ ansible-playbook site.yml \
--vault-id dev@~/.vault_pass_dev \
--vault-id prod@~/.vault_pass_prod
ansible.cfg Configuration
[defaults]
vault_identity_list = dev@~/.vault_pass_dev, prod@~/.vault_pass_prod
Best Practices
1. Separate Secret and Non-Secret Variables
group_vars/
├── production/
│ ├── vars.yml # Non-sensitive (plain text)
│ └── vault.yml # Sensitive (encrypted)
└── staging/
├── vars.yml
└── vault.yml
2. Prefix Vaulted Variable Names
# vault.yml (encrypted)
---
vault_db_password: "SuperSecret123!"
vault_api_key: "sk-abc123"
# vars.yml (plain text, references vault vars)
---
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"
This makes it clear which variables contain secrets.
3. Never Commit Vault Password Files
# .gitignore
.vault_pass*
*.vault_password
4. Use a Password Script
#!/bin/bash
# ~/.vault_pass_script.sh
# Fetch password from a secret manager
aws secretsmanager get-secret-value --secret-id ansible-vault --query SecretString --output text
[defaults]
vault_password_file = ~/.vault_pass_script.sh
5. Encrypt Only What's Necessary
Don't encrypt entire files if only one variable is sensitive — use encrypt_string for individual values.
Complete Playbook: Secret Rotation
---
- name: Rotate database credentials
hosts: dbservers
become: true
vars_files:
- vars/vault.yml
vars:
new_password: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}"
tasks:
- name: Update database user password
community.mysql.mysql_user:
name: "{{ db_username }}"
password: "{{ new_password }}"
login_user: root
login_password: "{{ vault_mysql_root_password }}"
state: present
- name: Update application config
ansible.builtin.template:
src: database.yml.j2
dest: /opt/app/config/database.yml
owner: appuser
mode: '0600'
vars:
db_password: "{{ new_password }}"
notify: Restart application
- name: Store new password in vault (local)
ansible.builtin.copy:
content: |
---
vault_db_password: "{{ new_password }}"
dest: "{{ playbook_dir }}/vars/vault.yml"
mode: '0600'
delegate_to: localhost
run_once: true
- name: Re-encrypt vault file
ansible.builtin.command:
cmd: ansible-vault encrypt "{{ playbook_dir }}/vars/vault.yml"
delegate_to: localhost
run_once: true
changed_when: true
handlers:
- name: Restart application
ansible.builtin.systemd:
name: myapp
state: restarted
Troubleshooting
"Decryption failed"
Cause: Wrong vault password.
Fix: Verify you're using the correct password file or prompt.
"is not a vault encrypted file"
Cause: File doesn't start with $ANSIBLE_VAULT header.
Fix: Ensure the file was encrypted with ansible-vault encrypt.
"ERROR! Vault password required but not provided"
Fix: Add --ask-vault-pass or --vault-password-file to your command:
ansible-playbook site.yml --ask-vault-pass
Viewing Encrypted Variables in Debug
- name: Debug vaulted variable (shows decrypted value!)
ansible.builtin.debug:
var: db_password
# WARNING: This prints the secret in plain text to console
tags: [never, debug] # Only run when explicitly tagged
Vault vs External Secret Managers
| Feature | Ansible Vault | HashiCorp Vault | AWS Secrets Manager |
|---|---|---|---|
| Setup complexity | Low | High | Medium |
| Dynamic secrets | No | Yes | Yes |
| Access control | File-based | Policy-based | IAM-based |
| Rotation | Manual | Automatic | Automatic |
| Cost | Free | $$$ | $ per secret |
| Best for | Small teams | Enterprise | AWS-native |
For larger organizations, consider combining Ansible Vault with a lookup plugin:
- name: Fetch secret from HashiCorp Vault
ansible.builtin.debug:
msg: "{{ lookup('hashi_vault', 'secret=secret/data/myapp:password') }}"
Related Articles
- Ansible Vault encrypt_string — Inline string encryption
- Ansible Variables — Variable precedence
- Ansible Security Hardening — Server security
- Ansible Lookup Plugins — External data sources
Conclusion
Ansible Vault is the simplest way to manage secrets in Ansible — no external infrastructure required. Use encrypt_string for individual variables, full file encryption for secret-heavy files, and vault IDs for multi-environment setups. Always store vault passwords outside version control and consider password scripts that integrate with your team's existing secret management tools.