# PostgreSQL credentials for toolshed, from one Vault path into two # namespaces: the server needs them to initialise the database, and # toolshed's api needs them to connect. Kept in one file because they are one # credential with two consumers — splitting them invites the two drifting # apart, which fails as an authentication error that looks nothing like a # config mistake. # # Put the credential in Vault BEFORE syncing either of these. External # Secrets cannot create a Secret for a path that does not exist, and the # PostgreSQL pod will sit in CreateContainerConfigError until it can: # # kubectl -n vault exec -i vault-0 -- sh -lc ' # vault login >/dev/null && # vault kv put secret/toolshed/postgres \ # username=toolshed \ # password=' # # Use an alphanumeric password. It is interpolated into a libpq connection # URL below, where @ : / ? # would need percent-encoding, and a password that # silently truncates the URL is a genuinely unpleasant thing to debug. # # Remember that `kubectl exec` into Vault is unauthenticated by default — # without the `vault login` the commands fail with a "preflight capability # check" error that reads like a permissions bug rather than a missing login. --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: postgresql-credentials namespace: postgres spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: ClusterSecretStore target: name: postgresql-credentials creationPolicy: Owner data: - secretKey: username remoteRef: key: toolshed/postgres property: username - secretKey: password remoteRef: key: toolshed/postgres property: password --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: toolshed-db namespace: toolshed spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: ClusterSecretStore target: name: toolshed-db creationPolicy: Owner template: data: username: "{{ .username }}" password: "{{ .password }}" # Composed here rather than assembled in application code, so the # host, port and database name live in one place instead of being # spread across environment variables that can disagree. # # sslmode=disable is consistent with this cluster running plain HTTP # throughout; traffic stays on the pod network. It is the first thing # to change if this ever leaves the homelab. url: "postgres://{{ .username }}:{{ .password }}@postgresql.postgres.svc.cluster.local:5432/toolshed?sslmode=disable" data: - secretKey: username remoteRef: key: toolshed/postgres property: username - secretKey: password remoteRef: key: toolshed/postgres property: password