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.