Nereus/deploy/secrets/README.md

3 KiB

Secrets

nereus-db holds two keys, used by postgres.yaml and rollout.yaml:

  • POSTGRES_PASSWORD
  • DATABASE_URLpostgres://nereus:<password>@nereus-postgres:5432/nereus?sslmode=disable

It is not in base/kustomization.yaml. Plaintext never lands in the repo, and gitleaks runs on every push.

dev (k3d)

Create it directly, before kubectl apply -k deploy/overlays/dev:

set pw (openssl rand -hex 16)
kubectl create secret generic nereus-db -n nereus \
  --from-literal=POSTGRES_PASSWORD=$pw \
  --from-literal=DATABASE_URL="postgres://nereus:$pw@nereus-postgres:5432/nereus?sslmode=disable"

Rotating means deleting the secret, the StatefulSet's PVC, and restarting — Postgres only reads POSTGRES_PASSWORD when it initialises the data directory.

prod (sealed)

Install the controller through terraform/platform first. It is named sealed-secrets-controller, which is the default expected by kubeseal.

Create the database Secret locally and pipe it straight into kubeseal. The plaintext exists only in the pipeline and the password variable:

db_password="$(openssl rand -hex 16)"
kubectl create secret generic nereus-db --namespace nereus \
  --from-literal=POSTGRES_PASSWORD="$db_password" \
  --from-literal=DATABASE_URL="postgres://nereus:${db_password}@nereus-postgres:5432/nereus?sslmode=disable" \
  --dry-run=client -o yaml | \
kubeseal --format yaml >deploy/secrets/nereus-db-sealed.yaml
unset db_password

Commit only nereus-db-sealed.yaml and add it to the prod overlay. Back up the controller key outside the repository before relying on sealed secrets for recovery. Losing that key makes every committed SealedSecret undecryptable.

On a cluster that already has a manually created nereus-db Secret, do not apply the sealed replacement in place. PostgreSQL keeps the password used when its data directory was initialized. Cut over during a deliberate database reset: remove the old Secret and disposable PVC, apply the SealedSecret, then start PostgreSQL against the empty volume. Fresh clusters can apply the prod overlay directly.

Discord alert routing

Alertmanager reads its Discord webhook from the nereus-discord Secret as a mounted file. Create the webhook in Discord, keep it in the shell environment, and seal it without writing plaintext to disk:

test -n "${DISCORD_WEBHOOK_URL:-}"
printf '%s' "$DISCORD_WEBHOOK_URL" | \
kubectl create secret generic nereus-discord --namespace observability \
  --from-file=webhook-url=/dev/stdin --dry-run=client -o yaml | \
kubeseal --format yaml >deploy/secrets/nereus-discord-sealed.yaml
unset DISCORD_WEBHOOK_URL

Apply the sealed secret, confirm it produced the nereus-discord Secret, then set enable_discord = true in the platform Terraform variables and apply again. Discord routing defaults off so a missing owner-provided webhook cannot stop Alertmanager from starting. The committed opt-in values route warning and critical Nereus alerts to Discord and discard alerts that do not match.