HashiVault Role¶
HashiCorp Vault is a powerful secrets management tool that provides secure storage for sensitive data such as API keys, passwords, certificates, and more. This Ansible role deploys Vault as a containerized service using Podman.
Features¶
- Rootless Podman deployment
- Systemd integration using Quadlets
- Secure initialization and key management
- Multiple secret engines support (KV, PKI, SSH, Transit)
- Built-in web UI for easy management
- Automatic unsealing support
- Audit logging
Requirements¶
- Podman 4.x or later
- Systemd
- User with sudo access
- SELinux if running on RHEL/CentOS (role handles contexts)
Default Configuration¶
- API Port: 8200
- Cluster Port: 8201
- UI Enabled: Yes (access via http://localhost:8200/ui)
- Storage: File backend (configurable to Raft for clustering)
- TLS: Optional (disabled by default)
Directory Structure¶
~/vault-data/
├── config/ # Vault configuration files
├── data/ # Vault storage
├── logs/ # Audit logs
└── tls/ # TLS certificates (if enabled)
Deployment Steps¶
1. Prepare¶
Creates necessary directory structure and configuration:
This command: - Creates configuration and data directories - Sets proper permissions - Configures SELinux contexts (on RHEL-based systems)
2. Deploy¶
Creates and starts the Vault container:
This is idempotent and can be run multiple times safely. It: - Creates the Podman pod and container(s) - Generates systemd Quadlet files - Starts the Vault service
3. Initialize¶
After deployment, Vault must be initialized:
This command:
- Initializes Vault with configurable key shares (default: 5)
- Sets the key threshold for unsealing (default: 3)
- Securely stores keys and root token in ~/.secrets/vault-secrets/vault-keys.json
- Optionally creates backup of keys
- Automatically unseals Vault if configured
4. Configure¶
Set up authentication methods and secret engines:
This configures: - Authentication methods (userpass, approle) - Admin user with secure password - Policies for access control - KV v2 secrets engine
5. Set Up Secret Engines¶
Enable additional secret engines:
This enables: - Transit engine for encryption as a service - PKI engine for certificate management - SSH engine for SSH key signing/management - Populates initial secrets from environment variables
Configuration Variables¶
Installation State¶
hashivault_state: present # Use 'absent' to remove
vault_force_reload: false # Force reload configuration
vault_delete_data: false # Delete data on removal
Container Settings¶
vault_image: docker.io/hashicorp/vault:1.15
vault_data_dir: "{{ ansible_user_dir }}/vault-data"
vault_api_port: 8200
vault_cluster_port: 8201
Security Settings¶
TLS Configuration¶
vault_enable_tls: false
vault_tls_cert_file: "" # Path to certificate
vault_tls_key_file: "" # Path to private key
vault_tls_ca_file: "" # Optional CA certificate
Storage Settings¶
Initial Secrets Configuration¶
Configure initial secrets in your inventory:
vault_initial_secrets:
- path: "kv/ansible/vault"
data:
provision_vault_password: "{{ lookup('env', 'PROVISION_VAULT_PASSWORD') }}"
- path: "kv/services/elasticsearch"
data:
elastic_password: "{{ lookup('env', 'ELASTIC_PASSWORD') }}"
es_ro_token: "{{ lookup('env', 'ES_RO_TOKEN') }}"
Maintenance¶
Unsealing Vault¶
Vault requires unsealing after every restart:
This command: - Checks if Vault is already unsealed - Reads unseal keys from the keys file - Applies keys up to the threshold - Verifies unsealed status
Backup¶
Create a backup of Vault data:
Creates timestamped backup of: - Vault data directory - Configuration files - Unseal keys (encrypted)
Service Management¶
# Check status
systemctl --user status vault-pod
systemctl --user status vault-svc
# View logs
podman logs vault-svc
# Restart
systemctl --user restart vault-pod
# Stop
systemctl --user stop vault-pod
Usage Examples¶
Store a Secret¶
# Login with root token or admin credentials
export VAULT_ADDR='http://localhost:8200'
vault login
# Store a secret
vault kv put kv/myapp/config \
username=admin \
password=secret123
Read a Secret¶
# Read the secret
vault kv get kv/myapp/config
# Get specific field
vault kv get -field=password kv/myapp/config
Using PKI Engine¶
Using Transit Engine¶
# Encrypt data
vault write transit/encrypt/my-key \
plaintext=$(base64 <<< "my secret data")
# Decrypt data
vault write transit/decrypt/my-key \
ciphertext=vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==
Security Considerations¶
Key Storage¶
In production:
- Store key shares with different security officers
- Use hardware security modules (HSMs) if possible
- Never store all unseal keys on the same system as Vault
- The keys file (~/.secrets/vault-secrets/vault-keys.json) is extremely sensitive
Production Settings¶
- Enable TLS (
vault_enable_tls: true) - Use audit logging (
vault_enable_audit: true) - Configure proper firewall rules
- Use Raft storage instead of file storage for high availability
- Revoke root token after initial setup:
Troubleshooting¶
Cannot Unseal Vault¶
If you see "Error unsealing: Error making API request":
-
Check if Vault is running:
-
Verify keys file exists and is readable:
-
Check Vault status:
API Connection Issues¶
- Verify Vault is running and unsealed
-
Check API port accessibility:
-
Ensure network is not blocked by firewall
Permission Issues¶
For SELinux-related issues:
Removal¶
Remove but Keep Data¶
Complete Removal¶
License¶
MIT
Author¶
Created by jackaltx and Claude.