Skip to content

Authentik

Single sign-on and identity provider for the rest of the stack. Services either wire native OIDC/SAML to it, or sit behind its Traefik forward-auth middleware.

Runtime Container (Docker Swarm), 4 containers: server, worker, postgresql, redis
Tier Core
Node swarm-core
Image ghcr.io/goauthentik/server:2026.5.5 (server and worker share this image)
URL https://authentik.lab.riversfamily.uk
Auth N/A (is the identity provider)
Source ansible/stacks/core/authentik/

Configuration

Authentik applications and providers are declarative blueprints (YAML), applied by the worker on startup from /blueprints/custom, not clicked together in the UI. 13 blueprint templates live under ansible/stacks/core/authentik/blueprints/ and are rendered as stack_extra_templates by deploy-stacks.yml — they are not picked up automatically, so a new OIDC/SAML consumer needs a blueprint entry added to that playbook. Each entry's dest must keep the .yaml extension: Authentik's custom-blueprint auto-discovery under /blueprints/custom only scans for .yaml, and its dir_mode: "0755" must stay world-readable, since the worker runs as a non-root user and the shared stack role's directory default (0750, root-only) would otherwise block it from reading the mount.

The blueprints cover: a per-service OIDC provider for each native-OIDC consumer (vaultwarden, gitea, mealie, netbox, immich, paperless-ngx, matomo, linkding, openproject), SAML providers for kimai/snipe-it/fleet plus a shared saml-signing-cert.yaml.j2 (must render before any SAML provider that references it — order is enforced in deploy-stacks.yml), and forward-auth.yaml.j2 defining the single forward_domain proxy provider used by every forward-auth-gated app.

The reusable forward-auth middleware, authentik@swarm, is defined on the server service itself:

traefik.http.middlewares.authentik.forwardauth.address=http://authentik_server:9000/outpost.goauthentik.io/auth/traefik

Volumes

Volume Path Backing Contents
media /media Local Shared by server and worker
redis /data Local Redis persistence
database /var/lib/postgresql/data Local Postgres data — never NFS
(rendered) /blueprints/custom The 13 blueprint templates

Networking

server joins both the shared traefik network (for its Traefik route) and this stack's private internal network. worker, postgresql and redis join internal only — they are unreachable from every other stack.

Secrets

Vault variable Delivered as Purpose
vault_authentik_secret_key Swarm secret Django-style secret key
vault_authentik_postgres_password Swarm secret Postgres password
vault_authentik_bootstrap_password Swarm secret Initial akadmin password
vault_authentik_bootstrap_token Swarm secret Initial API token
vault_authentik_saml_signing_cert / _key Env var, embedded in blueprint Shared SAML signing certificate used by kimai, snipe-it, fleet
vault_<service>_oidc_client_secret (9 services) Env var per service Client secret shared with each OIDC consumer's blueprint

Gotchas

  • The chicken-and-egg problem (Authentik needs to exist before a service can authenticate against it, but the client secret must match on both sides) is resolved by generating each OIDC/SAML client secret once in Vault and writing it into both the Authentik blueprint and the consuming service's config — the secret is set on both sides, never read back from Authentik after the fact.
  • The authoritative reference for whether a given service supports OIDC/SAML, and exactly how to wire it, is the Authentik integrations catalogue. If a service has no guide there, it falls back to forward-auth.
  • The authentik@swarm middleware trusts the forwarded headers (trustForwardHeader=true) and sets X-authentik-username, -groups, -email, -name, -uid. Any service consuming those headers directly (see Firefly-III) depends on the middleware to stop header spoofing — it is the only thing standing between a client and impersonating another user.