Free tech learning for everyone, from basics to pro

AnsibleProgramming and Application SecurityIntermediate

Ansible Vault and handling secrets

In short: Ansible Vault encrypts secrets such as device passwords and API tokens so they can sit safely in Git. Playbooks decrypt them in memory at run time using a vault password, which itself must be protected. For larger teams, an external secret manager is often better still.

The problem Vault solves

Automation needs credentials: SSH passwords, enable secrets, SNMPv3 keys, API tokens. Storing them in plain text in group_vars means anyone who can read the repository, or any backup of it, can log in to your network. Ansible Vault encrypts these values with AES-256 so the files can be committed safely, and decrypts them only in memory while a playbook runs.

How Vault protects a secretPlain secretin a vars fileEncryptansible-vaultCommitciphertext inGitRunsupply vaultpasswordDecryptin memory only
Figure 1. Vault keeps secrets encrypted at rest and in Git; they are decrypted in memory only when a playbook runs.

Core commands

ansible-vault create group_vars/switches/vault.yml   # new encrypted file
ansible-vault edit   group_vars/switches/vault.yml   # edit in your $EDITOR
ansible-vault view   group_vars/switches/vault.yml
ansible-vault encrypt existing_secrets.yml
ansible-vault rekey  group_vars/switches/vault.yml   # change the vault password

# encrypt a single value to paste into a vars file
ansible-vault encrypt_string --stdin-name 'vault_snmp_auth_key'

# run a playbook that uses vaulted data
ansible-playbook -i inventory.yml site.yml --ask-vault-pass

The --stdin-name form reads the secret from standard input, so it does not appear in your shell history.

A clean layout: vars plus vault

Vault optionsEncrypted fileWhole vars file encryptedansible-vault editHard to see what changedGood for many secretsEncrypted stringOne value inlineansible-vault encrypt_stringRest of file readableGood for a few secrets
Figure 2. Encrypt a whole file or individual values; many teams pair a readable vars file with a vaulted secrets file.

A widely used pattern turns group_vars/switches into a folder with two files. The readable file refers to variables that live in the encrypted one, so reviewers can still see which variables exist without seeing their values.

# group_vars/switches/vars.yml  (plain text)
ansible_user: netops
ansible_password: "{{ vault_ansible_password }}"
snmp_auth_key: "{{ vault_snmp_auth_key }}"

# group_vars/switches/vault.yml  (encrypted with ansible-vault)
vault_ansible_password: <set-with-ansible-vault-edit>
vault_snmp_auth_key: <set-with-ansible-vault-edit>

Use vault IDs to separate environments, for example --vault-id lab@prompt --vault-id prod@~/.vault_prod_pass, so lab engineers never hold the production vault password.

Protecting secrets at run time

  • The vault password is the new crown jewel. Do not commit it. If you use a password file, restrict it with chmod 600, or use a script that fetches it from a password manager.
  • Hide output. Add no_log: true to tasks that handle secrets so values are not printed in output or logged by AWX.
  • Prefer keys. SSH keys or certificates for automation accounts remove the need to store many device passwords at all.
  • Least privilege. Give the automation account only the privilege level it needs, and log its sessions through TACACS+ or RADIUS.
ApproachStrengthsWatch out for
Ansible VaultBuilt in, works offline, simpleSharing and rotating the vault password
External manager (HashiCorp Vault, CyberArk, Azure Key Vault, AWS Secrets Manager)Central audit, rotation, short-lived credentialsExtra infrastructure; lookup plugins needed
AWX / automation controller credentialsSecrets stored encrypted in the controller, never shown to usersController itself must be well secured

If a secret was ever committed in plain text, encrypting it now is not enough: the old value is still in Git history. Rotate the credential on the devices, then encrypt the new one.

Tip: add a pre-commit hook or CI check that fails if any file named vault.yml is not encrypted, so a mistake never reaches the shared repository.

Practice

Why keep a plain vars.yml alongside an encrypted vault.yml?
Reviewers can see which variables exist and how they are used, while the secret values stay encrypted.
What does no_log: true do?
It stops Ansible printing or logging the task's arguments and results, preventing secrets appearing in output.
A password was committed in plain text last month. Is running ansible-vault encrypt on the file now enough?
No. The old value remains in Git history, so the password must be changed on the devices and the new one stored encrypted.

Key takeaways

  • Ansible Vault encrypts secrets so they can be stored in Git.
  • Use a readable vars file pointing to vault_ variables in an encrypted file.
  • Protect the vault password and separate environments with vault IDs.
  • Use no_log on tasks that handle secrets.
  • Rotate any secret that was ever exposed in plain text.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.