$linuxjunkies
>

Manage Secrets with Ansible Vault

Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • Ansible 2.8 or later installed on the control node
  • An existing Ansible project with at least one playbook and inventory
  • Basic familiarity with YAML variable files and group_vars layout

Hardcoding passwords, API keys, and certificates in Ansible playbooks is a fast path to a credentials leak. Ansible Vault encrypts sensitive data at rest using AES-256 so secrets travel safely in version control. This guide covers encrypting individual files and variables, using password files for automation, and organizing group-level secrets that different teams or environments need separately.

How Ansible Vault Works

Vault encrypts any YAML or arbitrary file with a symmetric AES-256-CBC key derived from a password you supply. The encrypted blob is valid YAML, so it can live inside a vars file, a host_vars directory, or inline with !vault tagged strings. Ansible decrypts transparently at runtime when you pass the password. You can maintain multiple vault IDs—useful when separate teams own separate secrets.

Prerequisites and Installation

Ansible Vault is bundled with Ansible core; no extra package is needed. Verify your version first, since vault IDs require Ansible 2.4+ and the --encrypt-vault-id flag requires 2.8+.

ansible --version

Install or upgrade if needed:

# Debian / Ubuntu
sudo apt update && sudo apt install ansible

# Fedora / RHEL / Rocky
sudo dnf install ansible

# Arch
sudo pacman -S ansible

# Any distro — latest via pip (recommended for current releases)
pip install --upgrade ansible

Encrypting a File

The most straightforward use is encrypting an entire variable file. Create a plain YAML secrets file, then encrypt it in place.

cat > group_vars/production/vault.yml << 'EOF'
db_password: "s3cur3P@ssword"
api_key: "abc123secretkey"
EOF
ansible-vault encrypt group_vars/production/vault.yml

Vault prompts for a new password and confirmation. The file becomes a block starting with $ANSIBLE_VAULT;1.1;AES256. Commit it to git safely—without the password it is useless.

Editing, Viewing, and Decrypting

View without decrypting to disk

ansible-vault view group_vars/production/vault.yml

Edit in place

Vault decrypts to a temp file, opens your $EDITOR, then re-encrypts on save. Set your preferred editor if needed.

EDITOR=nano ansible-vault edit group_vars/production/vault.yml

Decrypt permanently

Only do this locally when you need to inspect or migrate the file. Never leave decrypted secrets on shared hosts.

ansible-vault decrypt group_vars/production/vault.yml

Re-key: change the vault password

ansible-vault rekey group_vars/production/vault.yml

Running Playbooks with Vault-Encrypted Files

Pass the password interactively during a run:

ansible-playbook site.yml --ask-vault-pass

For automated pipelines use a password file instead of interactive prompts.

Using a Password File

A password file contains exactly one line: the vault password, no trailing newline is necessary but harmless. Lock it down hard.

echo 'MyVaultPassword123!' > ~/.vault_pass
chmod 600 ~/.vault_pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass

To avoid repeating the flag, set it in ansible.cfg:

cat >> ansible.cfg << 'EOF'
[defaults]
vault_password_file = ~/.vault_pass
EOF

In CI/CD pipelines, inject the password as an environment variable and use a script that prints it:

cat > vault_pass_script.sh << 'EOF'
#!/bin/sh
echo "$VAULT_PASSWORD"
EOF
chmod 700 vault_pass_script.sh
ansible-playbook site.yml --vault-password-file ./vault_pass_script.sh

Encrypting Individual Variables (Inline Vault)

When only one or two values in a file are sensitive, encrypt just those strings. This keeps most of the file human-readable.

ansible-vault encrypt_string 's3cur3P@ssword' --name 'db_password'

Output looks like:

db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  66386134306565383338353534...

Paste the entire block, including the !vault | tag, into any variable file. Ansible decrypts it at task execution time.

Group-Level Secrets with Multiple Vault IDs

Large environments often need different teams to own different secrets. Vault IDs let you label encrypted content and supply the matching password at runtime without exposing other vaults.

Create vaults with named IDs

# Encrypt the production secrets with the 'prod' ID
ansible-vault encrypt --vault-id prod@prompt group_vars/production/vault.yml

# Encrypt staging secrets with the 'staging' ID
ansible-vault encrypt --vault-id staging@prompt group_vars/staging/vault.yml

Run providing both passwords

ansible-playbook site.yml \
  --vault-id prod@~/.vault_pass_prod \
  --vault-id staging@~/.vault_pass_staging

Each password file is only known to the team responsible for that tier. A developer with only ~/.vault_pass_staging cannot decrypt production secrets.

group_vars/
  production/
    vars.yml        # plain variables
    vault.yml       # vault-encrypted (vault-id: prod)
  staging/
    vars.yml
    vault.yml       # vault-encrypted (vault-id: staging)
host_vars/
  db-primary.example.com/
    vault.yml       # host-specific secrets

The convention of separating vars.yml (readable) from vault.yml (encrypted) makes code reviews practical—reviewers see variable names without touching secrets.

Verification

Confirm encryption is intact and the password works before committing:

ansible-vault view group_vars/production/vault.yml --vault-password-file ~/.vault_pass

Run a syntax check against your playbook to ensure Ansible can decrypt and parse all vars:

ansible-playbook site.yml --syntax-check --vault-password-file ~/.vault_pass

Grep for any accidental plaintext secrets before pushing:

grep -r 'ANSIBLE_VAULT' group_vars/ host_vars/

Every file that should be encrypted will match. Anything that doesn't appear in this output but contains a password is a problem.

Troubleshooting

  • ERROR! Decryption failed (no vault secrets would unlock): The supplied password is wrong, or you forgot to pass --vault-id for a labeled vault. Double-check which ID was used during encryption.
  • Playbook hangs waiting for vault password: You have encrypted vars but no --ask-vault-pass or password file configured. Set vault_password_file in ansible.cfg.
  • ansible-vault edit opens vi unexpectedly: Set export EDITOR=nano (or your preferred editor) in your shell profile.
  • Encrypted file committed but others can't decrypt: Team members need the password out-of-band (a secrets manager like HashiCorp Vault, a shared password manager, or a CI/CD secret). The vault password itself is never committed to git.
  • Mixed vault IDs in a single run fail: You must supply a --vault-id flag for every distinct ID used across all encrypted files loaded in that play. Use password files rather than @prompt in automation to avoid interactive blocking.
tested on:Ubuntu 24.04Fedora 40Rocky 9Arch rolling

Frequently asked questions

Can I store the vault password inside the repository?
No. The vault password must be distributed out-of-band—through a secrets manager, CI/CD environment variable, or a shared password manager. Committing it defeats the entire purpose of encryption.
What is the difference between encrypting a whole file and using encrypt_string?
Encrypting a whole file hides every value in it, making diffs in code review uninformative. encrypt_string encrypts only the sensitive value and leaves variable names visible, which is better for reviewability but requires more care to not miss a sensitive field.
Does Ansible Vault protect secrets in memory or only at rest?
Vault only protects secrets at rest and in transit in the repository. During playbook execution, decrypted values exist in memory on the control node and may appear in verbose output or log files if you use -vvv or log_path.
How do vault IDs differ from using separate password files without IDs?
Without IDs, Ansible tries every supplied password against every encrypted blob, which works but is slow and error-prone at scale. Vault IDs tag each encrypted object so Ansible immediately knows which password to try, and they enforce access separation by environment or team.
Can I use Ansible Vault with HashiCorp Vault or AWS Secrets Manager?
Yes. Write a vault password script that fetches the password from your external secrets manager at runtime, then pass it with --vault-password-file ./your_script.sh. This combines Vault's encryption with centralized secret rotation.

Related guides