HashiCorp Vault centraliza la gestión de secretos: contraseñas, tokens de API, certificados y claves de cifrado se guardan cifrados en un único servicio, cada acceso se controla con políticas y todo queda registrado en un log de auditoría. En este tutorial instalarás Vault en Ubuntu 24.04 con TLS y almacenamiento Raft integrado, lo inicializarás y desbloquearás, guardarás secretos en el motor KV y darás a una aplicación acceso de solo lectura mediante AppRole.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM.
  • Un usuario no root con privilegios sudo.
  • La IP del servidor por la que se conectarán los clientes (your_server_ip en los ejemplos). Lo habitual es usar una IP de red privada y no exponer Vault a Internet.

La guía usa un único nodo. El almacenamiento Raft permite añadir más nodos después para tener alta disponibilidad sin cambiar de backend.

Paso 1: Instalar Vault

Añade el repositorio oficial de HashiCorp con su clave en /etc/apt/keyrings:

sudo apt update
sudo apt install -y wget gpg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

Instala Vault:

sudo apt update
sudo apt install -y vault
vault version
Vault v1.x.x (...), built ...

El paquete crea el usuario de sistema vault, el archivo de configuración /etc/vault.d/vault.hcl, el directorio de datos /opt/vault/data y la unidad systemd vault.service.

Paso 2: Crear el certificado TLS

Vault debe servir su API siempre por HTTPS: por ella viajan tokens y secretos. Si tienes un dominio apuntando al servidor, usa un certificado de una CA real. Para una instalación interna, genera un certificado autofirmado que incluya en el campo subjectAltName la IP por la que te conectarás y 127.0.0.1:

sudo install -d -o vault -g vault -m 0750 /opt/vault/tls
sudo openssl req -x509 -newkey rsa:4096 -sha256 -days 825 -nodes \
  -keyout /opt/vault/tls/tls.key -out /opt/vault/tls/tls.crt \
  -subj "/CN=vault" \
  -addext "subjectAltName=IP:your_server_ip,IP:127.0.0.1,DNS:localhost"

Ajusta propietario y permisos. La clave privada solo debe poder leerla el usuario vault:

sudo chown vault:vault /opt/vault/tls/tls.key /opt/vault/tls/tls.crt
sudo chmod 0600 /opt/vault/tls/tls.key

Añade el certificado a los certificados de confianza del sistema para que el cliente vault (y curl) lo acepten sin avisos. Repite esto en cada máquina cliente que vaya a conectarse a Vault:

sudo cp /opt/vault/tls/tls.crt /usr/local/share/ca-certificates/vault.crt
sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.

Comprueba las direcciones incluidas:

openssl x509 -in /usr/local/share/ca-certificates/vault.crt -noout -ext subjectAltName
X509v3 Subject Alternative Name:
    IP Address:10.0.1.10, IP Address:127.0.0.1, DNS:localhost

Paso 3: Configurar Vault

Abre el archivo de configuración:

sudo nano /etc/vault.d/vault.hcl

Sustituye su contenido por el siguiente, con tu IP en api_addr y cluster_addr:

ui            = true
disable_mlock = true

storage "raft" {
  path    = "/opt/vault/data"
  node_id = "vault-01"
}

listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/tls.crt"
  tls_key_file  = "/opt/vault/tls/tls.key"
}

api_addr     = "https://your_server_ip:8200"
cluster_addr = "https://your_server_ip:8201"
  • storage "raft": almacenamiento integrado, sin depender de Consul ni de otra base de datos. Los datos se guardan cifrados en /opt/vault/data.
  • disable_mlock = true: HashiCorp recomienda desactivar mlock con almacenamiento Raft. Para que los secretos no acaben en disco, desactiva también el swap del servidor o cífralo.
  • listener "tcp": la API y la interfaz web en el puerto 8200 con TLS.
  • api_addr y cluster_addr: las direcciones que Vault anuncia a los clientes y a otros nodos Raft (puerto 8201).

Paso 4: Arrancar Vault y abrir el firewall

Habilita e inicia el servicio:

sudo systemctl enable --now vault
sudo systemctl status vault
● vault.service - "HashiCorp Vault - A tool for managing secrets"
     Loaded: loaded (/usr/lib/systemd/system/vault.service; enabled; preset: enabled)
     Active: active (running) since ...

Permite el acceso al puerto 8200 solo desde la red de la que vengan tus clientes (aquí 10.0.1.0/24). Si UFW no está activo, permite antes SSH:

sudo ufw allow OpenSSH
sudo ufw allow from 10.0.1.0/24 to any port 8200 proto tcp
sudo ufw enable

Configura el cliente vault para que hable con el servidor local. Añade esta línea a tu ~/.bashrc:

nano ~/.bashrc
export VAULT_ADDR="https://127.0.0.1:8200"

Carga la variable y consulta el estado:

source ~/.bashrc
vault status
Key                Value
---                -----
Seal Type          shamir
Initialized        false
Sealed             true
Total Shares       0
Threshold          0
Unseal Progress    0/0
Storage Type       raft
HA Enabled         true

Vault está en marcha pero sin inicializar y sellado: todavía no puede leer ni escribir datos.

Paso 5: Inicializar y desbloquear Vault

La inicialización genera la clave maestra que cifra todos los datos y la divide en varias partes (unseal keys) con el algoritmo de Shamir. Con 5 partes y un umbral de 3, hacen falta 3 cualesquiera para desbloquear Vault, así que puedes repartirlas entre varias personas. Ejecuta la inicialización una sola vez:

vault operator init -key-shares=5 -key-threshold=3
Unseal Key 1: 4jYbl2CBIv6SpkKj6Hos9iD32k5RfGkLzlosrrq/JgOm
Unseal Key 2: B05G1DRtfYckFV5BbdBvXq0wkK5HFqB9g2jcDmNfTQiS
Unseal Key 3: Arig0N9rN9ezkTRo7qTB7gsIZDaonOcc53EHo83F5chA
Unseal Key 4: 0cZE0C/gEk3YHaKjIWxhyyfs8REhqkRW/CSXTnmTilv+
Unseal Key 5: fYhZOseRgzxmJCmIqUdxEm9C3jB5Q27AowER9w4FC2Ck

Initial Root Token: hvs.KkNJYWF5g0pomcCLEmDdOVCW
...

Desbloquea Vault introduciendo tres claves distintas, una por comando. Cada comando te pide la clave sin mostrarla en pantalla:

vault operator unseal
vault operator unseal
vault operator unseal

Tras la tercera clave, comprueba el estado:

vault status
Key                     Value
---                     -----
Seal Type               shamir
Initialized             true
Sealed                  false
Total Shares            5
Threshold               3
...
Storage Type            raft
HA Enabled              true
HA Mode                 active

Sealed false indica que Vault está operativo. Inicia sesión con el root token para la configuración inicial; el comando te lo pide de forma interactiva:

vault login

Paso 6: Crear un usuario administrador y retirar el root token

El root token no tiene restricciones ni caducidad, así que no debe usarse en el día a día. Crea una política de administración:

nano ~/admin-policy.hcl
path "*" {
  capabilities = ["create", "read", "update", "patch", "delete", "list", "sudo"]
}

Esta política da control total; cuando tengas claro qué necesita cada persona, sustitúyela por políticas más limitadas. Cárgala:

vault policy write admin ~/admin-policy.hcl

Activa el método de autenticación por usuario y contraseña y crea el usuario admin. Con password=-, Vault lee la contraseña de la entrada estándar y no queda en el historial de la shell; escríbela y pulsa Ctrl+D:

vault auth enable userpass
vault write auth/userpass/users/admin token_policies=admin password=-

Inicia sesión como admin para comprobar que funciona:

vault login -method=userpass username=admin
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
...
token_policies         ["admin" "default"]

Ahora revoca el root token inicial, sustituyendo el valor por el tuyo:

vault token revoke hvs.KkNJYWF5g0pomcCLEmDdOVCW

Si alguna vez necesitas un root token de nuevo, puedes generarlo con vault operator generate-root y la mayoría de las unseal keys.

Paso 7: Guardar secretos en el motor KV

Los secretos se guardan en motores montados en rutas. El motor KV versión 2 almacena pares clave-valor y conserva un historial de versiones. Actívalo en la ruta secret/:

vault secrets enable -path=secret kv-v2

Guarda las credenciales de una aplicación. Sustituye your_strong_password por la contraseña real:

vault kv put -mount=secret myapp/config db_user=myapp db_password=your_strong_password
===== Secret Path =====
secret/data/myapp/config

======= Metadata =======
Key                Value
---                -----
created_time       2026-09-25T10:15:00.000000Z
deletion_time      n/a
destroyed          false
version            1

Léelo completo o extrae un solo campo, útil en scripts:

vault kv get -mount=secret myapp/config
vault kv get -mount=secret -field=db_user myapp/config
myapp

Cada put sobre la misma ruta crea una versión nueva. Puedes leer una versión anterior con -version=1 y ver el historial con vault kv metadata get -mount=secret myapp/config.

Paso 8: Dar acceso a una aplicación con AppRole

Las aplicaciones no deben usar tokens de administrador. Crea una política que solo permita leer los secretos bajo myapp/:

nano ~/myapp-policy.hcl
path "secret/data/myapp/*" {
  capabilities = ["read"]
}

path "secret/metadata/myapp/*" {
  capabilities = ["list"]
}

En KV v2, los datos se leen a través de la ruta secret/data/ y los listados a través de secret/metadata/, por eso la política usa esas rutas y no secret/myapp/. Cárgala:

vault policy write myapp ~/myapp-policy.hcl

AppRole es el método de autenticación pensado para aplicaciones y automatización: la aplicación presenta un role_id (similar a un nombre de usuario) y un secret_id (similar a una contraseña) y recibe un token de vida corta. Actívalo y crea el rol:

vault auth enable approle
vault write auth/approle/role/myapp token_policies=myapp token_ttl=1h token_max_ttl=4h secret_id_ttl=24h

Obtén las dos credenciales. En producción entregarías el role_id con la configuración de la aplicación y el secret_id por un canal distinto, en el momento del despliegue:

ROLE_ID=$(vault read -field=role_id auth/approle/role/myapp/role-id)
SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/myapp/secret-id)

Inicia sesión como la aplicación y guarda el token que devuelve:

APP_TOKEN=$(vault write -field=token auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID")

Comprueba que con ese token se puede leer el secreto:

VAULT_TOKEN="$APP_TOKEN" vault kv get -mount=secret -field=db_user myapp/config
myapp

Y que no se puede escribir:

VAULT_TOKEN="$APP_TOKEN" vault kv put -mount=secret myapp/config db_user=otro
Error writing data to secret/data/myapp/config: Error making API request.
...
Code: 403. Errors:

* 1 error occurred:
	* permission denied

Paso 9: Activar el log de auditoría y las copias de seguridad

El log de auditoría registra cada petición a Vault, con los valores sensibles cifrados con HMAC. Crea el directorio y activa el dispositivo de auditoría:

sudo install -d -o vault -g vault -m 0750 /var/log/vault
vault audit enable file file_path=/var/log/vault/audit.log
Success! Enabled the file audit device at: file/

Configura la rotación del archivo. Vault vuelve a abrir el log al recibir SIGHUP, que es lo que hace systemctl reload vault:

sudo nano /etc/logrotate.d/vault
/var/log/vault/audit.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        /usr/bin/systemctl reload vault > /dev/null 2>&1 || true
    endscript
}

Con almacenamiento Raft, una copia de seguridad completa es un snapshot:

vault operator raft snapshot save vault-$(date +%F).snap

El snapshot está cifrado con la clave maestra, así que para restaurarlo con vault operator raft snapshot restore necesitarás también las unseal keys. Guárdalo fuera del servidor.

Solución de problemas

  • x509: certificate signed by unknown authority: el cliente no confía en el certificado. Repite en esa máquina la copia a /usr/local/share/ca-certificates/ y sudo update-ca-certificates, o indica el certificado con la variable VAULT_CACERT. Si regeneras el certificado, vuelve a copiarlo.
  • x509: certificate is valid for ..., not ...: te conectas por una IP o nombre que no está en el subjectAltName. Regenera el certificado incluyéndolo y reinicia con sudo systemctl restart vault.
  • Vault is sealed tras un reinicio: es el comportamiento esperado. Vault arranca siempre sellado y hay que volver a ejecutar vault operator unseal con tres claves. Para desbloquearlo de forma automática existen los mecanismos de auto-unseal con un KMS externo o con otro Vault (motor Transit).
  • permission denied al leer un secreto KV: la política usa secret/myapp/* en lugar de secret/data/myapp/*. Comprueba qué permite el token con vault token capabilities secret/data/myapp/config.
  • El servicio no arranca: revisa sudo journalctl -u vault -e. Los fallos habituales son permisos de /opt/vault/tls/tls.key o /opt/vault/data y errores de sintaxis en vault.hcl.

Conclusión

Tienes Vault funcionando en Ubuntu 24.04 con TLS y almacenamiento Raft, un administrador con su propio usuario en lugar del root token, secretos versionados en KV, una aplicación que se autentica con AppRole con acceso de solo lectura, log de auditoría y copias de seguridad. Como siguientes pasos, añade dos nodos más con vault operator raft join para tener alta disponibilidad, prueba el motor de secretos database para generar credenciales temporales de base de datos y configura auto-unseal para que un reinicio no requiera intervención manual.