PostgreSQL
PostgreSQL
Purpose
Shared PostgreSQL 16 instance used by other homelab services (Media Indexer, Postgres MCP, the homelab knowledge base, and connections registered in pgAdmin). Runs in the default namespace of the k3s cluster.
The image is the pgvector build of PostgreSQL 16, so the knowledge base can store embeddings in the same instance. It’s the Debian trixie variant: its glibc matches the collation version the existing databases were created with (2.41), so switching images didn’t trigger collation-mismatch warnings or need a reindex.
Deployment
| Item | Value |
|---|---|
| Image | pgvector/pgvector:0.8.7-pg16-trixie (PostgreSQL 16 with the pgvector extension, Debian trixie build) |
| Namespace | default |
| Replicas | 1 (Recreate strategy) |
| Service | LoadBalancer, port 5432 (MetalLB-assigned external IP 192.0.2.33) |
| Storage | postgres-data-zfs PVC, 5Gi, local-zfs storage class, mounted at /var/lib/postgresql/data |
| Data directory | PGDATA=/var/lib/postgresql/data/pgdata (subdirectory of the PVC mount, avoiding issues with lost+found in the volume root) |
| Credentials | POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB loaded in full via envFrom.secretRef from the postgres-secret Secret |
| Auto-reload | reloader.stakater.com/auto: "true" |
Storage
Uses a node-local local-zfs volume: a directory on that node’s ZFS-backed volume (a zvol on the TrueNAS NVMe pool, attached to the k3s LXC node), so the pod is scheduled where its volume is. Losing that node means Postgres waits for it to come back; the data itself is protected by ZFS snapshots of the node’s volume, replicated off-site every night.
Access
The LoadBalancer Service exposes Postgres directly on the LAN at 192.0.2.33:5432 — there’s no ingress/TLS layer in front of it, since the Postgres wire protocol isn’t HTTP. Consumers on the cluster (Postgres MCP, Media Indexer) instead reach it via the in-cluster DNS name postgres.default.svc.cluster.local:5432.