Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,36 @@ The local stack uses `local` and `oci`.
PGHOST=127.0.0.1 PGPORT=15432 PGUSER=postgres PGPASSWORD=postgres PGDATABASE=platz psql
```

## Database TLS

The in-cluster Postgres ([manifests/postgres.yaml](manifests/postgres.yaml))
serves TLS: an init container generates a self-signed certificate and the
server starts with `ssl=on`. This exercises the backend's TLS support
end-to-end in local dev.

The backend's TLS behavior is controlled by `PGSSLMODE` (and `PGSSLROOTCERT`
for a custom CA), mirroring libpq's `sslmode`:

* `disable` — plaintext (the pre-TLS behavior).
* `prefer` *(default)* — use TLS if the server offers it, otherwise plaintext;
the server certificate is **not** verified.
* `require` — always use TLS; the certificate is **not** verified.
* `verify-full` — always use TLS and verify the certificate chain **and**
hostname against the system trust store or `PGSSLROOTCERT`.

Because the default is `prefer`, the local workers connect to the dev Postgres
over TLS automatically — no extra configuration needed. The certificate is
self-signed, so `verify-full` won't work locally without distributing the CA;
`prefer`/`require` are the right choices for the local stack.

Verify a connection is encrypted from inside the cluster:

```bash
kubectl -n platz exec deploy/postgres -- \
psql -U postgres -d platz -c \
"SELECT ssl, version FROM pg_stat_ssl JOIN pg_stat_activity USING (pid) WHERE usename = 'postgres';"
```

## Adding test charts

Test charts live under [charts/](charts/) and are pushed to the in-cluster
Expand Down
36 changes: 36 additions & 0 deletions manifests/postgres.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,41 @@ spec:
labels:
app: postgres
spec:
# Generate a self-signed server certificate before Postgres starts so the
# local database serves TLS, exercising the backend's TLS code path
# (PGSSLMODE). The key must be owned by the postgres user (uid 70 in the
# alpine image) with 0600 perms or the server refuses to start.
initContainers:
- name: generate-tls-cert
image: postgres:17-alpine
command:
- sh
- -c
- |
set -eu
if [ ! -f /certs/server.crt ]; then
command -v openssl >/dev/null 2>&1 || apk add --no-cache openssl
openssl req -new -x509 -days 3650 -nodes \
-subj "/CN=postgres.platz.svc.cluster.local" \
-keyout /certs/server.key \
-out /certs/server.crt
fi
chmod 600 /certs/server.key
chown 70:70 /certs/server.key /certs/server.crt
volumeMounts:
- name: tls
mountPath: /certs
containers:
- name: postgres
image: postgres:17-alpine
# Enable TLS using the certificate produced by the init container.
args:
- -c
- ssl=on
- -c
- ssl_cert_file=/certs/server.crt
- -c
- ssl_key_file=/certs/server.key
ports:
- containerPort: 5432
env:
Expand All @@ -58,6 +90,10 @@ spec:
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: tls
mountPath: /certs
volumes:
- name: data
emptyDir: {}
- name: tls
emptyDir: {}