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

Featureencrypt_string (inline)Vault file (full file)
Encrypted unitSingle variable valueEntire 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 workflowRe-encrypt each stringansible-vault edit file.yml
Multiple vault IDs✅ Per-string✅ Per-file
Best forFew secrets mixed with non-secretsMany 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
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 edit workflow
  • You follow the vars.yml + vault.yml directory 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

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.