Ready-to-adapt manifests for feeding the plane-enterprise chart from a cloud secret store.
The chart consumes plain Kubernetes Secrets, so nothing here is chart-specific plumbing — it is ordinary External Secrets Operator configuration. Pick the file for your provider:
| File | Provider |
|---|---|
aws-secrets-manager.yaml |
AWS Secrets Manager (RDS / Amazon MQ / ElastiCache) |
gcp-secret-manager.yaml |
GCP Secret Manager (CloudSQL / Memorystore) |
azure-key-vault.yaml |
Azure Key Vault (Flexible Server / Cache for Redis) |
rotation-runbook.md |
How to rotate without dropping requests |
A managed-rotation secret from RDS or CloudSQL contains only {"username": "...", "password": "..."}. Mirror it into the cluster verbatim with a plain dataFrom.extract — no rewrite, no template — and tell the chart which keys hold the username and password. The chart wires those keys into the pods as POSTGRES_USER / POSTGRES_PASSWORD and supplies the non-secret endpoint from values.yaml. The application composes its own connection URL from the parts, so a rotation never requires recomposing a URL and there is only one secret to watch.
# values.yaml
external_secrets:
database:
secretName: plane-rds # the mirrored secret
usernameKey: username # keys as they appear inside it
passwordKey: password
env:
pgdb_host: plane.abc123.eu-west-1.rds.amazonaws.com
pgdb_name: plane# External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
-n external-secrets --create-namespace
# Stakater Reloader — restarts pods when a synced Secret changes.
# Without this a rotated credential never reaches a running pod.
helm repo add stakater https://stakater.github.io/stakater-charts
helm install reloader stakater/reloader -n reloader --create-namespaceThen in the chart's values:
services:
api:
annotations:
reloader.stakater.com/auto: "true"refreshInterval bounds how long a rotated credential stays unnoticed, and each interval costs one API call per ExternalSecret per provider.
1h— the sensible default for secrets you rotate on a schedule and where you use the two-valid-credentials pattern from the runbook, so the window is harmless.1m–5m— when a single credential is swapped in place and the failure window must be short.
If your provider can push on rotation (an AWS Lambda rotation hook that annotates the ExternalSecret, or ESO's PushSecret/webhook paths), prefer that over polling frequently.
From planeVersion v3.2.0 every service — including silo, live and Plane AI — reads
discrete credential parts, so the template: blocks in the provider examples that build
a DATABASE_URL/REDIS_URL/AMQP_URL are no longer needed. Point
external_secrets.database / rabbitmq / redis at the mirrored secret and let each
app compose its own URL.
Keep using the templated DSN sections (plane-silo-env and friends) only when pinned
below v3.2.0, or when a service genuinely needs different credentials from the primary.
Do not put SECRET_KEY, AES_SECRET_KEY or AES_SALT in a secret with a rotation policy. SECRET_KEY derives the Fernet key encrypting the instance-configuration rows, and the AES pair protects stored OAuth/MCP tokens; changing either makes existing ciphertext undecryptable, silently. Keep them in a separate, static secret — that is what app_keys_existingSecret is for.