HashiCorp Vault — Hardening
Harden your Vault deployment to minimize the attack surface and protect against unauthorized access.
1. TLS Everywhere
# vault.hcl
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/vault-cert.pem"
tls_key_file = "/opt/vault/tls/vault-key.pem"
# Require TLS 1.2+
tls_min_version = "tls12"
# Disable client certificate verification (unless using mTLS)
# tls_require_and_verify_client_cert = true
# tls_client_ca_file = "/opt/vault/tls/ca.pem"
}
Generate certificates using Vault’s own PKI or a trusted CA.
2. Revoke the Root Token
# After initial setup, revoke the root token
vault token revoke <root-token>
# If you need root again later, generate a temporary one
vault operator generate-root -init
# Requires unseal key holders to participate
3. Disable Unused Auth Methods & Secrets Engines
# List enabled auth methods
vault auth list
# Disable unused ones
vault auth disable approle/ # if not needed
# List enabled secrets engines
vault secrets list
# Disable unused ones
vault secrets disable totp/
4. Restrict Network Access
# vault.hcl — bind to private interface only
listener "tcp" {
address = "10.0.1.10:8200"
cluster_address = "10.0.1.10:8201"
tls_cert_file = "/opt/vault/tls/vault-cert.pem"
tls_key_file = "/opt/vault/tls/vault-key.pem"
}
Firewall rules:
# Allow only specific subnets
iptables -A INPUT -p tcp --dport 8200 -s 10.0.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 8200 -j DROP
# Cluster port — only between Vault nodes
iptables -A INPUT -p tcp --dport 8201 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 8201 -j DROP
5. Harden the OS
# Run Vault as a dedicated user (not root)
useradd --system --home /opt/vault --shell /sbin/nologin vault
# Set memory lock to prevent swapping secrets to disk
# /etc/systemd/system/vault.service
[Service]
LimitMEMLOCK=infinity
# In vault.hcl
disable_mlock = false
# Filesystem permissions
chown -R vault:vault /opt/vault
chmod 700 /opt/vault/data
chmod 600 /opt/vault/config/*.hcl
chmod 600 /opt/vault/tls/*.pem
6. Enable Audit Logging
# Always enable at least two audit devices
vault audit enable file file_path=/var/log/vault/audit.log
vault audit enable syslog tag=vault facility=AUTH
# Vault BLOCKS all requests if no audit device can log
# Two devices provide redundancy
7. Policy Best Practices
# GOOD: Specific paths, minimal capabilities
path "secret/data/myapp/*" {
capabilities = ["read"]
}
# BAD: Overly broad
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
# GOOD: Deny sensitive paths explicitly
path "sys/seal" {
capabilities = ["deny"]
}
8. Token Hygiene
# Use short TTLs
vault token create -ttl=1h -policy=myapp
# Set max TTL
vault write auth/approle/role/myapp \
token_ttl=15m \
token_max_ttl=1h
# Use token types appropriately
# Batch tokens for high-throughput (no storage overhead)
# Service tokens for interactive sessions (renewable)
9. Rate Limiting
# vault.hcl — default lease and token limits
default_lease_ttl = "1h"
max_lease_ttl = "24h"
10. Disable UI in Production (Optional)
# vault.hcl
ui = false
Hardening Checklist
| # | Item | Command/Config |
|---|---|---|
| 1 | TLS enabled | tls_cert_file in listener |
| 2 | Root token revoked | vault token revoke |
| 3 | Unused auth disabled | vault auth disable |
| 4 | Network restricted | Firewall + private bind |
| 5 | Non-root OS user | useradd --system vault |
| 6 | Memory lock | disable_mlock = false |
| 7 | Audit logging | Two audit devices |
| 8 | Least-privilege policies | Specific paths |
| 9 | Short token TTLs | token_ttl, token_max_ttl |
| 10 | File permissions | chmod 600/700 |
Next: Backup & Recovery