Files
serverAppConfigs/serverAppConfigs-docs/Dankclaw/Postgres.md
T
Frank e7f0d93c86 docs(vault): fleet-wide fact re-verification pass (67 pages)
The docs-fact census wave re-read the live hosts and re-keyed every page
it could: runtime/payload identities, ports, sizes, ledger figures, unit
state, and the retirement banners that drifted as the fleet moved. The
wave was interrupted mid-run, so this commit carries only what passed the
integrity gates: every touched page parses (front matter or H1+status
convention intact, balanced fences, no truncated tables, trailing
newline), the docs_completeness and link-integrity seams are green, and
bats is 384/384.

Numbers that this session proved on live hosts are keyed to the measured
value, not the page's earlier claim.
2026-10-18 13:15:43 -07:00

6.7 KiB

type, description, tags, timestamp
type description tags timestamp
reference PostgreSQL is the database backend for Gitea.
dankclaw
postgres
2026-09-03

Postgres

PostgreSQL is the database backend for two separate services on this host: Gitea (gitea-postgres) and Authentik (authentik-postgres). They are two independent clusters — two containers, two data dirs, two podman networks — and each holds only its own app's data; neither is a shared instance. Gitea's DB holds the repository metadata, users, and issue data; Authentik's holds the IdP objects.

Host: Dankclaw — Docs: https://www.postgresql.org/docs

Facts

Item gitea-postgres authentik-postgres
Image docker.io/library/postgres:16-alpine (dankclaw/gitea/quadlet/gitea-postgres.container:18) docker.io/library/postgres:16-alpine (dankclaw/authentik/quadlet/authentik-postgres.container:17)
Port 5432, container-internal — no PublishPort; a TCP probe of 192.168.0.143:5432 is refused (ss -ltn + probe 2026-10-18) same: nothing published, 5432 refused on the LAN IP (2026-10-18)
Network systemd-gitea, 10.89.0.0/24 (dankclaw/gitea/quadlet/gitea.network, podman network inspect systemd-gitea 2026-10-18) dankclaw_default, 10.89.1.0/24 (authentik-postgres.container:18; the compose-stack bridge shared with Authentik/Seerr/Grafana)
Data volume /home/dank/Containers/gitea/postgres:/var/lib/postgresql/data (gitea-postgres.container:23) /home/dank/Containers/authentik/postgres:/var/lib/postgresql/data (authentik-postgres.container:23)
Healthcheck none — the unit carries no HealthCmd, so podman ps reports Up with no health state (2026-10-18) pg_isready -d authentik -U authentik every 30 s, 5 retries, 20 s start (authentik-postgres.container:29-33); container reports healthy (2026-10-18)
Secret source /home/dank/Containers/gitea/env (mode 0600, ls -l 2026-10-18) /home/dank/serverAppConfigs/dankclaw/.env (authentik-postgres.container:19)

shared/homepage/services.json reflects both: its Postgres card reads "Authentik's and Gitea's databases (Dankclaw). Not probeable: 5432 is container-internal."

Configuration

Retired compose-era definition (kept for the history below — the live stack is Quadlet, and this service ran from compose.yaml before the 2026 boot-persistence cutover). Note the data path in it (/opt/gitea/data/gitea-postgres) no longer exists; nothing deploys this block today.

services:
  postgres:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: "${GITEA_DB_PASSWORD}"
      POSTGRES_DB: gitea
    volumes:
      - /opt/gitea/data/gitea-postgres:/var/lib/postgresql/data

Gitea Connection

Gitea reaches its database over the systemd-gitea network. The live quadlet unit dankclaw/gitea/quadlet/gitea-server.container:24-29 sets exactly these variables (Environment=DATABASE_*), so the compose-era block below is equivalent in keys:

environment:
  DATABASE_TYPE: postgres
  DATABASE_HOST: gitea-postgres
  DATABASE_NAME: gitea
  DATABASE_USER: gitea
  DATABASE_PASSWD: "${GITEA_DB_PASSWORD}"

The live app.ini on the host overrides env vars: its [database] stanza carries HOST = gitea-postgres:5432, NAME = gitea, USER = gitea (/home/dank/Containers/gitea/data/gitea/conf/app.ini:27-33, 2026-10-18). When you rename the database container, update that [database] HOST line. See Gitea Gotchas.

Layout (current)

Both live units mount their data under /home/dank/Containers:

  • gitea-postgres → /home/dank/Containers/gitea/postgres:/var/lib/postgresql/data
  • authentik-postgres → /home/dank/Containers/authentik/postgres:/var/lib/postgresql/data

Both directories exist on the host with mode 0700 and owner uid 100069 (the mapped postgres uid of the rootless namespace) — ls -ld 2026-10-18. The old /opt/gitea/data/gitea-postgres compose-era path is gone. Secrets come from host-local env files (/home/dank/Containers/gitea/env, 0600; /home/dank/serverAppConfigs/dankclaw/.env) via EnvironmentFile=; the passwords never enter this repo. See Gitea and Authentik.

Boot persistence (Quadlet)

Both units carry Restart=always (gitea-postgres.container:28, authentik-postgres.container:38) and [Install] WantedBy=default.target (gitea-postgres.container:31, authentik-postgres.container:41-42), are installed under ~/.config/containers/systemd/, and report generated / active with Linger=yes on the host (2026-10-18), so both come back at boot.

Healthcheck

Only authentik-postgres has one. Its quadlet runs bare argv, not a shell string, because the generator space-splits HealthCmd (the quoted /bin/sh -c "…" form arrived mangled and reported a false-negative unhealthy forever — see the comment in dankclaw/authentik/quadlet/authentik-postgres.container:24-33):

HealthCmd=pg_isready -d authentik -U authentik
HealthInterval=30s

gitea-postgres has no HealthCmd; the probe below is the compose-era snippet, kept as the recipe to add if Gitea's DB ever needs one. Until it is in the unit, judge gitea-postgres by podman ps state and Gitea's own health.

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U gitea"]
  interval: 30s
  timeout: 5s
  retries: 3

Gotchas

  • Two clusters, not one: gitea-postgres serves only Gitea and authentik-postgres only Authentik. They are on different bridges (systemd-gitea 10.89.0.0/24 vs dankclaw_default 10.89.1.0/24, podman network inspect 2026-10-18), so neither can reach the other's data by name. Any "one Postgres serves everything" reading of this page is wrong.
  • The database password must match between the postgres container and Gitea's DATABASE_PASSWD; both come from the same env-file variable (GITEA_DB_PASSWORD, expanded by systemd from /home/dank/Containers/gitea/env).
  • Do not change the Gitea SECRET_KEY or INTERNAL_TOKEN after migration — encrypted data becomes unreadable.
  • Back up with pg_dump; see Gitea (knowledge base).

See Also

Citations

  • dankclaw/gitea/quadlet/gitea-postgres.container, dankclaw/gitea/quadlet/gitea.network, dankclaw/gitea/quadlet/gitea-server.container
  • dankclaw/authentik/quadlet/authentik-postgres.container
  • shared/homepage/services.json (the Postgres card)
  • Host evidence 2026-10-18: podman ps, podman inspect, podman network inspect systemd-gitea dankclaw_default, ss -ltn, TCP probe of 192.168.0.143:5432, systemctl --user is-enabled/is-active gitea-postgres authentik-postgres