Introduction
Ansible Vault encrypts sensitive data so you can safely commit secrets to version control. You can encrypt entire files or individual strings inline. Each approach has different workflows, git diff behavior, and team collaboration implications. This guide helps you choose the right one.
Quick Comparison
| Feature | encrypt_string (inline) | Vault file (full file) |
|---|---|---|
| Encrypted unit | Single variable value | Entire file |
| Git diff | ❌ Unreadable (binary blob per value) | ❌ Unreadable (entire file) |
| Variable names visible | ✅ Yes (only value encrypted) | ❌ No (everything encrypted) |
| Mix with plaintext | ✅ Same file | ❌ Separate file required |
| Edit workflow | Re-encrypt each string | ansible-vault edit file.yml |
| Multiple vault IDs | ✅ Per-string | ✅ Per-file |
| Best for | Few secrets mixed with non-secrets | Many secrets, dedicated secret files |
encrypt_string — Inline Encryption
# Encrypt a single string
ansible-vault encrypt_string 'MyS3cretP@ss' --name 'db_password'
# Output:
# db_password: !vault |
# $ANSIBLE_VAULT;1.1;AES256
# 61626364...
# Encrypt from stdin (more secure — no shell history)
echo -n 'MyS3cretP@ss' | ansible-vault encrypt_string --stdin-name 'db_password'
# With a specific vault ID
ansible-vault encrypt_string 'MyS3cretP@ss' --name 'db_password' --vault-id prod@prompt
Use in Variables File
# group_vars/production.yml
# Variable names are visible, only values are encrypted
---
app_version: "2.5.0"
deploy_user: deploy
http_port: 8080
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
6164623431393030363033...
api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
3839323632353431313439...
# Non-secret variables remain readable
log_level: info
backup_enabled: true
Advantages
# ✅ Easy to see which variables exist
# ✅ Non-secret values stay readable
# ✅ Can mix encrypted and plain in one file
# ✅ Easy to add one new secret without touching others
Vault File — Full File Encryption
# Create an encrypted file
ansible-vault create group_vars/production/vault.yml
# Encrypt an existing file
ansible-vault encrypt group_vars/production/vault.yml
# Edit (decrypts in $EDITOR, re-encrypts on save)
ansible-vault edit group_vars/production/vault.yml
# View without editing
ansible-vault view group_vars/production/vault.yml
# Decrypt permanently
ansible-vault decrypt group_vars/production/vault.yml
Directory Pattern (Recommended)
group_vars/
└── production/
├── vars.yml # Plaintext — all non-secret variables
└── vault.yml # Encrypted — all secrets
# group_vars/production/vault.yml (encrypted)
---
vault_db_password: "MyS3cretP@ss"
vault_api_key: "sk-abc123xyz"
vault_ssl_key: |
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBg...
-----END PRIVATE KEY-----
# group_vars/production/vars.yml (plaintext)
---
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"
ssl_key: "{{ vault_ssl_key }}"
app_version: "2.5.0"
Advantages
# ✅ Easy to edit with ansible-vault edit
# ✅ All secrets in one place
# ✅ vault_ prefix makes it clear which vars are secrets
# ✅ vars.yml shows the mapping without revealing values
Running Playbooks
# Prompt for password
ansible-playbook site.yml --ask-vault-pass
# Password file
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# Environment variable
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
ansible-playbook site.yml
# Multiple vault IDs
ansible-playbook site.yml \
--vault-id dev@~/.vault_pass_dev \
--vault-id prod@~/.vault_pass_prod
Multiple Vault IDs
# Encrypt with specific ID
ansible-vault encrypt_string 'secret' --vault-id prod@prompt --name 'api_key'
# Different teams can have different passwords
ansible-vault encrypt group_vars/production/vault.yml --vault-id prod@prompt
ansible-vault encrypt group_vars/staging/vault.yml --vault-id staging@prompt
When to Use Which
Use encrypt_string when:
- You have few secrets mixed with many plain variables
- Team members need to see variable names without vault access
- You want one file per group (simpler structure)
- Secrets belong to different vault IDs in the same file
Use vault files when:
- You have many secrets (database creds, API keys, certificates)
- You want easy
ansible-vault editworkflow - You follow the
vars.yml+vault.ymldirectory pattern - You need to encrypt multiline content (SSL keys, certificates)
Common Mistakes
# ❌ Committing vault password to git
echo "mypassword" > .vault_pass
git add .vault_pass # NEVER do this!
# ✅ Add to .gitignore
echo ".vault_pass" >> .gitignore
# ❌ Using the same vault password for all environments
# ✅ Use vault IDs: different passwords for prod/staging/dev
# ❌ Encrypting non-secret variables
ansible-vault encrypt group_vars/all.yml
# Now nobody can see ANY variables without the password
# ✅ Only encrypt secrets, keep everything else readable
# Use the vars.yml + vault.yml split pattern
# ❌ Forgetting the vault_ prefix convention
# vault.yml
db_password: "secret" # Which vars come from vault?
# ✅ Use vault_ prefix
# vault.yml
vault_db_password: "secret"
# vars.yml
db_password: "{{ vault_db_password }}" # Clear origin
Related Articles
- Ansible Vault Guide
- Ansible group_vars vs host_vars vs role defaults
- Ansible Variables Guide
- Ansible Security Best Practices
Conclusion
encrypt_string for inline secrets mixed with plaintext variables — good for few secrets, visible variable names. Vault files for dedicated secret files with the vars.yml + vault.yml pattern — good for many secrets and easy editing. The recommended practice: split group_vars/<env>/ into vars.yml (readable) and vault.yml (encrypted), use vault_ prefix on encrypted variables, and never commit vault passwords to git.