

The problem with Configuration as Code and secrets comes down to version control: playbooks go in Git, but API keys, passwords, and certificates cannot go there as plaintext. Ansible Vault solves this by encrypting secrets in place so they live alongside playbooks in your repository without exposure risk.
This post walks through Ansible Vault: how to encrypt files and variables, how to run playbooks with encrypted secrets, and the patterns that work in real CI/CD pipelines.
At a glance
Ansible Vault is the built-in encryption utility for ansible-core. Current version: ansible-core 2.20.5 (April 2025). Uses AES256 encryption. Works transparently withansible-playbook; no code changes required to use encrypted files alongside existing playbooks.
What is Ansible Vault
Ansible Vault is an encryption tool included with Ansible that protects secrets while enabling DevOps workflows. Ansible Vault uses AES256 encryption and integrates transparently with ansible-playbook, so existing workflows run without modification.
Ansible Vault is a utility included in Ansible that can encrypt and decrypt arbitrary data using a password. It can encrypt a variety of data using AES256 encryption, including:
- Structured YAML files, such as variable files or even entire playbooks
- Configuration files with sensitive information
- Individual variables in Ansible playbooks
Most importantly, Ansible Vault integrates transparently with other Ansible commands, such as ansible and ansible-playbook. These commands can automatically detect and decrypt encrypted data to use in standard Ansible workflows.
For example, an Ansible playbook can reference variables stored in an encrypted variable file. These files will automatically be decrypted at runtime using the appropriate password.
Password protection and encryption
Creating an encrypted file
At its most basic level, Ansible Vault can encrypt entire files with a password. For example, consider a situation where you want to store an API key as a variable in a YAML file. You can create the initial vault encrypted file using ansible-vault create:
ansible-vault create vars/secrets.ymlThe file will launch in your shell’s default editor, as controlled by the EDITOR environment variable. If no editor is set, it will default to vi. Create the file like any other text file and save it:
db_password: "s3cur3p@ssw0rd"
api_key: "sk-prod-abc123xyz"
smtp_password: "m@ilsecret42"Now, when you try to view the file, notice that it is an encrypted blob:
$ANSIBLE_VAULT;1.1;AES256
66663832333661323430363136303263646338396132306566643131326135613564353738633061
3232656266393531313036306533643161363531656637310a313237373932613665383235323032
36393437653636643362313162636562373063613963396434363035386339653163653465636561
6361633534386438390a393066326639663366656636363835326261363736303434366162306531
3837Viewing and editing encrypted files
You will frequently need to view the contents of vault-encrypted files or edit them directly. You can do this with the view and edit commands.
The view command displays the contents of the encrypted file:
ansible-vault view vars/secrets.ymlThe edit command launches an editor to modify the encrypted file using the shell’s default editor:
ansible-vault edit vars/secrets.ymlDecrypting an Encrypted File
Sometimes, you may want to fully decrypt a file. For example, you may determine that the data is no longer sensitive and doesn’t need to be protected as a secret.
You can fully decrypt a file using the decrypt command. This command fully removes the encrypted file and leaves only the decrypted file in place:
ansible-vault decrypt vars/secrets.ymlEncrypting an Existing File
Configuration as Code is frequently used to transfer sensitive configuration files to remote hosts. Ansible Vault can fully encrypt an existing file. For example, consider a configuration file with sensitive information in it:
[database]
host = db.internal.example.com
port = 5432
username = app_user
password = p@ssw0rd_prod_2024Ansible Vault can encrypt this entire file using a password with the encrypt command:
ansible-vault encrypt config/database.iniChanging the Encryption Key
It’s a security best practice to regularly rotate encryption material. This principle also applies to the passwords used to protect files encrypted with Ansible Vault.
Ansible Vault makes it easy to rotate the encryption key for a file using the rekey command. Simply provide it with the existing password and a new password:
ansible-vault rekey vars/secrets.yml
# Vault password: (enter current password)
# New Vault password: (enter new password)
# Confirm New Vault password: (confirm)
# Rekey successfulEncrypting Variables in a Playbook
The examples we have looked at so far encrypt entire files. This is the most common way to use Ansible Vault. However, there are also situations where you want to encrypt data within a playbook while leaving the rest of the playbook unencrypted.
Ansible Vault enables this pattern with the encrypt_string command. You can use encrypt_string to encrypt the contents of an arbitrary string and then place these contents in a playbook.
For example, consider a playbook that makes an HTTP request to a password-protected API endpoint:
---
- name: Query monitoring API
hosts: localhost
vars:
api_url: "https://api.monitoring.example.com/metrics"
api_key: "sk-plaintext-not-safe-in-vcs"
tasks:
- name: Fetch metrics
ansible.builtin.uri:
url: "{{ api_url }}"
headers:
Authorization: "Bearer {{ api_key }}"
return_content: true
register: metrics_responseWe want to protect this password using Ansible Vault, but we don’t want to encrypt the entire file. You can use encrypt_string to encrypt the API key:
ansible-vault encrypt_string --vault-password-file vault_pass.txt \
'sk-prod-abc123xyz' \
--name 'api_key'
# Output:
# api_key: !vault |
# $ANSIBLE_VAULT;1.1;AES256
# 34306566633636326639323836653161323836306633633265316566623764346436363838306631
# ...Notice that encrypt_string allows you to directly input the string you want to encrypt into the terminal. You end the string with CTRL+D, not with a newline character. This is important to remember, as any newlines you enter into the terminal will become part of the encrypted string.
Finally, you can insert this encrypted string directly into the playbook:
---
- name: Query monitoring API
hosts: localhost
vars:
api_url: "https://api.monitoring.example.com/metrics"
api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
34306566633636326639323836653161323836306633633265316566623764346436363838306631
6237616365303566653532346231623133306535633533310a353765386231363432383434616132
tasks:
- name: Fetch metrics
ansible.builtin.uri:
url: "{{ api_url }}"
headers:
Authorization: "Bearer {{ api_key }}"This approach is useful for very basic playbooks, but it has limitations. You must encrypt each string individually, which can be tedious and time-consuming. There's also no way to easily rekey all of the encrypted strings in a file. Instead, you must re-encrypt each string.
A better approach in most scenarios is to use a fully encrypted variable file and limit the use of encrypt_string. However, using encrypt_string can be helpful in very simple playbooks that don’t require the overhead of fully encrypted variable files.
Running Ansible Plays with Encrypted Files
By now, you should have a good understanding of how to use Ansible Vault to create and manipulate encrypted files and data. Ansible integrates transparently with Ansible Vault and allows you to use encrypted files and variables within your plays. Ansible automatically decrypts the encrypted data using the password that you provide.
To illustrate these principles, you can use a playbook that contains both encrypted variables and fully encrypted files:
---
- name: Deploy application
hosts: webservers
vars_files:
- vars/secrets.yml # AES256-encrypted variable file
tasks:
- name: Fetch data from monitoring API
ansible.builtin.uri:
url: "https://api.example.com/data"
headers:
Authorization: "Bearer {{ api_key }}"
register: api_response
- name: Deploy database config
ansible.builtin.copy:
src: config/database.ini # AES256-encrypted config file
dest: /etc/myapp/database.ini
mode: '0600'This playbook performs two tasks:
- Makes an HTTP request using the encrypted
api_keyvariable - Copies an encrypted configuration file to the remote host. This configuration file is created using
ansible-vault create
Next, it’s time to run the playbook. Ansible will automatically recognize data encrypted by Ansible Vault and decrypt it at the appropriate time. Ansible relies on a password to make this work. There are three main methods for providing Ansible with a password for decrypting protected data:
- Provide the password manually via the command line using
--ask-vault-pass. This is inappropriate for automated scenarios but works well when testing. - Reference a password file that contains the password with
--vault-password-file. This is the most common approach. This file should be carefully locked down to prevent exposing the password. - Look up the password using a script specified by
--vault-password-file. This is an advanced approach that is very useful when you want Ansible to interact with an external secret storage system, such as AWS Secrets Manager.
For this example, we will use a password file:
echo -n "your_vault_password" > vault_pass.txt
chmod 600 vault_pass.txt
echo "vault_pass.txt" >> .gitignoreWith everything in place, it’s time to run Ansible:
ansible-playbook site.yml -i inventory.ini --vault-password-file vault_pass.txtNotice that the ansible-playbook command transparently decrypts the necessary files and variables. This makes it easy to begin using encrypted secrets without disrupting existing automation workflows.
Advanced use cases
The basic features we have covered so far are enough for most scenarios. However, Ansible Vault also features several advanced usage patterns that are helpful for more complex environments.
Managing multiple vaults
Large environments frequently use multiple secrets with different permission levels. For example, a different set of secrets may be used for staging and production infrastructure. Operators may also choose to encrypt different files and variables using separate passwords.
Ansible Vault allows operators to work with multiple vaults, each uniquely identified by a vault ID. Vault IDs provide a “hint” to indicate the correct password to use when decrypting a vault file.
For example, consider a situation where you want to encrypt two different configuration files with different passwords. Ansible Vault enables this with the --vault-id flag. This flag takes its argument in the format of ID@SOURCE, where “ID” is the vault ID to use, and “SOURCE” is the location to find the vault password.
For example, you can encrypt two different files with different passwords provided via the command line prompt:
# Encrypt staging config with "staging" vault ID
ansible-vault encrypt --vault-id staging@prompt config/staging.ini
# Encrypt production config with "prod" vault ID
ansible-vault encrypt --vault-id prod@prompt config/production.iniNext, you can tell ansible-playbook about the appropriate place to obtain the password for each vault using the --vault-id flag. Notice that the password for the vault with ID “config1” is given at the prompt, while the password for the vault with ID “config2” is provided through a password file:
ansible-playbook site.yml -i inventory.ini \
--vault-id staging@prompt \
--vault-id prod@vault_prod_pass.txtThis approach provides great flexibility when using multiple passwords. However, it can quickly become complicated. You should still try to maintain simplicity when designing your password strategy.
It’s important to understand that vault IDs are just hints. Vault ID matching is not strictly enforced by Ansible unless you set the DEFAULT_VAULT_ID_MATCH environment variable. Ansible will try all provided passwords with all provided vaults until it succeeds or fails to decrypt a vault.
Integrating with a secrets manager
Storing an Ansible Vault password in a text file or entering it in the command line is appropriate for basic use cases, but advanced environments will typically use an external secrets storage solution. For example, your environment might use HashiCorp Vault, Amazon Web Service Secrets Manager, or your in-house solution.
Ansible makes it very easy to look up the decryption password for a vault with a client script. Client scripts can perform whatever logic is necessary to look up a vault’s password, including interacting with external secret managers. The script then prints the password to standard output, and Ansible uses this password to decrypt the Vault.
The example below uses the aws-secrets-manager-client.sh script to look up a vault password. The actual content and logic of this script isn’t important; all that matters is that the script prints the password to standard output for Ansible to use:
ansible-playbook site.yml -i inventory.ini \
--vault-id prod@./scripts/aws-secrets-manager-client.shUsing a client script provides the best of both worlds: You can encrypt files and variables in your Ansible playbooks and Configuration as Code repositories, and also integrate with external secrets managers to keep your Ansible Vault passwords safe.
Practical tips
Version control
A significant benefit of the Ansible Vault approach is the ability to store encrypted files and variables directly in your version control system. This avoids the need to store data in multiple places, providing you with a single source of truth for your Configuration as Code.
However, you must still ensure that any sensitive information, such as the password file for Ansible Vault, is stored outside of the version control system.
Environment variables and Ansible configuration
There are several Ansible configuration directives related to Ansible Vault. While you don’t need to know all of them, it is helpful to mention the most common directives that you will encounter:
DEFAULT_VAULT_ID_MATCH: This environment variable controls vault ID matching. By default, Ansible will not enforce strict ID matching and will try every password with all vaults. Set this variable to “True” to change this behavior.DEFAULT_VAULT_PASSWORD_FILE: This environment variable specifies the default vault password file.DEFAULT_VAULT_IDENTITY_LIST: This environment variable is equivalent to specifying multiple--vault-idflags, and it can be useful for shortening the length of youransible-playbookcommands.
Understanding when files are decrypted
Ansible will decrypt files as needed when running plays, and the files will remain encrypted at rest once the play has been completed. However, files will be decrypted at rest on a target host when they are used as the src argument to the copy, template, unarchive, script, or assemble module.
This is intended and desirable behavior. It allows you to decrypt a file and place it on a remote host. For example, you can reference an encrypted configuration file in Ansible’s copy module and it will be decrypted and placed onto a remote host.
While this behavior may seem obvious, it's important to understand the scenarios when Ansible will leave a file decrypted at rest.
Integrating Ansible with env0
env0 includes native support for Ansible, enabling you to use your existing playbooks alongside its infrastructure lifecycle management capabilities. With Ansible templates, you can consistently deploy environments while leveraging env0's features like controlled access, cost estimation, and automated deployment flows. Learn more here.
Ansible Vault in practice
Protecting sensitive data while still enabling Configuration as Code best practices is a challenge for DevOps teams of any size. It is one of the earliest challenges faced by organizations when they automate their configuration management practices, and it continues to challenge mature teams. The right approach is flexible enough to preserve velocity without compromising on security.
Ansible Vault is an ideal solution for teams already running Ansible in their automation workflows. It has a very low entry barrier, and its basic and advanced features make it appropriate for a variety of scenarios. Simple environments can benefit from encrypted vaults with basic password authentication. Advanced environments with complex needs can tier their vaults using vault IDs and externally stored vault passwords with frequent rotation.
Ansible Vault is a focused utility that provides strong secrets protection across a variety of scenarios. It is an important component of any Ansible environment’s security posture.
Frequently asked questions
Q. What is Ansible Vault?
Ansible Vault is a utility for encrypting secrets. Secrets can include variables inside Ansible playbooks, external variable files, or even arbitrary data. Ansible Vault integrates transparently with other Ansible tools, such as the ansible-playbook command. These Ansible tools can automatically decrypt and use secrets in playbooks and Ansible commands.
Q. Is Ansible Vault just for encrypting Ansible playbooks?
No. Ansible Vault can also encrypt arbitrary files, such as sensitive configuration files. Ansible can automatically decrypt these files as necessary, such as when they are transferred to a remote host.
Q. How is Ansible Vault different from an external secrets manager, such as AWS Secrets Manager?
Ansible Vault is built directly into Ansible and doesn’t require any additional modules or external infrastructure to work. It directly encrypts files using a shared key. External secrets managers exist outside of Ansible and require their own configuration, tooling, and modules to work with Ansible.
Q. Can you integrate Ansible Vault with an external secrets manager?
Yes. Ansible Vault uses a shared secret password to encrypt and decrypt secrets. This password can be stored in an external secrets manager. Ansible can look up this password in an external secrets manager at runtime using a client script.
.avif)
.webp)

![Using Open Policy Agent (OPA) with Terraform: Tutorial and Examples [2026]](https://cdn.prod.website-files.com/63eb9bf7fa9e2724829607c1/69d6a3bde2ffe415812d9782_post_th.png)