Skip to main content

Secrets Rotation Runbook

Secret Inventory​

SecretFileTypeRotation Cadence
pg_urisecrets/pg_uriPostgreSQL passwordQuarterly
session_keysecrets/session_keyHMAC key (32 bytes hex)Quarterly
cache_hmacsecrets/cache_hmacCache HMAC key (32 bytes hex)Quarterly
kms_local_keysecrets/kms_local_keyEd25519 private key (32 bytes raw)Semi-annually
vendor_public_keypkg/license/zz_keys.goEd25519 public key (64 hex chars)Per vendor rotation

Rotation Procedures​

Session Key / Cache HMAC​

# Generate new 32-byte random keys
openssl rand -hex 32 > deploy/secrets/session_key
openssl rand -hex 32 > deploy/secrets/cache_hmac

# Restart services to pick up new secrets
docker compose restart gateway admin loggerd

Note: Rotating session_key will invalidate all active sessions. Notify users. Rotating cache_hmac will evict cached data (rebuilds automatically).

PostgreSQL Password​

  1. Log into the database: docker compose exec postgres psql -U yabanin
  2. Create new password: ALTER USER yabanin WITH PASSWORD 'newpassword';
  3. Update secrets/pg_uri with the new password
  4. Restart all services: docker compose restart

KMS Local Key​

# Generate new 32-byte raw key (Ed25519 private key)
head -c 32 /dev/urandom > deploy/secrets/kms_local_key

# Verify it's exactly 32 bytes
wc -c deploy/secrets/kms_local_key
# Expected: 32

# Restart services that use KMS
docker compose restart gateway loggerd kms-signer

Warning: Rotating kms_local_key invalidates all previously signed license keys. You must regenerate vendor-signed license keys after this rotation.

Vendor Public Key (zz_keys.go)​

The vendor public key is embedded in Go source (pkg/license/zz_keys.go). To rotate it:

  1. Obtain the new Ed25519 public key from the vendor
  2. Update const VendorPublicKey = "<64-char hex>" in zz_keys.go
  3. Run go generate ./pkg/license/... to regenerate if needed
  4. Commit and redeploy

Emergency Rotation​

If a secret is suspected to be compromised:

  1. Immediately rotate the affected secret using procedures above
  2. Restart all affected services: docker compose restart
  3. For session_key or pg_uri — notify users of service disruption
  4. Audit logs for unauthorized access: docker compose logs gateway | grep -i "unauthorized\|forbidden"