
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Hardcoded credentials in source control remain the leading cause of preventable breaches, yet many teams still rely on environment variables or encrypted files that lack audit trails and rotation capabilities. Proper secrets management with HashiCorp Vault solves this by centralizing encryption, enforcing access policies, and generating short-lived credentials dynamically. If you are building cloud-native applications or preparing for SOC 2 compliance, moving beyond static secrets is no longer optional.
How do you configure secrets management with HashiCorp Vault for production?
Setting up Vault requires treating it as critical infrastructure, not an afterthought. In my experience helping Nepali fintech startups achieve ISO 27001 certification, the difference between a toy setup and a production-grade deployment lies in storage backend selection, high availability configuration, and unseal key management. Never run Vault with in-memory storage outside of local development.
Storage Backend and High Availability
For production, use Integrated Storage (Raft) or Consul. Raft is now the recommended default for most deployments because it eliminates external dependencies while providing strong consistency. Configure at least three nodes to tolerate a single failure without losing quorum.
# vault-config.hcl (Production Raft Example)
ui = true
disable_mlock = false
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault/tls/vault-cert.pem"
tls_key_file = "/etc/vault/tls/vault-key.pem"
}
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-node-1"
retry_join {
leader_api_addr = "https://vault-2.internal:8200"
}
retry_join {
leader_api_addr = "https://vault-3.internal:8200"
}
}
seal "awskms" {
region = "ap-south-1"
kms_key_id = "alias/vault-unseal-key"
} Always enable auto-unseal using a cloud KMS (AWS KMS, Azure Key Vault, or GCP Cloud KMS). Manual unseal with Shamir shares is operationally fragile; if your team cannot respond to a restart at 3 AM during a monsoon-induced power outage in Kathmandu, your service will remain down until someone physically intervenes. Auto-unseal removes this human bottleneck securely.
Initial Policy and Auth Method Setup
After initialization, enable only the auth methods your workloads actually need. For Kubernetes-native applications, use the Kubernetes auth method. For CI/CD pipelines integrating with tools discussed in our GitLab CI pipeline guide, use AppRole or JWT/OIDC authentication.
# Enable Kubernetes auth
vault auth enable kubernetes
# Configure Kubernetes connection
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443"
# Create a read-only policy for app secrets
vault policy write app-read - <<EOF
path "secret/data/apps/myapp/*" {
capabilities = ["read"]
}
path "database/creds/app-role" {
capabilities = ["read"]
}
EOF
# Bind policy to Kubernetes service account
vault write auth/kubernetes/role/myapp \
bound_service_account_names=myapp-sa \
bound_service_account_namespaces=production \
policies=app-read \
ttl=1h What are dynamic secrets and why do they matter?
Static secrets are liabilities. Every database password stored in an environment variable is a potential breach vector that never expires unless manually rotated. Dynamic secrets invert this model: Vault generates unique, short-lived credentials on demand and automatically revokes them when the lease expires. This is the single most valuable feature in secrets management with HashiCorp Vault.
Configuring the Database Secrets Engine
The database secrets engine supports PostgreSQL, MySQL, MongoDB, Oracle, and dozens of other datastores. Below is a working PostgreSQL configuration I have deployed across multiple AWS RDS environments:
# Enable and configure the database engine
vault secrets enable database
vault write database/config/postgres-prod \
plugin_name=postgresql-database-plugin \
allowed_roles="app-role,readonly-role" \
connection_url="postgresql://{{username}}:{{password}}@prod-db.cluster-xyz.ap-south-1.rds.amazonaws.com:5432/myapp?sslmode=require" \
username="vault_admin" \
password="initial-password-rotate-me"
# Define the role with SQL creation statements
vault write database/roles/app-role \
db_name=postgres-prod \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
revocation_statements="DROP ROLE IF EXISTS \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h" Your application now requests credentials via the Vault API or agent. Each pod or instance receives unique credentials valid for one hour. If a credential leaks, its blast radius is limited to that specific instance and timeframe. When the lease expires, Vault connects to PostgreSQL and drops the user automatically. No cron jobs, no manual rotation scripts, no shared passwords.
How does Vault compare to AWS Secrets Manager and SSM Parameter Store?
A common question from teams already invested in AWS is whether they need Vault at all. The answer depends on your multi-cloud strategy, compliance requirements, and secret complexity. As someone who manages infrastructure across AWS, Azure, and on-premises government data centers, I use both — but for different purposes.
| Criteria | HashiCorp Vault | AWS Secrets Manager | SSM Parameter Store |
|---|---|---|---|
| Multi-cloud support | Native (AWS, Azure, GCP, on-prem) | AWS only | AWS only |
| Dynamic secrets | Full support (DB, cloud, PKI, SSH) | Limited (RDS proxy only) | No |
| Encryption as a service | Transit engine built-in | KMS integration required | KMS integration required |
| Identity-based auth | K8s, LDAP, OIDC, AppRole, cloud IAM | IAM only | IAM only |
| Cost at scale | $0.40/secret/month + API calls | Free tier available; Advanced $0.05/param | |
| Compliance auditing | Detailed audit device logging | CloudTrail integration | CloudTrail integration |
| Operational overhead | High (self-managed HA cluster) | Zero (fully managed) | Zero (fully managed) |
Choose AWS Secrets Manager if you are single-cloud, have simple static secrets, and want zero operational burden. Choose Vault if you need dynamic secrets, operate across multiple clouds or hybrid environments, require encryption-as-a-service, or must meet strict audit requirements where vendor lock-in is a concern. For teams deploying Laravel on AWS as described in our AWS hosting guide, starting with SSM Parameter Store and migrating to Vault when dynamic database credentials become necessary is a pragmatic path.
How do you enforce least-privilege policies effectively?
Vault’s policy language is powerful but unforgiving. A misconfigured policy either blocks legitimate application traffic or grants excessive access. Treat policies as code: version them, review them in pull requests, and test them against staging environments before applying to production.
Policy Design Principles
- Deny by default. Vault denies all access unless explicitly permitted. Never write permissive wildcard policies like
path "secret/*"with write capabilities. - Scope by workload identity. Tie policies to Kubernetes service accounts, cloud IAM roles, or AppRole IDs — never to human users for application access.
- Separate read from write. Applications should almost never have write access to their own secret paths. Only deployment pipelines or administrators should create or update secrets.
- Use templated policies. Reduce duplication by using identity templating:
path "secret/data/{{identity.entity.name}}/*"allows each entity to access only its own namespace.
# Production app policy with scoped access
path "secret/data/apps/myapp/config" {
capabilities = ["read"]
}
path "database/creds/myapp-role" {
capabilities = ["read"]
}
# Allow renewal of own leases only
path "sys/leases/renew" {
capabilities = ["update"]
allowed_parameters = {
lease_id = []
increment = []
}
}
# Explicitly deny destructive operations
path "secret/metadata/apps/myapp/*" {
capabilities = ["deny"]
} Audit every policy change. Enable the file or syslog audit device in production so every access attempt — successful or denied — is logged immutably. During SOC 2 audits, these logs are the primary evidence reviewers examine to verify that access controls function as documented. I have seen audits fail because teams had correct policies but no proof they were enforced consistently.
Secure Your Infrastructure Before Scaling
Implementing secrets management with HashiCorp Vault is a foundational step toward production-grade security and audit readiness. Start with a clear threat model, deploy with auto-unseal and Raft storage, adopt dynamic secrets for databases first, and enforce least-privilege policies as code. The operational investment pays dividends in reduced breach surface area and smoother compliance reviews. If your team needs hands-on guidance designing a Vault architecture that fits your existing infrastructure and compliance requirements, reach out to discuss your specific environment.