Configure Ansible Vault for secret management and encryption with playbook automation

Intermediate 25 min Apr 21, 2026 618 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up Ansible Vault to encrypt sensitive data like passwords, API keys, and certificates in your playbooks. Learn to create encrypted variables, manage vault passwords, and integrate secure secret handling into automated deployments.

Prerequisites

  • Linux server with sudo access
  • Basic Ansible knowledge
  • SSH key access to target hosts

What this solves

Ansible Vault encrypts sensitive data in your playbooks and variable files, preventing passwords, API keys, and certificates from being stored in plain text. This tutorial shows you how to create encrypted variables, manage vault passwords securely, and integrate vault-protected secrets into your automation workflows.

Step-by-step configuration

Install Ansible and required tools

Start by installing Ansible and the tools needed for vault operations.

sudo apt update
sudo apt install -y ansible python3-pip
pip3 install ansible-vault
sudo dnf update -y
sudo dnf install -y ansible python3-pip
pip3 install ansible-vault

Create a vault password file

Create a secure password file that Ansible will use to encrypt and decrypt vault data. Store this outside your project directory.

mkdir -p ~/.ansible/vault
echo 'your-strong-vault-password-here' > ~/.ansible/vault/password
chmod 600 ~/.ansible/vault/password
Security: Use a strong password (minimum 20 characters) and never commit this file to version control. Consider using a password manager to generate and store the vault password.

Configure Ansible to use the vault password file

Set up Ansible configuration to automatically use your vault password file for encryption operations.

[defaults]
vault_password_file = ~/.ansible/vault/password
host_key_checking = False
inventory = inventory.ini

[ssh_connection]
ssh_args = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

Create your first encrypted variables file

Create a variables file with encrypted sensitive data like database passwords and API keys.

ansible-vault create group_vars/all/vault.yml

This opens your default editor. Add your encrypted variables:

---
vault_mysql_root_password: "MySecureP@ssw0rd123"
vault_api_key: "sk-1234567890abcdef"
vault_ssl_private_key: |
  -----BEGIN PRIVATE KEY-----
  MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7
  -----END PRIVATE KEY-----
vault_database_url: "postgresql://user:password@localhost:5432/mydb"

Create a public variables file for non-sensitive data

Create a companion file for non-encrypted variables that reference the vault variables.

---
mysql_root_password: "{{ vault_mysql_root_password }}"
api_key: "{{ vault_api_key }}"
ssl_private_key: "{{ vault_ssl_private_key }}"
database_url: "{{ vault_database_url }}"

# Non-sensitive configuration
mysql_port: 3306
api_endpoint: "https://api.example.com"
ssl_cert_path: "/etc/ssl/certs/example.com.crt"
ssl_key_path: "/etc/ssl/private/example.com.key"

Create an inventory file

Set up your inventory with target hosts for the playbook.

[webservers]
web1 ansible_host=203.0.113.10 ansible_user=ubuntu
web2 ansible_host=203.0.113.11 ansible_user=ubuntu

[databases]
db1 ansible_host=203.0.113.20 ansible_user=ubuntu

[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa

Create a playbook that uses encrypted variables

Build a playbook that demonstrates how to use vault-encrypted secrets in real automation tasks.

---
- name: Deploy application with encrypted secrets
  hosts: webservers
  become: yes
  vars_files:
    - group_vars/all/vars.yml
    - group_vars/all/vault.yml
  
  tasks:
    - name: Install required packages
      package:
        name:
          - nginx
          - mysql-client
          - python3-mysqldb
        state: present
    
    - name: Create application user
      user:
        name: appuser
        shell: /bin/bash
        home: /opt/myapp
        system: yes
    
    - name: Create SSL certificate directory
      file:
        path: /etc/ssl/private
        state: directory
        mode: '0700'
        owner: root
        group: root
    
    - name: Deploy SSL private key from vault
      copy:
        content: "{{ ssl_private_key }}"
        dest: "{{ ssl_key_path }}"
        mode: '0600'
        owner: root
        group: root
      notify: restart nginx
    
    - name: Create application configuration
      template:
        src: app.conf.j2
        dest: /opt/myapp/config.yml
        mode: '0640'
        owner: appuser
        group: appuser
      notify: restart application
    
    - name: Test database connection with encrypted credentials
      mysql_db:
        name: testdb
        login_host: "{{ database_url.split('@')[1].split(':')[0] }}"
        login_user: "{{ database_url.split('//')[1].split(':')[0] }}"
        login_password: "{{ database_url.split(':')[2].split('@')[0] }}"
        state: present
      delegate_to: "{{ groups['databases'][0] }}"
      run_once: true
  
  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted
        enabled: yes
    
    - name: restart application
      systemd:
        name: myapp
        state: restarted
        enabled: yes

Create the application configuration template

Create a Jinja2 template that uses encrypted variables securely.

mkdir -p templates
---
api:
  endpoint: "{{ api_endpoint }}"
  key: "{{ api_key }}"
  timeout: 30

database:
  url: "{{ database_url }}"
  pool_size: 10
  timeout: 5000

ssl:
  certificate: "{{ ssl_cert_path }}"
  private_key: "{{ ssl_key_path }}"
  protocols: ["TLSv1.2", "TLSv1.3"]

logging:
  level: INFO
  file: /var/log/myapp.log

Set up environment-specific vault files

Create separate vault files for different environments to manage secrets per stage.

mkdir -p group_vars/production group_vars/staging
ansible-vault create group_vars/production/vault.yml
ansible-vault create group_vars/staging/vault.yml

Add environment-specific secrets to each file:

---
vault_mysql_root_password: "Pr0d-MySecureP@ssw0rd123"
vault_api_key: "sk-prod-1234567890abcdef"
vault_database_url: "postgresql://produser:prodpass@prod-db:5432/proddb"

Create a vault management script

Build a helper script to manage vault operations across your infrastructure.

#!/bin/bash

VAULT_PASSWORD_FILE="~/.ansible/vault/password"

case "$1" in
    "encrypt")
        if [ -z "$2" ]; then
            echo "Usage: $0 encrypt 
chmod +x vault-manager.sh

Run the playbook with encrypted variables

Execute your playbook and verify that encrypted secrets are properly decrypted and used.

ansible-playbook deploy-secure-app.yml --limit webservers --check

Run the actual deployment:

ansible-playbook deploy-secure-app.yml --limit webservers

Configure multiple vault password files

Set up different vault passwords for different environments or teams.

mkdir -p ~/.ansible/vault/environments
echo 'production-vault-password-123' > ~/.ansible/vault/environments/production
echo 'staging-vault-password-456' > ~/.ansible/vault/environments/staging
chmod 600 ~/.ansible/vault/environments/*

Use environment-specific passwords:

ansible-playbook deploy-secure-app.yml --vault-password-file ~/.ansible/vault/environments/production --limit production
ansible-playbook deploy-secure-app.yml --vault-password-file ~/.ansible/vault/environments/staging --limit staging

Advanced vault security practices

Set up vault ID labels for multiple encryption keys

Use vault IDs to manage multiple encryption keys within the same playbook infrastructure.

ansible-vault create --vault-id production@~/.ansible/vault/environments/production group_vars/production/vault.yml
ansible-vault create --vault-id staging@~/.ansible/vault/environments/staging group_vars/staging/vault.yml

Run playbooks with specific vault IDs:

ansible-playbook deploy-secure-app.yml --vault-id production@~/.ansible/vault/environments/production --limit production

Create encrypted strings for inline use

Encrypt individual strings for use directly in playbooks without separate files.

ansible-vault encrypt_string 'MySecretPassword123' --name 'admin_password'

This outputs encrypted data you can paste directly into playbooks:

---
- name: Deploy with inline encrypted variables
  hosts: all
  vars:
    admin_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66633939373737386264323233343734346138663639373566353930643238336
          3666373865336435353561323637363138656533373263650a373834646466316
          63303138653738636666333034356462363661336565353235626562313633626
          6662623865653635353864653237343739333363386536310a626436313461363
  tasks:
    - name: Debug encrypted variable
      debug:
        msg: "Admin password is {{ admin_password }}"

Set up automated vault password rotation

Create a script to rotate vault passwords and re-encrypt files with new keys.

#!/bin/bash

OLD_PASSWORD_FILE="~/.ansible/vault/password.old"
NEW_PASSWORD_FILE="~/.ansible/vault/password.new"
CURRENT_PASSWORD_FILE="~/.ansible/vault/password"

# Generate new password
echo "$(openssl rand -base64 32)" > "$NEW_PASSWORD_FILE"
chmod 600 "$NEW_PASSWORD_FILE"

# Backup current password
cp "$CURRENT_PASSWORD_FILE" "$OLD_PASSWORD_FILE"

# Find all vault files and rekey them
find . -name "*.yml" -exec grep -l "\$ANSIBLE_VAULT" {} \; | while read vault_file; do
    echo "Rekeying $vault_file..."
    ansible-vault rekey "$vault_file" \
        --vault-password-file="$CURRENT_PASSWORD_FILE" \
        --new-vault-password-file="$NEW_PASSWORD_FILE"
done

# Update current password file
cp "$NEW_PASSWORD_FILE" "$CURRENT_PASSWORD_FILE"

echo "Vault password rotation completed"
echo "Old password backed up to $OLD_PASSWORD_FILE"
echo "Remember to update CI/CD systems with new password"
chmod +x rotate-vault-password.sh

Verify your setup

# Test vault file creation and encryption
ansible-vault view group_vars/all/vault.yml

# Verify playbook syntax with vault variables
ansible-playbook deploy-secure-app.yml --syntax-check

# Test variable resolution without running tasks
ansible-playbook deploy-secure-app.yml --list-tasks

# Check that encrypted files are properly encrypted
cat group_vars/all/vault.yml

# Verify vault operations work
./vault-manager.sh view group_vars/all/vault.yml

You should see encrypted content starting with $ANSIBLE_VAULT;1.1;AES256 when viewing raw files, and decrypted content when using vault commands.

Integration with CI/CD pipelines

For automated deployments, set up vault password management in your CI/CD system. Store the vault password as an encrypted environment variable and write it to a temporary file during pipeline execution.

deploy:
  stage: deploy
  script:
    - echo "$ANSIBLE_VAULT_PASSWORD" > /tmp/vault_password
    - chmod 600 /tmp/vault_password
    - ansible-playbook deploy-secure-app.yml --vault-password-file /tmp/vault_password
    - rm -f /tmp/vault_password
  variables:
    ANSIBLE_HOST_KEY_CHECKING: "false"
  only:
    - main

Similar patterns work for GitHub Actions, Jenkins, and other CI/CD platforms. Always clean up temporary password files and use encrypted secrets storage provided by your platform.

Common issues

SymptomCauseFix
ERROR! Decryption failedWrong vault passwordCheck password file path and content with ansible-vault view
Vault password file not foundIncorrect path in ansible.cfgUpdate vault_password_file path or use --vault-password-file
Variables not resolvingVault file not included in vars_filesAdd vault.yml to vars_files section in playbook
Permission denied on password fileWrong file permissionsSet correct permissions: chmod 600 ~/.ansible/vault/password
Vault ID not foundMissing vault-id parameterUse --vault-id label@password_file when multiple IDs exist
Cannot edit vault fileNo EDITOR environment variableSet EDITOR: export EDITOR=nano or export EDITOR=vim

Next steps

Running this in production?

Want this handled for you? Setting up Ansible Vault once is straightforward. Keeping it patched, monitored, backed up and tuned across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Nie chcesz zarządzać tym samodzielnie?

Zarządzamy infrastrukturą firm, które zależą od dostępności. W pełni zarządzana, z jednym stałym kontaktem, który zna Twoje środowisko.

Macie jednego stałego opiekuna, który zna Waszą konfigurację

Rotterdam 13:03 · dostępny w wiadomości, bez formularza zgłoszeń