Skip to content

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:

./manage-svc.sh hashivault prepare

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:

./manage-svc.sh hashivault deploy

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:

./svc-exec.sh hashivault initialize

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:

./svc-exec.sh hashivault configure

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:

./svc-exec.sh hashivault vault-secrets

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

vault_enable_ui: true
vault_enable_audit: true

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

vault_storage_type: "file"         # Options: file, raft, consul

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:

./svc-exec.sh hashivault unseal

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:

./svc-exec.sh hashivault backup

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

# Generate a certificate
vault write pki/issue/my-role \
  common_name=test.example.com \
  ttl=24h

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:
podman exec -it vault-svc vault token revoke $ROOT_TOKEN

Troubleshooting

Cannot Unseal Vault

If you see "Error unsealing: Error making API request":

  1. Check if Vault is running:

    systemctl --user status vault-pod
    

  2. Verify keys file exists and is readable:

    cat ~/.secrets/vault-secrets/vault-keys.json
    

  3. Check Vault status:

    podman exec vault-svc vault status
    

API Connection Issues

  1. Verify Vault is running and unsealed
  2. Check API port accessibility:

    curl -v http://localhost:8200/v1/sys/health
    

  3. Ensure network is not blocked by firewall

Permission Issues

For SELinux-related issues:

# Check contexts
ls -Z ~/vault-data

# Reapply contexts
sudo restorecon -Rv ~/vault-data

Removal

Remove but Keep Data

./manage-svc.sh hashivault remove

Complete Removal

VAULT_DELETE_DATA=true ./manage-svc.sh hashivault remove

License

MIT

Author

Created by jackaltx and Claude.