Ansible OEL 8 DevOps · OEL 8 · Secrets

AnsibleAnsible Vault — Encrypting Secrets

Why secrets shouldn't sit in plain text, the encrypt/decrypt/edit lifecycle, encrypting just one variable inside a plain file, and the multi-vault-id pattern for managing different keys per environment.

Database passwords, API tokens, TLS private keys — these can't sit in group_vars/all.yml in plain text if that file is committed to git. Anybody with read access to the repo would have production credentials. Ansible Vault is the built-in solution: encrypt the file with a password, commit the encrypted bytes, keep the password out of git.

vault.yml (plain) db_password: super_secret api_key: xxx encrypt ansible-vault AES-256-CTR vault.yml (encrypted) $ANSIBLE_VAULT;1.2; AES256;prod_key 61356638316563... vault password .vault_pass / prompt / file At playbook run: ansible-playbook site.yml --vault-password-file .vault_pass decrypts in memory only Encrypted file is committed to git · password is NOT
💡 Tip: Vault uses AES-256 in CTR mode with HMAC-SHA-256 for authentication. The encrypted file is safe to push to public GitHub if your password is strong.
BASH — encrypt a file
# Create your secrets file in plain text
cat > group_vars/all/vault.yml << EOF
vault_mysql_root_password: "ChangeMeNow123!"
vault_appuser_password:    "AnotherSecret456!"
vault_api_token:           "tok_aBc123XyZ"
EOF

# Encrypt in place
ansible-vault encrypt group_vars/all/vault.yml

# You'll be prompted twice for a password. The file now starts with:
head -1 group_vars/all/vault.yml
# $ANSIBLE_VAULT;1.2;AES256

# Safe to commit
git add group_vars/all/vault.yml && git commit -m "Add encrypted vault"
BASH — edit / view / rekey
# Open the encrypted file in $EDITOR — decrypt, edit, re-encrypt automatically
ansible-vault edit group_vars/all/vault.yml

# View without editing
ansible-vault view group_vars/all/vault.yml

# Decrypt (gives back plain text — be careful, don't commit!)
ansible-vault decrypt group_vars/all/vault.yml

# Change the vault password (re-encrypt with a new one)
ansible-vault rekey group_vars/all/vault.yml

# Inspect: which vault id encrypted this file?
head -1 group_vars/all/vault.yml
# $ANSIBLE_VAULT;1.2;AES256;production
#                          ^^^^^^^^^^ — the vault id
BASH — running with vault
# Prompt for password interactively
ansible-playbook site.yml --ask-vault-pass

# Read password from a file (NOT committed!)
ansible-playbook site.yml --vault-password-file ~/.ansible/vault_pass

# Read from a script that prints the password (great for CI / 1Password)
ansible-playbook site.yml --vault-password-file ./scripts/get_vault_pass.sh

# Configure default in ansible.cfg so you don't repeat the flag
echo "[defaults]
vault_password_file = ~/.ansible/vault_pass" >> ansible.cfg
ansible-playbook site.yml

Sometimes you want one secret inside an otherwise plain file. encrypt_string produces an encrypted YAML scalar you can paste anywhere:

BASH — encrypt a single string
# Generate an encrypted scalar
ansible-vault encrypt_string 'SuperSecret123!' --name 'mysql_root_password'

# Output (paste into any plain YAML file)
mysql_root_password: !vault |
          $ANSIBLE_VAULT;1.2;AES256;default
          61356638316563663...
          393633623761306...
          3263333766613664...
YAML — mixed plain + encrypted file
---
# group_vars/databases.yml — plain settings + ONE encrypted value
mysql_port: 3306
mysql_max_connections: 200
mysql_role: primary

# Just this one value is encrypted
mysql_root_password: !vault |
          $ANSIBLE_VAULT;1.2;AES256
          61356638316563663831...
          ...

A common pattern: dev, staging, and production each have their own vault password so a junior dev with the dev password can't decrypt prod secrets. Tag each encrypted file with a vault id:

BASH — multi-vault setup
# Encrypt with a named vault id
ansible-vault encrypt --vault-id dev@~/.vault_pass_dev    group_vars/all/vault_dev.yml
ansible-vault encrypt --vault-id prod@~/.vault_pass_prod  group_vars/all/vault_prod.yml

# Look at the headers — each file is tagged
head -1 group_vars/all/vault_dev.yml
# $ANSIBLE_VAULT;1.2;AES256;dev

head -1 group_vars/all/vault_prod.yml
# $ANSIBLE_VAULT;1.2;AES256;prod
BASH — running with multiple vaults
# Provide both vault passwords; Ansible auto-picks the right one per file
ansible-playbook site.yml \
  --vault-id dev@~/.vault_pass_dev \
  --vault-id prod@~/.vault_pass_prod

# Or set in ansible.cfg
[defaults]
vault_identity_list = dev@~/.vault_pass_dev, prod@~/.vault_pass_prod
GoalCommand
Encrypt a fileansible-vault encrypt FILE
Decrypt a fileansible-vault decrypt FILE
Edit in placeansible-vault edit FILE
Show plain contentansible-vault view FILE
Change passwordansible-vault rekey FILE
Encrypt one stringansible-vault encrypt_string 'val' --name 'key'
Run with promptansible-playbook --ask-vault-pass
Run with fileansible-playbook --vault-password-file FILE
Multi-vault run--vault-id dev@FILE --vault-id prod@FILE
✅ Tip: End of the encryption mechanics. Page 30 covers the operational side — git workflows, CI/CD secret rotation, and the discipline that keeps vault from becoming a liability.