HashiCorp Vault — Production Server
A production Vault server uses persistent storage, TLS encryption, and proper initialization. This page covers everything you need to run Vault in a production-like environment.
Production Configuration File
Create /etc/vault.d/vault.hcl:
# /etc/vault.d/vault.hcl
# Raft integrated storage
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-1"
}
# HTTPS listener
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"
}
# Cluster address (for HA communication)
cluster_addr = "https://127.0.0.1:8201"
# API address (what clients use to reach Vault)
api_addr = "https://127.0.0.1:8200"
# Enable the web UI
ui = true
# Prevent memory from being swapped to disk
disable_mlock = false
# Telemetry for monitoring
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
Directory Setup
# Create directories
sudo mkdir -p /opt/vault/data
sudo mkdir -p /opt/vault/tls
sudo mkdir -p /etc/vault.d
sudo mkdir -p /var/log/vault
# Create vault user (non-root)
sudo useradd --system --home /opt/vault --shell /bin/false vault
# Set ownership
sudo chown -R vault:vault /opt/vault
sudo chown -R vault:vault /etc/vault.d
sudo chown -R vault:vault /var/log/vault
# Set permissions
sudo chmod 750 /opt/vault/data
sudo chmod 700 /opt/vault/tls
Generate Self-Signed TLS Certificates (Lab Only)
For production, use certificates from your PKI or a public CA. For labs:
# Generate self-signed certificate
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /opt/vault/tls/vault-key.pem \
-out /opt/vault/tls/vault-cert.pem \
-subj "/CN=vault.local" \
-addext "subjectAltName=DNS:vault.local,DNS:localhost,IP:127.0.0.1"
# Set permissions
sudo chown vault:vault /opt/vault/tls/*
sudo chmod 600 /opt/vault/tls/vault-key.pem
sudo chmod 644 /opt/vault/tls/vault-cert.pem
Start Vault
Manual Start
vault server -config=/etc/vault.d/vault.hcl
Systemd Service
Create /etc/systemd/system/vault.service:
[Unit]
Description=HashiCorp Vault
Documentation=https://www.vaultproject.io/docs
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/vault.d/vault.hcl
[Service]
User=vault
Group=vault
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
SecureBits=keep-caps
AmbientCapabilities=CAP_IPC_LOCK
NoNewPrivileges=yes
ExecStart=/usr/local/bin/vault server -config=/etc/vault.d/vault.hcl
ExecReload=/bin/kill --signal HUP $MAINPID
KillMode=process
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
LimitNOFILE=65536
LimitMEMLOCK=infinity
[Install]
WantedBy=multi-user.target
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable vault
sudo systemctl start vault
# Check status
sudo systemctl status vault
Initialize Vault
The first time Vault starts, it must be initialized:
# Set the address (use HTTPS with -tls-skip-verify for self-signed certs)
export VAULT_ADDR='https://127.0.0.1:8200'
export VAULT_SKIP_VERIFY=true # Only for self-signed certs in labs
# Initialize with default Shamir parameters (5 shares, threshold 3)
vault operator init
Expected output:
Unseal Key 1: MIGHAoGBAL...
Unseal Key 2: MIGHAoGBAM...
Unseal Key 3: MIGHAoGBAK...
Unseal Key 4: MIGHAoGBAJ...
Unseal Key 5: MIGHAoGBAI...
Initial Root Token: hvs.KLhFgN...
Vault initialized with 5 key shares and a key threshold of 3.
Please securely distribute the key shares printed above.
⚠️ Critical: Save the unseal keys and root token securely. This is the only time they are displayed.
Custom Initialization
# Fewer key shares (3 shares, threshold 2)
vault operator init -key-shares=3 -key-threshold=2
# PGP-encrypted keys (recommended for distribution)
vault operator init \
-key-shares=5 \
-key-threshold=3 \
-pgp-keys="alice.asc,bob.asc,carol.asc,dave.asc,eve.asc"
Unseal Vault
# Check status (sealed)
vault status
# Sealed: true
# Provide unseal keys (repeat until threshold is met)
vault operator unseal MIGHAoGBAL...
# Unseal Progress: 1/3
vault operator unseal MIGHAoGBAM...
# Unseal Progress: 2/3
vault operator unseal MIGHAoGBAK...
# Sealed: false ← Vault is now unsealed!
Login with Root Token
# Login
vault login hvs.KLhFgN...
# Verify
vault token lookup
Expected output:
Key Value
--- -----
accessor abc123
creation_time 1706198400
creation_ttl 0
display_name root
entity_id n/a
expire_time <nil>
explicit_max_ttl 0
id hvs.KLhFgN...
meta <nil>
num_uses 0
orphan true
path auth/token/root
policies [root]
renewable false
ttl 0
type service
Production Docker Setup
For a more production-like Docker deployment:
# docker-compose-vault-prod.yml
services:
vault:
image: hashicorp/vault:1.15
container_name: vault-prod
ports:
- "8200:8200"
volumes:
- ./vault/data:/vault/data
- ./vault/config:/vault/config
- ./vault/tls:/vault/tls
environment:
VAULT_ADDR: "https://0.0.0.0:8200"
cap_add:
- IPC_LOCK
command: vault server -config=/vault/config/vault.hcl
restart: unless-stopped
vault/config/vault.hcl:
storage "raft" {
path = "/vault/data"
node_id = "vault-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/tls/vault-cert.pem"
tls_key_file = "/vault/tls/vault-key.pem"
}
api_addr = "https://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
ui = true
Post-Init Checklist
After initializing a production Vault:
✅ Save unseal keys in separate secure locations
✅ Revoke the root token after initial setup
✅ Enable audit devices
✅ Create admin policies and auth methods
✅ Enable required secrets engines
✅ Set up monitoring and alerting
✅ Configure auto-unseal (AWS KMS, Azure KV, etc.)
✅ Schedule backup procedures
Revoke the root token:
# Create admin user/policy first, then:
vault token revoke hvs.KLhFgN...
Quick Reference
| Command | Description |
|---|---|
vault server -config=vault.hcl |
Start production server |
vault operator init |
Initialize Vault |
vault operator init -key-shares=N -key-threshold=M |
Custom Shamir params |
vault operator unseal <key> |
Provide unseal key |
vault login <token> |
Authenticate |
vault token revoke <token> |
Revoke a token |
systemctl start vault |
Start via systemd |
systemctl status vault |
Check service status |
Next: Storage Backends