Introduction
Ansible Vault encrypts sensitive data — passwords, API keys, certificates, tokens — so you can safely store them in version control alongside your playbooks. Files are encrypted with AES-256, and you can encrypt entire files or individual variables (inline encryption).
Create an Encrypted File
# Create a new encrypted file
ansible-vault create secrets.yml
# Opens your editor — type your secrets, save, and it's encrypted
# Create with specific vault ID
ansible-vault create --vault-id prod@prompt secrets.yml
secrets.yml (what you type inside the editor):
db_password: "SuperSecret123!"
api_key: "sk-abc123def456"
ssl_private_key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQE...
-----END PRIVATE KEY-----
The saved file looks like:
$ANSIBLE_VAULT;1.1;AES256
65316332393532313030636134643235623365...
Encrypt an Existing File
# Encrypt an existing file
ansible-vault encrypt vars/production.yml
# Encrypt multiple files
ansible-vault encrypt vars/production.yml vars/staging.yml
# Encrypt with vault ID label
ansible-vault encrypt --vault-id prod@prompt vars/production.yml
View, Edit, Decrypt
# View encrypted file (read-only)
ansible-vault view secrets.yml
# Edit encrypted file (opens in editor)
ansible-vault edit secrets.yml
# Decrypt file permanently (removes encryption)
ansible-vault decrypt secrets.yml
# Re-key (change password)
ansible-vault rekey secrets.yml
Encrypt a Single String
Instead of encrypting the whole file, encrypt just one value:
# Encrypt a string
ansible-vault encrypt_string 'SuperSecret123!' --name 'db_password'
Output (paste this into your vars file):
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
65316332393532313030636134643235623365...
# Encrypt from stdin (avoid password in shell history)
echo -n 'SuperSecret123!' | ansible-vault encrypt_string --stdin-name 'db_password'
# Encrypt with specific vault ID
ansible-vault encrypt_string 'mytoken' --name 'api_token' --vault-id prod@prompt
Use Inline Encrypted Variables
# vars/main.yml — mix encrypted and plain vars
---
app_name: myapp
app_port: 8080
db_host: db.internal
# This value is encrypted, everything else is plain
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
65316332393532313030636134643235623365...
api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
38373661326462303562323564393030...
Run Playbooks with Vault
# Prompt for password
ansible-playbook site.yml --ask-vault-pass
# Password from file
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# Password from script (dynamic)
ansible-playbook site.yml --vault-password-file ./get-vault-pass.sh
# Environment variable
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
ansible-playbook site.yml
Password File
# Create a password file
echo 'MyVaultPassword' > ~/.vault_pass
chmod 600 ~/.vault_pass
# Set in ansible.cfg
# [defaults]
# vault_password_file = ~/.vault_pass
⚠️ Never commit the password file. Add it to .gitignore:
# .gitignore
.vault_pass
*.vault_pass
Multi-Vault (Multiple Passwords)
Use different passwords for different environments:
# Encrypt with vault IDs
ansible-vault encrypt --vault-id dev@prompt vars/dev.yml
ansible-vault encrypt --vault-id prod@prompt vars/prod.yml
# Run with multiple vault passwords
ansible-playbook site.yml \
--vault-id dev@~/.vault_pass_dev \
--vault-id prod@~/.vault_pass_prod
Practical Examples
Separate Secrets File
project/
├── playbook.yml
├── vars/
│ ├── main.yml # Plain variables
│ └── secrets.yml # Encrypted (ansible-vault)
└── .gitignore # Contains .vault_pass
vars/main.yml:
app_name: myapp
app_port: 8080
db_host: db.internal
db_name: myapp_prod
vars/secrets.yml (encrypted):
db_password: "SuperSecret123!"
api_key: "sk-abc123def456"
smtp_password: "EmailPass789"
playbook.yml:
---
- name: Deploy application
hosts: appservers
become: true
vars_files:
- vars/main.yml
- vars/secrets.yml # Ansible decrypts automatically
tasks:
- name: Deploy config
ansible.builtin.template:
src: app-config.yml.j2
dest: /opt/myapp/config.yml
mode: "0640"
Group Vars with Vault
inventory/
├── hosts
├── group_vars/
│ ├── all/
│ │ ├── vars.yml # Plain vars for all hosts
│ │ └── vault.yml # Encrypted secrets for all hosts
│ ├── production/
│ │ ├── vars.yml
│ │ └── vault.yml # Production secrets
│ └── staging/
│ ├── vars.yml
│ └── vault.yml # Staging secrets
This pattern is recommended by Ansible documentation — Ansible automatically loads both vars.yml and vault.yml from group_vars directories.
Encrypt Certificates
# Encrypt a certificate file
ansible-vault encrypt files/ssl/server.key
# Use in playbook
- name: Deploy SSL key
ansible.builtin.copy:
src: ssl/server.key # Ansible decrypts automatically
dest: /etc/ssl/private/server.key
mode: "0600"
CI/CD Integration
# GitHub Actions
- name: Run Ansible
env:
ANSIBLE_VAULT_PASSWORD: ${{ secrets.VAULT_PASSWORD }}
run: |
echo "$ANSIBLE_VAULT_PASSWORD" > .vault_pass
ansible-playbook site.yml --vault-password-file .vault_pass
rm -f .vault_pass
# GitLab CI
deploy:
script:
- echo "$VAULT_PASSWORD" > .vault_pass
- ansible-playbook site.yml --vault-password-file .vault_pass
- rm -f .vault_pass
Best Practices
- Separate secrets from plain vars — keep encrypted files small and focused
- Use
vault.ymlnaming convention — makes it obvious which files are encrypted - Never commit the vault password — use
.gitignore, CI secrets, or a password manager - Use inline encryption for 1-2 secrets mixed with plain vars
- Use file encryption when most/all values in a file are sensitive
- Use vault IDs when you have different passwords per environment
- Rotate passwords regularly with
ansible-vault rekey
Troubleshooting
"Decryption failed"
Wrong password. Verify you're using the correct password/file:
# Test by viewing
ansible-vault view secrets.yml --ask-vault-pass
"is not a vault encrypted file"
The file isn't encrypted, or the header is corrupted. Check if it starts with $ANSIBLE_VAULT;:
head -1 secrets.yml
# Should show: $ANSIBLE_VAULT;1.1;AES256
"No vault secrets found"
You forgot --ask-vault-pass or --vault-password-file:
# Add the flag
ansible-playbook site.yml --ask-vault-pass
# Or set in ansible.cfg
# [defaults]
# vault_password_file = ~/.vault_pass
Related Articles
- Ansible Vault Credentials for Enterprise
- Ansible Variables Guide
- Ansible Best Practices
- Ansible Security Hardening
Conclusion
Ansible Vault makes it safe to store secrets in Git. Encrypt entire files with ansible-vault encrypt or individual values with encrypt_string. Use password files or CI/CD secrets for automation. The recommended pattern: keep plain vars in vars.yml and secrets in vault.yml within group_vars directories. Use multi-vault with vault IDs when managing multiple environments with different passwords.