73 lines
3 KiB
Markdown
73 lines
3 KiB
Markdown
# Secrets
|
|
|
|
`nereus-db` holds two keys, used by `postgres.yaml` and `rollout.yaml`:
|
|
|
|
- `POSTGRES_PASSWORD`
|
|
- `DATABASE_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`:
|
|
|
|
```fish
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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.
|