reference-ansible/inventories/demo-gymburgdorf/host_vars/application/authentik.yml
Simon Bärlocher 2206b809e7
fix(demo-gymburgdorf): route cross-host ForwardAuth via dedicated outpost FQDN
Storage Traefik calling the public auth.gymb.* FQDN hit Authentik's ASGI
handler, which 404s the /outpost.goauthentik.io/auth/traefik path. Add a
dedicated outpost.auth.int.gymb.* FQDN outside authentik_domains so the
request falls through to the embedded outpost, pinned to the application
host via traefik_extra_hosts to stay on the LAN.

- authentik: add authentik_outpost_domains; allow users group on drawio
  proxy so the Nextcloud drawio iframe works for non-admins
- garage: point webui ForwardAuth at the new outpost FQDN
- homarr: use public OIDC issuer to match the iss claim, enable
  auto-login, pin auth FQDN to LAN via extra_hosts
- opnform: intercept / and /login for SSO, keep break-glass bypass
- drawio: align comments with admins+users allow-list
2026-06-04 11:07:48 +02:00

162 lines
6.3 KiB
YAML

---
# Bao secret expected at <mount>/data/authentik with keys:
# secret_key, postgres_password, admin_password,
# ldap_outpost_token,
# nextcloud_oidc_secret,
# opnform_oidc_secret, homarr_oidc_secret, bookstack_oidc_secret
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
# Canonical public FQDN browsers and OIDC iss-claim use.
authentik_domains:
- "auth.gymb.souveredu.ch"
# Internal FQDN for server-to-server calls (Nextcloud OIDC discovery,
# token, userinfo; LDAP outpost configuration pull). Traefik rewrites
# the Host header to `authentik_domains[0]` on these routers so authentik
# still emits issuer URLs against the public hostname — that keeps the
# iss claim matching what the browser sees while the traffic itself
# stays inside the LAN (the DMZ has no hairpin-NAT for the public IP).
authentik_host_rewrite_domains:
- "auth.int.gymb.souveredu.ch"
authentik_secret_key: "{{ _authentik.secret_key }}"
authentik_postgres_password: "{{ _authentik.postgres_password }}"
# Dedicated FQDN for cross-host ForwardAuth (storage Traefik calling
# /outpost.goauthentik.io/auth/traefik). Routing through the public
# auth.gymb.* FQDN doesn't work — Authentik sees Host: auth.gymb.* and
# routes to ASGI which 404s the outpost path. This FQDN sits outside
# authentik_domains so the same request falls through to the embedded
# outpost handler (which matches the protected app via X-Forwarded-Host).
authentik_outpost_domains:
- "outpost.auth.int.gymb.souveredu.ch"
# LDAP outpost (provider for nextcloud)
authentik_ldap_apps:
- slug: ldap
name: LDAP
base_dn: "dc=gymb,dc=souveredu,dc=ch"
search_group: admins
authentik_ldap_outpost:
name: "ldap-outpost"
token: "{{ _authentik.ldap_outpost_token }}"
config:
# Outpost pulls config from authentik over the internal FQDN — keeps
# the round-trip in the LAN with a valid cert.
authentik_host: "https://auth.int.gymb.souveredu.ch/"
log_level: "info"
# Proxy providers (ForwardAuth) — gate downstream services behind
# authentik. The embedded outpost (which authentik ships out of the box)
# hosts these providers under /outpost.goauthentik.io/auth/traefik on the
# canonical FQDN; the service-side traefik attaches a ForwardAuth
# middleware that talks to that endpoint.
authentik_proxy_apps:
- slug: drawio
name: Drawio
external_host: "https://draw.gymb.souveredu.ch"
internal_host: "http://drawio:8080"
# drawio is embedded in Nextcloud as an iframe (nextcloud_enable_drawio).
# Every authenticated Nextcloud user must therefore pass the ForwardAuth
# gate, otherwise the editor loads a 403 inside the iframe. Allow both
# standard groups; tightening this back to admins-only would break the
# Nextcloud integration for regular users.
allowed_groups:
- admins
- users
flows:
authentication_slug: default-authentication-flow
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
- slug: garage-webui
name: "Garage S3 Console"
external_host: "https://console.s3.gymb.souveredu.ch"
internal_host: "http://garage-webui:3909"
allowed_groups:
- admins
flows:
authentication_slug: default-authentication-flow
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
# Bind both proxy providers to authentik's built-in embedded outpost so
# we don't have to deploy a separate proxy outpost container. The
# embedded outpost listens on the same host:9000 as the authentik server
# and exposes /outpost.goauthentik.io/auth/traefik for ForwardAuth.
authentik_proxy_outposts:
- name: "authentik Embedded Outpost"
type: proxy
providers:
- drawio
- garage-webui
# OIDC clients
authentik_oidc_apps:
- slug: nextcloud
name: Nextcloud
client_id: nextcloud
client_secret: "{{ _authentik.nextcloud_oidc_secret }}"
redirect_uris:
- url: "https://cloud.gymb.souveredu.ch/apps/user_oidc/code"
matching_mode: strict
signing_key_name: "authentik Self-signed Certificate"
flows:
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
scopes: [openid, email, profile, offline_access]
- slug: opnform
name: OpnForm
client_id: opnform
client_secret: "{{ _authentik.opnform_oidc_secret }}"
redirect_uris:
- url: "https://forms.gymb.souveredu.ch/auth/authentik/callback"
matching_mode: strict
signing_key_name: "authentik Self-signed Certificate"
flows:
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
# No separate `groups` scope — authentik's default `profile` mapping
# already emits a `groups` claim built from request.user.groups, so
# OpnForm's admin-group mapping works without an extra scope.
scopes: [openid, email, profile]
- slug: homarr
name: Homarr
client_id: homarr
client_secret: "{{ _authentik.homarr_oidc_secret }}"
redirect_uris:
- url: "https://home.gymb.souveredu.ch/api/auth/callback/oidc"
matching_mode: strict
signing_key_name: "authentik Self-signed Certificate"
flows:
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
scopes: [openid, email, profile]
- slug: bookstack
name: BookStack
client_id: bookstack
client_secret: "{{ _authentik.bookstack_oidc_secret }}"
redirect_uris:
- url: "https://wiki.gymb.souveredu.ch/oidc/callback"
matching_mode: strict
signing_key_name: "authentik Self-signed Certificate"
flows:
authorization_slug: default-provider-authorization-implicit-consent
invalidation_slug: default-provider-invalidation-flow
scopes: [openid, email, profile]
authentik_groups:
- name: admins
- name: users
- name: opnform-admins
- name: homarr-admins
- name: bookstack-admins
authentik_local_users:
- username: akadmin
name: "Authentik Admin"
email: "admin@gymb.souveredu.ch"
password: "{{ _authentik.admin_password }}"
is_active: true
groups:
- authentik Admins
- admins