# App secrets (task 46). PLACEHOLDERS ONLY — never commit real values. # # Consumption: the Deployment and the migrate Job project every key below into # a tmpfs volume at `/run/secrets` (`defaultMode: 0400`, group 65532 via the # pod `fsGroup`) and read them through `*_FILE` variables, so no secret enters # the process environment (`/proc/self/environ`, children, crash dumps, # `docker inspect`): # # token-pepper -> D_OAUTH_TOKEN_PEPPER_FILE # totp-encryption-key -> D_OAUTH_TOTP_ENCRYPTION_KEY_FILE # database-password -> D_OAUTH_DATABASE__PASSWORD_FILE # redis-password -> D_OAUTH_REDIS__PASSWORD_FILE # # The passwordless DSNs (host/user/db/sslmode and the Redis address) are # non-secret and live in `configmap.yaml`; only the passwords are here. A # `kubectl exec` into a running pod therefore reads no credential from the # environment — only the 0400 files, which the container user already holds. # `scripts/check_manifests.py` fails the build if a workload injects any secret # through a `secretKeyRef` env instead. # # In-cluster Redis is expected to run with AUTH (`requirepass`); the password # is injected into the bare `redis://host:port` URL at connect time. A Redis # deployment without AUTH must enable it, or the workload fails closed on the # missing password file. # # Production rule: this file's keys are replaced by the secret manager # (external-secrets / sealed-secrets / vault agent). The manifests only ever # reference keys, never values; `scripts/check_manifests.py` fails the build # if a placeholder leaks outside this file, if a PEM block appears in any # manifest, or if a secret-shaped key lands in the ConfigMap. # # To provision: `kubectl create secret generic d-oauth-secrets -n d-oauth # --from-literal=database-password='...' --from-literal=redis-password='...' # ...` (or the external-secret equivalent), then delete this placeholder # file from the applied set. apiVersion: v1 kind: Secret metadata: name: d-oauth-secrets namespace: d-oauth labels: app.kubernetes.io/name: d-oauth-server app.kubernetes.io/part-of: d-oauth type: Opaque stringData: # Postgres password, split out of the passwordless DSN in configmap.yaml. database-password: "REPLACE_ME__postgres-password" # Redis AUTH password, injected into the bare redis:// URL at connect time. redis-password: "REPLACE_ME__redis-password" # 256-bit server-side pepper for opaque-token hashing. Losing it invalidates # every live token; rotate per docs/OPERATIONS.md. token-pepper: "REPLACE_ME__32-bytes-of-random" # 256-bit key encrypting TOTP secrets at rest. totp-encryption-key: "REPLACE_ME__32-bytes-of-random"