Securely Accessing Ansible Vault in Development

Guideline for securely accessing Ansible Vault during development without storing passwords in plain files, using GNOME Keyring or environment variables.

Projects: c2platform/phx/ansible , c2platform.core


Problem

Developing and testing Ansible playbooks that use Ansible Vault requires providing the vault password repeatedly, which is cumbersome. Using a vault password file risks exposing sensitive information and is considered poor practice.

Context

In Ansible engineering work on projects that use an inventory project which includes a vault managed with Ansible Vault, you must provide the vault passphrase to avoid provisioning failures. You can do this with the --ask-vault-pass flag:

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

Alternatively, use --vault-password-file to specify a password file. For more details, see the Ansible documentation  .

If using a password file, ensure its permissions prevent unauthorized access, and never commit it to source control. However, storing vault passwords in files increases security risks, as mistakes can easily lead to leaks.

Solution

Use GNOME Keyring by default for storing the Ansible Vault password, as it is more secure and convenient. It stores the password encrypted in the user’s keyring, accessible across sessions with a GUI.

For SSH sessions without a GUI, use an environment variable PX_ANSIBLE_VAULT_PASSWORD as a fallback. Set the Ansible environment variable ANSIBLE_VAULT_PASSWORD_FILE to a script that echoes this variable. Note that ANSIBLE_VAULT_PASSWORD_FILE serves as an alternative to --vault-password-file. The “password file” can be either a plain text file or an executable script (e.g., Bash or Python) that outputs the password.

The password resides in memory only for the duration of the shell session, which is acceptable for most environments1.

Benefits

  • Enhances security by avoiding plaintext storage of sensitive passwords.
  • Improves convenience for developers, reducing repetitive password entry.
  • Supports both GUI and non-GUI access methods for flexibility in development environments.

Examples and Implementation

The inventory project  c2platform/phx/ansible includes an Ansible Vault-based vault (see folder  secret_vars). This approach is compatible with the Automation Controller (AWX) of Ansible Automation Platform (AAP), see Managing Secrets with Ansible Vault in AAP / AWX for more information. This inventory project contains the definition/configuration of an Ubuntu-based desktop pxd-ubuntu-devtop. The creation of this node is part of how-to Setting Up an Ansible Development Desktop .

Another how-to Set Up Ansible with Kerberos on a PHX Development Desktop simulates how an Ansible desktop is used within the PHX domain. It incorporates Kerberos and Ansible Vault in a secure manner using environment variables.

In the how-to, domain user “Tony” adds a bash function phx-vault-password to his ~/.bash_aliases and exports ANSIBLE_VAULT_PASSWORD_FILE. By default, the GNOME Keyring is used for secure storage, with a fallback to the environment variable if no GUI is available. This setup allows Tony to access the Ansible Vault securely on the desktop pxd-ubuntu-devtop.

Option 1: GNOME Keyring

On this desktop, Ansible creates the script vault-client-keyring.sh. The configuration responsible for creating this file is shown below:

 group_vars/ubuntu_devtop/main.yml

41        - dest: /usr/local/bin/vault-client-keyring.sh
42          content: |
43            #!/usr/bin/env bash
44            # vault-client-keyring.sh - print the Ansible Vault password from Secret Service (GNOME Keyring/libsecret)
45            #
46            # Usage:
47            #   1) Store password in keyring (attributes: ansible=vault):
48            #        Interactive:  secret-tool store --label="Ansible Vault Password" ansible vault
49            #        Non-interactive (stdin):  printf '%s' 'YOUR_PASSWORD' | secret-tool store --label="Ansible Vault Password" ansible vault
50            #   2) Use with Ansible:
51            #        ansible-playbook --vault-password-file /usr/local/bin/vault-client-keyring.sh play.yml
52            #      or set in ansible.cfg:  vault_password_file = /usr/local/bin/vault-client-keyring.sh
53            #
54            # Requirements:
55            #   - secret-tool (Debian/Ubuntu: package libsecret-tools; RHEL/Fedora: libsecret)
56            #   - A running/unlocked Secret Service (e.g., GNOME Keyring). On headless hosts a valid D-Bus session is required.
57            #
58            # Security:
59            #   - This script prints the password to stdout for Ansible; avoid running it manually unless needed.
60
61            set -o nounset -o pipefail
62
63            main() {
64              if ! command -v secret-tool >/dev/null 2>&1; then
65                echo "Error: secret-tool not found. Install libsecret-tools (Debian/Ubuntu) or libsecret (RHEL/Fedora)." >&2
66                exit 2
67              fi
68
69              # Lookup attributes; defaults: ansible=vault. Override via env: KEYRING_VAULT_ATTR_KEY / KEYRING_VAULT_ATTR_VAL
70              local attr_key="${KEYRING_VAULT_ATTR_KEY:-ansible}"
71              local attr_val="${KEYRING_VAULT_ATTR_VAL:-vault}"
72
73              # Fetch secret; suppress secret-tool stderr
74              local pw
75              if ! pw="$(secret-tool lookup "$attr_key" "$attr_val" 2>/dev/null)"; then
76                echo "Error: no secret found for ${attr_key}=${attr_val}. Store it first with 'secret-tool store'." >&2
77                exit 3
78              fi
79
80              if [ -z "${pw}" ]; then
81                echo "Error: secret is empty. Store a non-empty value." >&2
82                exit 4
83              fi
84
85              # Print without trailing newline; avoids accidental whitespace
86              printf '%s' "${pw}"
87            }
88
89            main "$@"

The script vault-client-keyring.sh uses secret-tool to retrieve the password from GNOME Keyring and outputs it for Ansible to use. This method is secure and persistent across sessions as long as the keyring is unlocked.

function phx-vault-password() {
    local pw=$(secret-tool lookup ansible vault 2>/dev/null)
    if [ -z "${pw}" ]; then
        echo "Password doesn't exist or is empty, lets add/set it!"
        pw=$(secret-tool store --label 'Ansible Vault Password' ansible vault >&2)
        echo "Vault password has been set." >&2
    else
        echo "Vault password is already set."
    fi
    export ANSIBLE_VAULT_PASSWORD_FILE=/usr/local/bin/vault-client-keyring.sh
}

With this approach, a user can set the password in their shell session using:

phx-vault-password

The output below shows the result of running the command:

(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ phx
phx-vault-password
Password doesn't exist or is empty, lets add/set it!
Password:
Vault password has been set.
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$

If you run the command for the first time, you are asked to set a password for the GNOME Keyring. The Ansible Vault password will be stored there for convenience (you don’t have to provide the password each time you use Ansible) and also security. It is a safe place. The screenshot below shows the GNOME Keyring prompt asking for password and password confirmation.

After that you can the use the vault without passphrase prompts for example as show below:

ansible-vault view secret_vars/development/main.yml
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ phx-vault-password
Enter Ansible Vault passphrase:
PX_ANSIBLE_VAULT_PASSWORD has been set for this shell session.
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ alias phx-vault
alias phx-vault='ansible-vault edit secret_vars/development/main.yml'
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ phx-vault
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-vault view secret_vars/development/main.yml
---
# ad
px_ad_admin_password: Supersecret!

# cacerts_server
px_cacerts2_ca_domain_passphrase: huhohleSh8Beis9

# vagrant ssh
px_vagrant_ssh_id_rsa: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn

Option 2: SSH (no GUI)

For environments without a GUI, such as SSH sessions, Ansible creates the script vault-client.sh. The configuration responsible for creating this file is shown below:

 group_vars/ubuntu_devtop/main.yml

23        - dest: /usr/local/bin/vault-client.sh
24          content: |
25            #!/bin/bash
26
27            # vault-client.sh
28            # This script is intended to be used as ANSIBLE_VAULT_PASSWORD_FILE.
29            # It checks if the environment variable PX_ANSIBLE_VAULT_PASSWORD is set.
30            # If set, it echoes the value (returns it).
31            # If not set, it outputs an error to stderr and exits with status 1.
32            # Use the set_vault_password function in your shell (e.g., from .bash_aliases.sh)
33            # to set the variable before running ansible-playbook.
34
35            if [ -z "${PX_ANSIBLE_VAULT_PASSWORD}" ]; then
36                echo "Error: PX_ANSIBLE_VAULT_PASSWORD is not set. Please set it using 'set_vault_password' in your shell session." >&2
37                exit 1
38            fi
39
40            echo "${PX_ANSIBLE_VAULT_PASSWORD}"

The script vault-client.sh checks for the environment variable PX_ANSIBLE_VAULT_PASSWORD and outputs it if set, providing a fallback for non-GUI access.

function phx-vault-password-env() {
    local password
    echo -n "Enter Ansible Vault passphrase: " >&2
    read -s password
    echo >&2  # Add a newline after the hidden input
    export PX_ANSIBLE_VAULT_PASSWORD="$password"
    echo "PX_ANSIBLE_VAULT_PASSWORD has been set for this shell session." >&2
    export ANSIBLE_VAULT_PASSWORD_FILE=/usr/local/bin/vault-client.sh
}

With this approach, a user can set the password in their shell session using:

phx-vault-password-env

And then view the vault without passphrase prompts using:

ansible-vault view secret_vars/development/main.yml
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ phx-vault-password-env
Enter Ansible Vault passphrase:
PX_ANSIBLE_VAULT_PASSWORD has been set for this shell session.
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ alias phx-vault
alias phx-vault='ansible-vault edit secret_vars/development/main.yml'
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ phx-vault
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-vault view secret_vars/development/main.yml
---
# ad
px_ad_admin_password: Supersecret!

# cacerts_server
px_cacerts2_ca_domain_passphrase: huhohleSh8Beis9

# vagrant ssh
px_vagrant_ssh_id_rsa: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn

If phx-vault-password-env is not used (and so PX_ANSIBLE_VAULT_PASSWORD is not set), this will result in an error2.

Note that if ANSIBLE_VAULT_PASSWORD_FILE is not set, this will result in a message3.

Additional Information



  1. This is acceptable but not ideal for highly sensitive environments. If someone compromises your session (e.g., via malware), they could dump env vars. For production/automation, consider integrating with a secret manager like HashiCorp Vault, AWS Secrets Manager, or pass instead of manual input. ↩︎

  2. If phx-vault-password-env is not used (and so PX_ANSIBLE_VAULT_PASSWORD is not set), this will result in an error:

    (pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-playbook plays/mgmt/ad.yml
    [WARNING]: Error in vault password file loading (default): Vault password
    client script /usr/local/bin/vault-client.sh returned non-zero (1) when getting
    secret for vault-id=default: b"Error: PX_ANSIBLE_VAULT_PASSWORD is not set.
    Please set it using 'set_vault_password' in your shell session.\n"
    ERROR! Vault password client script /usr/local/bin/vault-client.sh returned non-zero (1) when getting secret for vault-id=default: b"Error: PX_ANSIBLE_VAULT_PASSWORD is not set. Please set it using 'set_vault_password' in your shell session.\n"
    (pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$
    
     ↩︎
  3. Note that if ANSIBLE_VAULT_PASSWORD_FILE is not set, this will result in a message:

    (pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-playbook plays/mgmt/ad.yml | tee provision.log
    [WARNING]: Error getting vault password file (default): The vault password file
    /home/tony@c2.org/git/gitlab/c2/ansible-phx/vpass was not found
    ERROR! The vault password file /home/tony@c2.org/git/gitlab/c2/ansible-phx/vpass was not found
    

    This is because in the PHX Ansible inventory project c2platform/phx/ansible in ansible.cfg, there is a line with vault_password_file:

     ansible.cfg

    vault_password_file=vpass
    

    In inventory projects consumed by Ansible Automation Platform, this setting is typically not made. But in the open-source PHX development environment, which uses Vagrant, this file vpass is created by Vagrant as you can see in the Vagrantfile. As this is only an Ansible development environment, security is not a major concern; everything is open source, so the vault password is secret.

     Vagrantfile

    231# vpass file for Ansible vault secrets.yml
    232vpass_file = File.join(File.dirname(__FILE__), 'vpass')
    233File.open(vpass_file, 'w') { |f| f.write('secret') } unless File.exist? vpass_file
    
     ↩︎


Last modified November 19, 2025: guideline dev vault PHX-155 (94fc46e)