Files
homelab/postgres

Shared PostgreSQL

PostgreSQL 17 for the Kubernetes deployments of Authentik, Gitea, NetBox, and Netronome.

The server runs in database as StatefulSet postgres17, with data in postgres17-data. Applications connect to postgres.database.svc.cluster.local:5432. The NetworkPolicy allows only the listed application namespaces; add a new consumer there as well as provisioning its database.

Initialization

initdb/01-create-databases.sh creates roles and databases on an empty data directory. The Kubernetes copy is embedded in k8s/postgres.yaml. It also provisions Penpot and Statuspage roles, even though those are not active consumers in the current Kubernetes manifests.

The initializer requires every listed password. Prepare k8s/secrets.yaml from the example before applying the StatefulSet. Existing application Secrets keep copies of their own database passwords; they must match the corresponding role.

The init scripts do not run again when an existing data directory is mounted. Changing a Secret does not rotate the PostgreSQL role password. Rotate the role with SQL and update the application Secret together.

Compose alternative

From this directory:

cp .env.example .env
$EDITOR .env
docker compose -f shared-compose.yaml config --quiet
docker compose -f shared-compose.yaml up -d

Add NETBOX_DB_PASSWORD to .env as well: the reviewed env example omits it; fix/postgres-env-example restores the key. Fill every required password. This stack creates the homelab-database Docker network and the homelab-postgres container. Compose applications need to join that network explicitly to use it; several committed Compose stacks use their own databases.

The filename is intentional: the automatic deploy discovery does not start this stack just because the Kubernetes database is active.

Backup and upgrades

Keep database dumps and role definitions, including ownership and grants. Take a logical backup before changing a major PostgreSQL version. A new image tag over the existing data directory is not a major-version migration. Test restores separately before changing application connection settings. Immich uses its own vector-enabled database and is outside this shared instance.

Inspect

From the repository root:

kubectl get pods,svc,pvc -n database
kubectl get events -n database --sort-by=.metadata.creationTimestamp

See the repository README for deployment selection.