Files
Panama/server/containers/Authentik/compose.yml
T
Gabriel Brown f33da41cc6 Panama learns what a server is: from a root login to running containers
A machine's role is now the interview's first question and the one answer
Panama records. Servers get the same shell minus the screen: core packages,
nvm, Bun, Claude Code and Codex (desktops get Codex too), linger, rootless
ports from 80, firewalld, the nginx-bridge network, and a nightly image
updater that replaced watchtower for cause.

server/containers/ carries junior's 23 compose services -- secrets moved to
per-machine .env files that never enter this public repo, every transformed
compose proven to render byte-identical to what is live. 'panama server'
enables, disables and relinks them; nothing here restarts a running service.
'boot --server' walks a fresh VPS from its root login to a normal install.

Five new contracts pin the secrets rule, the catalog's shape, panama-server's
behavior, the role plumbing, and the dotfile classification.

Claude-Session: https://claude.ai/code/session_01NU5JGiN3JfzqrLQB6wmJ1E
2026-08-25 23:11:49 -04:00

94 lines
3.8 KiB
YAML

# 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