What Vault Does
- Secret Storage: Securely store static secrets (API keys, passwords) with versioning
- Dynamic Secrets: Generate short-lived credentials on-demand for databases, AWS, etc.
- Encryption as a Service: Encrypt/decrypt data without storing encryption keys in your app
- Certificate Management: PKI for issuing TLS certificates and managing cert lifecycles
- Identity-Based Access: Integrate with LDAP, AD, OIDC, Kubernetes, AWS IAM for auth
- Audit Logging: Detailed audit trail of every secret access
- Secret Rotation: Automatic rotation of database passwords and cloud credentials
- Token-Based Auth: Time-limited, scoped access tokens
- Policy-Based Access: Fine-grained permissions via HCL policies
- Namespaces: Multi-tenant secret isolation (Enterprise)
Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Applications │────▶│ Vault │────▶│ Storage │
│ (Auth Method)│ │ Server │ │ Backend │
└──────────────┘ │ (Go) │ │ (Raft/S3/ │
└──────┬───────┘ │ Consul/etc) │
│ └──────────────┘
┌──────┴───────┐
│ Secret │
│ Engines │
│ (KV/DB/PKI) │
└──────────────┘Self-Hosting
Docker Compose (Production)
services:
vault:
image: hashicorp/vault:latest
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
volumes:
- ./config:/vault/config
- vault-data:/vault/data
- vault-logs:/vault/logs
command: server
environment:
VAULT_ADDR: http://127.0.0.1:8200
VAULT_API_ADDR: http://127.0.0.1:8200
volumes:
vault-data:
vault-logs:Config File
# config/vault.hcl
ui = true
storage "raft" {
path = "/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 0
tls_cert_file = "/vault/config/cert.pem"
tls_key_file = "/vault/config/key.pem"
}
api_addr = "https://vault.yourdomain.com:8200"
cluster_addr = "https://vault.yourdomain.com:8201"Initialization
# Initialize (only once)
vault operator init
# Outputs:
# Unseal Key 1: xxxxx
# Unseal Key 2: xxxxx
# Unseal Key 3: xxxxx
# Unseal Key 4: xxxxx
# Unseal Key 5: xxxxx
# Initial Root Token: s.xxxxxxxxx
# Unseal (need 3 of 5 keys)
vault operator unseal key1
vault operator unseal key2
vault operator unseal key3
# Login with root token
vault loginKey Features
KV (Key-Value) Secrets
# Enable KV v2 engine
vault secrets enable -path=secret kv-v2
# Write secret
vault kv put secret/myapp/db
username=admin
password=super-secret
host=db.example.com
# Read secret
vault kv get secret/myapp/db
# Get specific version
vault kv get -version=2 secret/myapp/dbDynamic Database Credentials
# Configure database secrets engine
vault secrets enable database
vault write database/config/my-postgres
plugin_name=postgresql-database-plugin
allowed_roles="readonly"
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb"
username="vaultuser"
password="vaultpass"
# Create role that generates temporary credentials
vault write database/roles/readonly
db_name=my-postgres
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 temporary credentials
vault read database/creds/readonly
# Returns: username, password, lease_id, ttl=1hNow your app gets fresh credentials every hour, eliminating static passwords.
Encryption as a Service
# Enable transit engine
vault secrets enable transit
vault write -f transit/keys/myapp
# Encrypt data (app never sees the key)
vault write transit/encrypt/myapp plaintext=$(echo "sensitive data" | base64)
# Returns: vault:v1:encrypted-blob
# Decrypt data
vault write transit/decrypt/myapp ciphertext="vault:v1:encrypted-blob"
# Returns: decoded plaintextYour app can encrypt data without ever touching encryption keys.
Authentication Methods
# Enable Kubernetes auth
vault auth enable kubernetes
vault write auth/kubernetes/config
kubernetes_host="https://kubernetes.default.svc"
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# Allow specific Kubernetes service account to access secrets
vault write auth/kubernetes/role/myapp
bound_service_account_names=myapp
bound_service_account_namespaces=default
policies=myapp-policy
ttl=1hSupported auth methods:
- Tokens (default)
- Kubernetes (service accounts)
- AWS IAM / EC2
- LDAP / Active Directory
- OIDC / OAuth
- JWT
- GitHub
- Username/Password
Policies
# myapp-policy.hcl
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
path "database/creds/myapp-readonly" {
capabilities = ["read"]
}
path "transit/encrypt/myapp" {
capabilities = ["update"]
}vault policy write myapp-policy myapp-policy.hclVault vs Alternatives
| Feature | Vault | AWS Secrets Manager | Infisical | Doppler |
|---|---|---|---|---|
| Open Source | BSL | No | Yes | No |
| Self-hosted | Yes | No | Yes | No |
| Dynamic secrets | Yes | Limited | Yes | No |
| Encryption service | Yes | KMS | Basic | No |
| PKI | Yes | Limited | No | No |
| Multi-cloud | Yes | AWS only | Yes | Yes |
| Secret rotation | Yes | Yes | Yes | Yes |
常见问题
Q: Vault 的学习曲线陡吗? A: 相对较陡。Vault 功能强大但概念众多(seal/unseal、policies、auth methods、secret engines)。建议从 KV 存储开始,逐步学习动态密钥和高级功能。官方文档和教程非常好。
Q: 生产环境如何避免 Unseal 操作? A: 使用自动解封(auto-unseal)配置。可以使用 AWS KMS、Azure Key Vault、GCP KMS 或 Transit engine(另一个 Vault 实例)作为解封密钥存储,实现服务重启后自动解封。
Q: 密钥丢失怎么办? A: 如果丢失了足够多的 unseal keys(默认是 5 分 3 合),密封的 Vault 将无法恢复。务必将 unseal keys 分发给不同人员或存储在不同位置,并定期演练恢复流程。
来源与致谢
- GitHub: hashicorp/vault — 35.4K+ ⭐ | BSL
- 官网: vaultproject.io