Skip to content

Vault — Practical

Terminal window
# enable
vault auth enable kubernetes
# configure with cluster info (from inside K8s)
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc" \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_ca_cert="$(cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt)"
# bind: SA `api` in `app` namespace gets policies api-read
vault write auth/kubernetes/role/api \
bound_service_account_names=api \
bound_service_account_namespaces=app \
policies=api \
ttl=1h
api.hcl
path "secret/data/api/*" {
capabilities = ["read"]
}
path "database/creds/api-readonly" {
capabilities = ["read"]
}
path "transit/encrypt/api" {
capabilities = ["update"]
}
path "transit/decrypt/api" {
capabilities = ["update"]
}
path "auth/token/renew-self" {
capabilities = ["update"]
}
Terminal window
vault policy write api api.hcl
Terminal window
vault secrets enable database
vault write database/config/main \
plugin_name=postgresql-database-plugin \
allowed_roles="api,migrator" \
connection_url="postgresql://{{username}}:{{password}}@db.svc:5432/app?sslmode=disable" \
username="vault_admin" \
password="..."
vault write database/roles/api \
db_name=main \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl=1h \
max_ttl=24h
# Get creds (auto-revoked after 1h)
vault read database/creds/api
Terminal window
vault secrets enable transit
vault write -f transit/keys/api # create key
# encrypt
vault write transit/encrypt/api plaintext=$(echo -n "secret data" | base64)
# {"ciphertext":"vault:v1:abc..."}
# decrypt
vault write transit/decrypt/api ciphertext="vault:v1:abc..."
# rotate key (creates v2; old v1 still works to decrypt)
vault write -f transit/keys/api/rotate

Annotate pods, agent sidecar injects rendered templates as files.

apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'api'
vault.hashicorp.com/agent-inject-secret-config: 'secret/data/api/db'
vault.hashicorp.com/agent-inject-template-config: |
{{ with secret "secret/data/api/db" -}}
DB_USER={{ .Data.data.user }}
DB_PASS={{ .Data.data.password }}
{{- end }}
spec:
serviceAccountName: api
containers:
- name: api
image: ghcr.io/org/api:1.0
env:
- name: ENV_FILE
value: /vault/secrets/config
/etc/vault-agent/config.hcl
vault { address = "https://vault.example.com:8200" }
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config = { role = "api" }
}
sink "file" { config = { path = "/run/vault/token" } }
}
template {
source = "/etc/vault-agent/db.tpl"
destination = "/run/vault/db.env"
command = "systemctl restart api"
}
import vault from 'node-vault';
const v = vault({ endpoint: 'https://vault.example.com:8200' });
// auth via K8s
const jwt = fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/token','utf8');
const r = await v.kubernetesLogin({ role: 'api', jwt });
v.token = r.auth.client_token;
const dbCreds = await v.read('database/creds/api');
console.log(dbCreds.data.username, dbCreds.data.password);

Production: prefer Vault Agent injector / sidecar instead of in-app Vault calls.

Terminal window
vault operator raft snapshot save backup-$(date +%F).snap
# restore (only on fresh cluster)
vault operator raft snapshot restore backup-2026-05-01.snap
Terminal window
vault status
vault token lookup
vault token revoke <token>
vault kv list secret/api
vault read database/config/main
vault list sys/leases/lookup/database/creds/api
vault lease revoke -prefix database/creds/api
vault audit enable file file_path=/vault/audit.log
vault read sys/health
  • Vault Agent injector (helm chart hashicorp/vault).
  • Banzai/Bank-Vaults — operator on K8s.
  • External Secrets Operator — alternative; pulls from Vault into K8s Secrets.
  • Sentinel (Enterprise) — policy as code beyond ACL.
  • vault-cli scripts — automation.