BlogSecrets

Ansible Vault vs HashiCorp Vault: which secret goes where

One encrypts files in your repo, the other serves secrets at runtime. Most teams need both — here is the split that works.

Sep 23, 2025·7 min readBeginner

Two tools, the same word in the name, completely different jobs. Ansible Vault encrypts files at rest so a secret can live safely in your Git repo. HashiCorp Vault is a running server that hands out secrets at runtime, leased and audited. Confuse them and you either commit plaintext to Git or stand up a cluster to hold one API key.

Same word, different jobs
Ansible Vault
Encrypts files at rest
Lives in your Git repo
One shared passphrase
Static secrets for a play
Decrypts in memory at run
HashiCorp Vault
Serves secrets at runtime
A running server / cluster
Per-identity auth + policy
Dynamic, leased, rotated
Central audit trail

Ansible Vault: secrets that ship with the play

Ansible Vault encrypts a vars file with a passphrase. The ciphertext is safe to commit, and Ansible decrypts it in memory when the playbook runs. It's the right tool for the handful of static secrets a playbook needs to bootstrap a host.

bash — ansible-vaultlive
ansible-vault encrypt group_vars/prod/secrets.yml
New Vault password: ********
Encryption successful
 
head -2 group_vars/prod/secrets.yml
$ANSIBLE_VAULT;1.1;AES256
39396264613966... (ciphertext — safe to commit)
playbook.yml
# group_vars/prod/secrets.yml is ansible-vault encrypted
- hosts: prod
tasks:
- name: write app config
template:
src: app.conf.j2 # references {{ db_password }}
dest: /etc/app.conf # decrypted only in memory, at run time

Supply the passphrase at run time — interactively, or from a 0600 file in CI that is never committed:

run.sh
ansible-playbook playbook.yml --ask-vault-pass
# in CI, from a locked-down file:
ansible-playbook playbook.yml --vault-password-file .vault-pass

HashiCorp Vault: secrets that live elsewhere

When secrets must rotate, differ per environment, or be revoked centrally, they don't belong in your repo at all. Ansible can look them up from HashiCorp Vault at run time, so nothing sensitive is ever stored with the playbook.

playbook.yml
- hosts: prod
vars:
db_password: "{{ lookup('community.hashi_vault.hashi_vault',
'secret=database/creds/app:password') }}"
tasks:
- name: run migration with a freshly-leased credential
command: ./migrate.sh
environment:
DB_PASS: "{{ db_password }}"
The passphrase is the whole model
An ansible-vault file is only as safe as its passphrase. Never commit the --vault-password-file, keep it out of shell history, and rotate (re-key every file) the moment you suspect it leaked — the ciphertext in Git history does not un-leak.

Which secret goes where

The rule of thumb: if the secret is static and small and needs to travel with the playbook — a bootstrap token, a registry pull password — reach for Ansible Vault. If it should rotate, expire, or be audited centrally — database creds, cloud keys, anything production-critical — put it in HashiCorp Vault and look it up. Most teams run both, and that's correct, not redundant.

Go deeper in a courseSecrets management foundationsWhere secrets actually belong — at rest, in transit, and at runtime.View course

Related posts