HashiCorp Vault for DevOps: Secrets That Expire and Rotate
HashiCorp Vault for DevOps: Secrets That Expire and Rotate
Kubernetes Secrets and CI variables solve distribution, but real organizations need more: credentials that expire, rotate, and leave an audit trail. HashiCorp Vault is the reference implementation of that idea.
Table of Contents
- What Vault actually does
- Dev server: try it in minutes
- The production shape
- Dynamic database secrets: the flagship feature
- Getting secrets into Kubernetes
- When Vault is overkill
What Vault actually does
Vault is a secrets service: your apps and pipelines authenticate to it, receive short-lived credentials for databases/clouds/APIs, and Vault handles issuance, rotation, and revocation. Instead of a password that lives forever, you get a lease.
- Static secrets — key/value storage (the KV engine) for API keys and config.
- Dynamic secrets — Vault creates credentials on demand: a real Postgres user or AWS IAM key per request, auto-deleted when the lease expires.
- Encryption as a service — the Transit engine encrypts/decrypts data so apps never hold keys.
- Audit log — every access, every credential issued, recorded.
Dev server: try it in minutes
vault server -dev # ephemeral, in-memory, prints root token
export VAULT_ADDR='http://127.0.0.1:8200'
vault kv put secret/myapp db_pass=s3cret api_key=abc123
vault kv get secret/myapp
vault kv list secret/
Dev mode is for learning only — production Vault runs unsealed, backed by Raft or Consul, TLS everywhere.
The production shape
- Seal/unseal — Vault starts sealed; key shards (Shamir) or cloud KMS auto-unseal it. This is the "can't start without ceremony" property that makes stolen disks worthless.
- Auth methods — how clients prove themselves: Kubernetes SA tokens, AWS IAM, OIDC, AppRole for machines.
- Policies — path-based ACLs: an app can read secret/data/myapp/* and nothing else.
- Leases + renewal — dynamic creds have TTLs; clients renew or let them die.
Dynamic database secrets: the flagship feature
vault secrets enable database
vault write database/config/mydb \
plugin_name=postgresql-database-plugin \
allowed_roles="readonly" \
connection_url="postgresql://vault:pw@db:5432/app?sslmode=disable" \
username="vault" password="pw"
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 ..." \
default_ttl="1h" max_ttl="24h"
# every request mints a fresh, expiring DB user:
vault read database/creds/readonly
A leaked credential here is a credential that self-destructs — that changes your incident math completely.
Getting secrets into Kubernetes
The Vault Agent Injector (sidecar) renders secrets as files inside the pod — no code changes:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-db: "secret/data/myapp/db"
For GitOps-friendly flows, External Secrets Operator syncs Vault paths to native Kubernetes Secrets — apps see standard Secrets, source of truth stays in Vault.
When Vault is overkill
Small teams running a few services get 90% of the value from cloud-native secret stores (AWS Secrets Manager, GCP Secret Manager) plus External Secrets. Vault earns its operational weight when you need dynamic credentials, a hardware-grade audit trail, multi-cloud identity brokering, or PKI management. It's a platform — deploy it when you have a platform problem.
Related Articles
Last Updated: October 2026 Author: CloudOpsGuide Team Difficulty: Advanced Estimated Reading Time: 11 minutes