--- title: "Cómo gestionar secretos con Ansible Vault en Ubuntu 24.04" description: "Cifra contraseñas y claves con Ansible Vault: archivos y variables cifradas, vault IDs por entorno, archivos de contraseña y uso seguro en playbooks y en CI/CD." category: "Automatización e IaC" language: es source: https://cubepath.com/es/docs/automatización-e-iac/ansible-vault-para-gestion-de-secretos updated: 2026-09-25 --- # Cómo gestionar secretos con Ansible Vault en Ubuntu 24.04 Ansible Vault cifra con AES256 archivos y variables que contienen datos sensibles (contraseñas, tokens de API, claves privadas) para que puedas guardarlos en Git junto al resto del proyecto. Ansible los descifra en memoria al ejecutar el playbook, siempre que le proporciones la contraseña de la bóveda. En este tutorial cifrarás un archivo de variables, cifrarás valores sueltos, separarás las contraseñas por entorno con vault IDs y usarás los secretos en un playbook sin exponerlos en la salida. ## Requisitos previos Necesitas: - Una máquina de control con Ubuntu 24.04 LTS, por ejemplo tu equipo o un VPS de CubePath, con un usuario no root con `sudo`. - Conocimientos básicos de playbooks e inventarios de Ansible. Los ejemplos se ejecutan contra `localhost`, así que no necesitas servidores gestionados para seguir la guía. ## Paso 1: Instalar Ansible y preparar el proyecto Ubuntu 24.04 incluye Ansible en el repositorio `universe`, y `ansible-vault` forma parte del mismo paquete: ```bash sudo apt update sudo apt install ansible ``` Comprueba la versión: ```bash ansible-vault --version ``` ```output ansible-vault [core 2.16.x] ... ``` Crea un directorio de proyecto con la estructura habitual de variables por grupo: ```bash mkdir -p ~/vault-demo/group_vars/all cd ~/vault-demo ``` Todos los comandos siguientes se ejecutan desde `~/vault-demo`. ## Paso 2: Crear un archivo cifrado La forma más cómoda de empezar es crear el archivo ya cifrado. `ansible-vault create` pide una contraseña, abre tu editor y cifra el contenido al guardar, de modo que el texto plano nunca se escribe en disco: ```bash EDITOR=nano ansible-vault create group_vars/all/vault.yml ``` Introduce la contraseña de la bóveda dos veces y escribe las variables. Usa el prefijo `vault_` para que se vea claramente qué valores están cifrados: ```yaml vault_db_password: your_strong_password vault_api_token: your_api_token ``` Guarda y sal. Comprueba que en disco solo hay texto cifrado: ```bash cat group_vars/all/vault.yml ``` ```output $ANSIBLE_VAULT;1.1;AES256 62336534643966346337623835363961376664393336356561633061643736353365376537653937 ... ``` Para trabajar con el archivo usa estos comandos, que siempre piden la contraseña: ```bash ansible-vault view group_vars/all/vault.yml ansible-vault edit group_vars/all/vault.yml ``` Si ya tienes un archivo en texto plano, cífralo en su sitio con `ansible-vault encrypt archivo.yml`. `ansible-vault decrypt` hace lo contrario y deja el archivo en claro en disco, así que úsalo solo si de verdad quieres dejar de cifrarlo. ## Paso 3: Referenciar los secretos desde variables en claro Si todas las variables de un grupo están cifradas, nadie puede buscar con `grep` dónde se define `db_password`. La práctica recomendada es tener al lado un archivo en claro que apunte a las variables cifradas: ```bash nano group_vars/all/vars.yml ``` ```yaml db_user: app db_password: "{{ vault_db_password }}" api_token: "{{ vault_api_token }}" ``` Ansible carga los dos archivos de `group_vars/all/` automáticamente. Los playbooks usan `db_password`, y el valor real solo existe dentro de la bóveda. ## Paso 4: Usar los secretos en un playbook Crea un playbook de prueba que escriba un archivo de configuración con el secreto. Fíjate en `no_log: true`: evita que Ansible imprima los argumentos de la tarea, que incluirían la contraseña, en la salida o en los logs: ```bash nano site.yml ``` ```yaml - name: Configurar la aplicación hosts: localhost connection: local gather_facts: false tasks: - name: Escribir el archivo de credenciales ansible.builtin.copy: dest: "{{ lookup('env', 'HOME') }}/vault-demo/app.env" content: | DB_USER={{ db_user }} DB_PASSWORD={{ db_password }} mode: "0600" no_log: true ``` Ejecútalo pidiendo la contraseña de la bóveda: ```bash ansible-playbook site.yml --ask-vault-pass ``` ```output Vault password: PLAY [Configurar la aplicación] ************************************************ TASK [Escribir el archivo de credenciales] ************************************* changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=1 changed=1 unreachable=0 failed=0 ``` Comprueba que el valor se descifró correctamente y que el archivo tiene permisos restrictivos: ```bash ls -l app.env cat app.env ``` ```output -rw------- 1 your_user your_user 38 ... app.env DB_USER=app DB_PASSWORD=your_strong_password ``` Si ejecutas el playbook sin `--ask-vault-pass`, Ansible se detiene con `Attempting to decrypt but no vault secrets found`. ## Paso 5: Cifrar valores sueltos con encrypt_string A veces solo quieres cifrar una variable dentro de un archivo que por lo demás es legible. `encrypt_string` genera un bloque que puedes pegar directamente en YAML. Con `--stdin-name` el valor se lee de la entrada estándar y no queda en el historial de la shell: ```bash ansible-vault encrypt_string --stdin-name 'smtp_password' ``` Introduce la contraseña de la bóveda, escribe el secreto y pulsa `Ctrl+D` dos veces (sin salto de línea al final, o formará parte del valor): ```output Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline) smtp_password: !vault | $ANSIBLE_VAULT;1.1;AES256 38656233373639633431363030623164396565303831633063393564366631373861353438373638 ... Encryption successful ``` Pega ese bloque en cualquier archivo de variables, por ejemplo en `group_vars/all/vars.yml`. Comprueba que Ansible lo descifra: ```bash ansible localhost -m ansible.builtin.debug -a var=smtp_password --ask-vault-pass ``` El inconveniente de este método es que no puedes editar el valor con `ansible-vault edit`; para cambiarlo, generas un bloque nuevo. Para muchos secretos, un archivo cifrado completo (paso 2) es más fácil de mantener. ## Paso 6: Separar entornos con vault IDs Usar la misma contraseña para desarrollo y producción significa que cualquiera con acceso a desarrollo puede leer los secretos de producción. Los vault IDs etiquetan cada contenido cifrado con el nombre de su contraseña, y Ansible prueba la adecuada al descifrar. Guarda cada contraseña en un archivo fuera del proyecto, legible solo por tu usuario: ```bash mkdir -p ~/.ansible-vault chmod 700 ~/.ansible-vault nano ~/.ansible-vault/dev nano ~/.ansible-vault/prod chmod 600 ~/.ansible-vault/dev ~/.ansible-vault/prod ``` Escribe en cada archivo una contraseña larga distinta, en una sola línea. Puedes generarlas con `openssl rand -base64 32`. Cifra un archivo de variables con el ID `prod`: ```bash mkdir -p group_vars/prod EDITOR=nano ansible-vault create --vault-id prod@~/.ansible-vault/prod group_vars/prod/vault.yml ``` La cabecera del archivo incluye ahora la etiqueta: ```bash head -n 1 group_vars/prod/vault.yml ``` ```output $ANSIBLE_VAULT;1.2;AES256;prod ``` El archivo `group_vars/all/vault.yml` del paso 2 sigue cifrado con la primera contraseña, sin etiqueta. Vuelve a cifrarlo con el ID `dev` para que todo el proyecto use los nuevos archivos de contraseña (te pedirá la contraseña antigua): ```bash ansible-vault rekey --ask-vault-pass --new-vault-id dev@~/.ansible-vault/dev group_vars/all/vault.yml ``` El bloque `smtp_password` del paso 5 no se puede recifrar con `rekey`: genéralo de nuevo con `ansible-vault encrypt_string --vault-id dev@~/.ansible-vault/dev --stdin-name 'smtp_password'` y sustituye el anterior. Para ejecutar un playbook que use secretos de varios entornos, pasa cada vault ID: ```bash ansible-playbook site.yml --vault-id dev@~/.ansible-vault/dev --vault-id prod@~/.ansible-vault/prod ``` Si quieres que una contraseña se pida de forma interactiva en lugar de leerse de un archivo, usa `prompt` como origen, por ejemplo `--vault-id prod@prompt`. Para no escribir los IDs en cada comando, decláralos en el `ansible.cfg` del proyecto: ```bash nano ansible.cfg ``` ```ini [defaults] vault_identity_list = dev@~/.ansible-vault/dev, prod@~/.ansible-vault/prod ``` Con este archivo, `ansible-playbook site.yml` y `ansible-vault view` encuentran las contraseñas solos. ## Paso 7: Cambiar la contraseña de una bóveda Cuando alguien con acceso deja el equipo, o cada cierto tiempo, rota la contraseña. `rekey` descifra con la contraseña actual y vuelve a cifrar con la nueva: ```bash ansible-vault rekey --vault-id prod@~/.ansible-vault/prod --new-vault-id prod@prompt group_vars/prod/vault.yml ``` Tras comprobar que el archivo se abre con la nueva contraseña, actualiza `~/.ansible-vault/prod`. Ten en cuenta que rotar la contraseña de Vault no cambia los secretos: si la contraseña antigua se filtró junto con el repositorio, cambia también las credenciales cifradas en los sistemas reales. ## Paso 8: Usar Vault en CI/CD y en Git En un pipeline no hay nadie que escriba la contraseña. Guárdala como secreto enmascarado de tu sistema de CI, escríbela en un archivo temporal con permisos `600` al iniciar el trabajo y pásala con `--vault-id`: ```bash ansible-playbook site.yml --vault-id prod@"$VAULT_PASS_FILE" ``` Aquí `VAULT_PASS_FILE` es la ruta del archivo temporal que crea el pipeline. Bórralo al terminar el trabajo. Para evitar subir por error contraseñas o archivos descifrados, añade al `.gitignore` del proyecto cualquier archivo de contraseña o generado: ```bash nano .gitignore ``` ```text .vault_pass* *.env ``` Antes de cada commit, puedes comprobar que los archivos de bóveda siguen cifrados: ```bash grep -L '^\$ANSIBLE_VAULT' group_vars/*/vault.yml ``` El comando lista los archivos `vault.yml` que **no** empiezan por la cabecera de Vault; si no imprime nada, todos están cifrados. ## Solución de problemas - **`Decryption failed (no vault secrets were found that could decrypt)`**: la contraseña o el vault ID no corresponden a ese archivo. Revisa la etiqueta con `head -n 1` y que pasas el ID correcto. - **`Attempting to decrypt but no vault secrets found`**: el playbook usa datos cifrados y no has pasado ninguna contraseña (`--ask-vault-pass`, `--vault-id` o `vault_identity_list`). - **El secreto aparece en la salida con `-v`**: falta `no_log: true` en la tarea que lo usa. - **Un valor de `encrypt_string` tiene un salto de línea de más**: terminaste la entrada con Intro antes de `Ctrl+D`. Genera de nuevo el bloque. ## Conclusión Has cifrado archivos y variables con Ansible Vault, separado las contraseñas por entorno con vault IDs y usado los secretos en un playbook sin mostrarlos en la salida. Como siguientes pasos, puedes integrar las contraseñas de Vault con un gestor de secretos mediante un script cliente de vault ID, o mover los secretos más sensibles a un almacén externo como HashiCorp Vault o OpenBao y leerlos con su lookup.