HashiCorp Vault — Operations¶
Scope
Production deployment, seal/unseal procedures, secret engines, audit logging, and HA patterns for HashiCorp Vault.
Deployment Patterns¶
HA Architectures¶
| Pattern | Storage Backend | Auto-Unseal | Use Case |
|---|---|---|---|
| Integrated Raft | Built-in Raft | AWS KMS / Azure Key Vault | Most deployments |
| Consul Backend | Consul cluster | Cloud KMS | Legacy, transitioning away |
| External PostgreSQL | PostgreSQL | Cloud KMS | Managed DB preference |
# Raft storage (recommended)
storage "raft" {
path = "/vault/data"
node_id = "vault-0"
retry_join {
leader_api_addr = "https://vault-1:8200"
}
}
# Auto-unseal with AWS KMS
seal "awskms" {
region = "us-east-1"
kms_key_id = "alias/vault-unseal"
}
Kubernetes Deployment (Helm)¶
helm install vault hashicorp/vault \
--namespace vault --create-namespace \
--set server.ha.enabled=true \
--set server.ha.replicas=3 \
--set server.ha.raft.enabled=true \
--set server.auditStorage.enabled=true \
--set injector.enabled=true
Secret Engines¶
| Engine | Use Case | Path |
|---|---|---|
| KV v2 | Static secrets | secret/ |
| PKI | TLS certificates | pki/ |
| Transit | Encryption as a Service | transit/ |
| Database | Dynamic DB credentials | database/ |
| AWS | Dynamic IAM credentials | aws/ |
| Kubernetes | Service account tokens | kubernetes/ |
Dynamic Database Secrets¶
# Configure database secret engine
vault write database/config/mydb \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db:5432/mydb" \
allowed_roles="readonly" \
username="vault" \
password="vault-password"
# Create role
vault write database/roles/readonly \
db_name=mydb \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
# Get dynamic credentials
vault read database/creds/readonly
Seal/Unseal Operations¶
# Initialize (first time only)
vault operator init -key-shares=5 -key-threshold=3
# Manual unseal (without auto-unseal)
vault operator unseal <key1>
vault operator unseal <key2>
vault operator unseal <key3>
# Check seal status
vault status
Recovery Keys
With auto-unseal enabled, the unseal keys become recovery keys. Store them securely (e.g., in separate physical safes or HSMs).
Audit Logging¶
# Enable file audit
vault audit enable file file_path=/vault/audit/audit.log
# Enable syslog
vault audit enable syslog tag="vault" facility="AUTH"
Monitoring¶
# Token creation rate
rate(vault_token_create_count[5m])
# Authentication failures
vault_core_handle_login_request{error!=""}
# Seal status
vault_core_unsealed
# Storage backend latency
vault_barrier_put{quantile="0.99"}
Common Issues¶
| Issue | Root Cause | Resolution |
|---|---|---|
| Vault sealed after restart | No auto-unseal configured | Configure cloud KMS auto-unseal |
| Token expired | TTL misconfigured | Increase default_ttl or use periodic tokens |
| Policy denied | Insufficient permissions | Review policy paths and capabilities |
| Raft leader election failures | Network partition | Check node connectivity, raft peers |
| High memory usage | Too many leases | Review lease TTLs, enable revocation |