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
94 lines
3.8 KiB
YAML
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
|