# Authentik — VPS (ROOTLESS PODMAN) copy of the home server's auth stack. # # This is a 1:1 copy of ~/Server/auth on server.gib, migrated 2026-08-11. The home # instance is still running and authoritative; this one has an independent database # restored from a dump taken at migration time, so THE TWO DIVERGE FROM THAT MOMENT ON. # Do not treat this as a hot standby -- it is a rehearsal/cutover target. # # Differences from the home Docker/root version, and why: # # :z on ./volumes/media (LOWERCASE, shared) # Both server and worker mount this same path. `:Z` assigns a PRIVATE SELinux MCS # category per container, so the second container to start would relabel it and # lock the first one out. Shared mounts must use `:z`. The per-container mounts # (server/custom-templates, worker/custom-templates, worker/certs) are exclusive # and correctly use `:Z`. # # No redis anywhere # authentik 2026.x dropped the Redis dependency (Postgres-backed now). The home # stack has no redis container and no AUTHENTIK_REDIS__* vars either -- verified, # not assumed. Do not "helpfully" add one. # # Postgres is the shared VPS instance # AUTHENTIK_POSTGRESQL__HOST=postgresql resolves over nginx-bridge to the same # container N8n and NPM use. Role + database `authentik` were created there with # the same PG_PASS as home, so .env needed no edits. # # .env is copied verbatim from home and contains AUTHENTIK_SECRET_KEY. That key MUST # match the one the database was encrypted with, or tokens and stored secrets break. # It is mode 600 -- never print it, never commit it. # # NOT YET SERVING auth.gbrown.org. That DNS record still points home. Cutover = create # an explicit auth.gbrown.org record pointing at this VPS (an explicit record overrides # the *.gbrown.org wildcard) plus an NPM proxy host to http://authentik-server:9000. networks: nginx-bridge: external: true services: server: image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2} container_name: authentik-server hostname: authentik-server domainname: auth.gbrown.org networks: - nginx-bridge command: server # Bound to the WireGuard address ONLY -- never listens on eth0, so this is not # reachable from the internet regardless of firewall state. Home's NPM uses it for # forward-auth (14 proxy hosts point at http://192.168.2.2:9000/outpost.goauthentik.io). # Do NOT change this to a bare "9000:9000"; that would expose it on the public # interface. Port 9443 is deliberately NOT published -- portainer already uses it. ports: - "192.168.2.2:9000:9000" environment: AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} TZ: America/New_York env_file: - .env volumes: - ./volumes/server/custom-templates:/templates:Z - ./volumes/media:/data/media:z labels: com.centurylinklabs.watchtower.enable: "true" restart: unless-stopped tty: true worker: image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2} container_name: authentik-worker hostname: authentik-worker networks: - nginx-bridge command: worker environment: AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} TZ: America/New_York env_file: - .env volumes: - ./volumes/media:/data/media:z - ./volumes/worker/certs:/certs:Z - ./volumes/worker/custom-templates:/templates:Z labels: com.centurylinklabs.watchtower.enable: "true" restart: unless-stopped tty: true