3 KiB
Secrets
nereus-db holds two keys, used by postgres.yaml and rollout.yaml:
POSTGRES_PASSWORDDATABASE_URL—postgres://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.