feat(demo): add full inventories for mbazürich and phbern #2
8 changed files with 58 additions and 110 deletions
|
|
@ -10,26 +10,9 @@ _authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data
|
||||||
authentik_domains:
|
authentik_domains:
|
||||||
- "auth.gymb.souveredu.ch"
|
- "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_secret_key: "{{ _authentik.secret_key }}"
|
||||||
authentik_postgres_password: "{{ _authentik.postgres_password }}"
|
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)
|
# LDAP outpost (provider for nextcloud)
|
||||||
authentik_ldap_apps:
|
authentik_ldap_apps:
|
||||||
- slug: ldap
|
- slug: ldap
|
||||||
|
|
@ -41,9 +24,10 @@ authentik_ldap_outpost:
|
||||||
name: "ldap-outpost"
|
name: "ldap-outpost"
|
||||||
token: "{{ _authentik.ldap_outpost_token }}"
|
token: "{{ _authentik.ldap_outpost_token }}"
|
||||||
config:
|
config:
|
||||||
# Outpost pulls config from authentik over the internal FQDN — keeps
|
# Outpost pulls config from authentik over the public FQDN, which
|
||||||
# the round-trip in the LAN with a valid cert.
|
# resolves (internal DNS view) to the DMZ reverseproxy the backend
|
||||||
authentik_host: "https://auth.int.gymb.souveredu.ch/"
|
# subnet can reach — keeps the round-trip in the LAN with a valid cert.
|
||||||
|
authentik_host: "https://auth.gymb.souveredu.ch/"
|
||||||
log_level: "info"
|
log_level: "info"
|
||||||
|
|
||||||
# Proxy providers (ForwardAuth) — gate downstream services behind
|
# Proxy providers (ForwardAuth) — gate downstream services behind
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,8 @@
|
||||||
# authenticate against the authentik server it talks to.
|
# authenticate against the authentik server it talks to.
|
||||||
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
|
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
|
||||||
|
|
||||||
authentik_outpost_ldap_host: "https://auth.int.gymb.souveredu.ch"
|
# Public FQDN resolves (internal DNS view) to the DMZ reverseproxy the
|
||||||
|
# backend subnet can reach, so the outpost->authentik round-trip stays in
|
||||||
|
# the LAN with a valid cert and matches the iss claim authentik emits.
|
||||||
|
authentik_outpost_ldap_host: "https://auth.gymb.souveredu.ch"
|
||||||
authentik_outpost_ldap_token: "{{ _authentik.ldap_outpost_token }}"
|
authentik_outpost_ldap_token: "{{ _authentik.ldap_outpost_token }}"
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ bookstack_admin_email: "admin@gymb.souveredu.ch"
|
||||||
bookstack_admin_name: "BookStack Admin"
|
bookstack_admin_name: "BookStack Admin"
|
||||||
|
|
||||||
# OIDC against Authentik. BookStack compares OIDC_ISSUER strictly against
|
# OIDC against Authentik. BookStack compares OIDC_ISSUER strictly against
|
||||||
# the `iss` claim in the discovery response. Authentik emits the public
|
# the `iss` claim in the discovery response, and Authentik emits the
|
||||||
# auth.gymb.* hostname there (host-rewrite middleware ensures the claim
|
# public auth.gymb.* hostname there, so the issuer must use the public
|
||||||
# matches what browsers see during login), so the issuer URL must use the
|
# FQDN. That FQDN resolves (internal DNS view) to the DMZ reverseproxy,
|
||||||
# public FQDN. Pinning auth.gymb.* in /etc/hosts below keeps the actual
|
# which the backend subnet can reach, so the server-to-server calls stay
|
||||||
# server-to-server traffic on the LAN.
|
# in the LAN.
|
||||||
bookstack_oidc_enabled: true
|
bookstack_oidc_enabled: true
|
||||||
bookstack_oidc_name: "Authentik"
|
bookstack_oidc_name: "Authentik"
|
||||||
bookstack_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/bookstack/"
|
bookstack_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/bookstack/"
|
||||||
|
|
@ -34,10 +34,3 @@ bookstack_oidc_additional_scopes: "openid profile email"
|
||||||
bookstack_oidc_user_to_groups: true
|
bookstack_oidc_user_to_groups: true
|
||||||
bookstack_oidc_groups_claim: "groups"
|
bookstack_oidc_groups_claim: "groups"
|
||||||
bookstack_oidc_auto_initiate: false
|
bookstack_oidc_auto_initiate: false
|
||||||
|
|
||||||
# Pin auth.gymb.* to the application host so server-to-server OIDC calls
|
|
||||||
# (discovery, token, userinfo, jwks) stay in the LAN and reach authentik
|
|
||||||
# directly without hairpinning through the DMZ (which has no NAT loop
|
|
||||||
# back to its own public IP).
|
|
||||||
bookstack_extra_hosts:
|
|
||||||
- "auth.gymb.souveredu.ch:172.16.19.101"
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ homarr_admin_password: "{{ _homarr.admin_password }}"
|
||||||
# AUTH_OIDC_AUTO_LOGIN bypasses the normal /login page.
|
# AUTH_OIDC_AUTO_LOGIN bypasses the normal /login page.
|
||||||
#
|
#
|
||||||
# Issuer must match the `iss` claim authentik emits, which is always the
|
# Issuer must match the `iss` claim authentik emits, which is always the
|
||||||
# public FQDN (authentik's host-rewrite middleware aligns the claim with
|
# public FQDN. Homarr (oauth4webapi) does a strict 1:1 comparison between
|
||||||
# what browsers see). Homarr (oauth4webapi) does a strict 1:1 comparison
|
# the discovery response's issuer and this URL — an internal FQDN here
|
||||||
# between the discovery response's issuer and this URL — using the
|
# fails with OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED. The public FQDN
|
||||||
# internal FQDN here fails with OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED.
|
# resolves (internal DNS view) to the DMZ reverseproxy, which the backend
|
||||||
# The extra_hosts pin below keeps the actual discovery/token/userinfo
|
# subnet can reach, so discovery/token/userinfo stay in the LAN.
|
||||||
# traffic on the LAN.
|
|
||||||
homarr_auth_providers: "credentials,oidc"
|
homarr_auth_providers: "credentials,oidc"
|
||||||
homarr_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/homarr/"
|
homarr_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/homarr/"
|
||||||
homarr_oidc_client_id: "homarr"
|
homarr_oidc_client_id: "homarr"
|
||||||
|
|
@ -33,14 +32,6 @@ homarr_oidc_scopes: "openid profile email groups"
|
||||||
homarr_oidc_groups_attribute: "groups"
|
homarr_oidc_groups_attribute: "groups"
|
||||||
homarr_oidc_auto_login: "true"
|
homarr_oidc_auto_login: "true"
|
||||||
|
|
||||||
# Pin the public authentik FQDN to the application host so OIDC
|
|
||||||
# discovery (and downstream token/userinfo) calls from the homarr
|
|
||||||
# container stay in the LAN. Without this, fetch() to auth.gymb.* would
|
|
||||||
# hit the public IP and time out in the DMZ (no hairpin-NAT). Same
|
|
||||||
# pattern as nextcloud_extra_hosts.
|
|
||||||
homarr_extra_hosts:
|
|
||||||
- "auth.gymb.souveredu.ch:172.16.19.101"
|
|
||||||
|
|
||||||
# Default board with shortcuts to the other gymburgdorf services. Width
|
# Default board with shortcuts to the other gymburgdorf services. Width
|
||||||
# values describe horizontal grid cells (1-10 desktop / 6 tablet / 2
|
# values describe horizontal grid cells (1-10 desktop / 6 tablet / 2
|
||||||
# mobile, packed left-to-right).
|
# mobile, packed left-to-right).
|
||||||
|
|
|
||||||
|
|
@ -62,25 +62,16 @@ nextcloud_s3_port: 443
|
||||||
nextcloud_s3_ssl: true
|
nextcloud_s3_ssl: true
|
||||||
nextcloud_s3_usepath_style: true
|
nextcloud_s3_usepath_style: true
|
||||||
|
|
||||||
# OIDC server-to-server discovery / token / userinfo goes to
|
# OIDC discovery/token/userinfo and the S3 backend both target FQDNs
|
||||||
# auth.int.gymb.souveredu.ch (LAN, RFC1918). Nextcloud's DnsPinMiddleware
|
# that resolve to RFC1918 addresses (auth.gymb.* via the reverseproxy,
|
||||||
# would otherwise block that as "local server access".
|
# s3.int.* directly), which Nextcloud's DnsPinMiddleware would otherwise
|
||||||
|
# block as "local server access".
|
||||||
nextcloud_allow_local_remote_servers: true
|
nextcloud_allow_local_remote_servers: true
|
||||||
|
|
||||||
# Share the LDAP docker network with the authentik LDAP outpost
|
# Share the LDAP docker network with the authentik LDAP outpost
|
||||||
nextcloud_extra_networks:
|
nextcloud_extra_networks:
|
||||||
- ldap
|
- ldap
|
||||||
|
|
||||||
# Pin the public authentik FQDN to the application host so server-to-server
|
|
||||||
# OIDC traffic (token, userinfo, jwks — endpoints the discovery doc lists
|
|
||||||
# under auth.gymb.* even when discovery itself is fetched via auth.int.*)
|
|
||||||
# stays in the LAN. Without this, curl in the PHP container would hit the
|
|
||||||
# public IP and time out in the DMZ (no hairpin-NAT). The DnsPin middleware
|
|
||||||
# only honours /etc/hosts when allow_local_remote_servers is enabled, so
|
|
||||||
# that flag (set above) is what makes this entry effective.
|
|
||||||
nextcloud_extra_hosts:
|
|
||||||
- "auth.gymb.souveredu.ch:172.16.19.101"
|
|
||||||
|
|
||||||
# LDAP backend (Authentik LDAP outpost)
|
# LDAP backend (Authentik LDAP outpost)
|
||||||
nextcloud_ldap_enabled: true
|
nextcloud_ldap_enabled: true
|
||||||
nextcloud_ldap_config:
|
nextcloud_ldap_config:
|
||||||
|
|
@ -118,13 +109,12 @@ nextcloud_oidc_providers:
|
||||||
display_name: "Login with Authentik"
|
display_name: "Login with Authentik"
|
||||||
client_id: nextcloud
|
client_id: nextcloud
|
||||||
client_secret: "{{ _authentik.nextcloud_oidc_secret }}"
|
client_secret: "{{ _authentik.nextcloud_oidc_secret }}"
|
||||||
# Discovery via the internal FQDN (LAN-only) — the DMZ has no
|
# Discovery via the public FQDN. It resolves (internal DNS view) to
|
||||||
# hairpin-NAT for the public IP, so server-to-server calls to
|
# the DMZ reverseproxy, which the backend subnet can now reach, so
|
||||||
# auth.gymb.* would time out. The traefik router for auth.int.*
|
# the server-to-server call stays in the LAN while the iss claim and
|
||||||
# rewrites the Host header to auth.gymb.souveredu.ch before the
|
# all listed endpoints match the public hostname the browser sees
|
||||||
# request reaches authentik, so the iss claim authentik emits still
|
# during login — no host-rewrite or /etc/hosts pin needed.
|
||||||
# matches the public hostname the browser sees during login.
|
discovery_url: "https://auth.gymb.souveredu.ch/application/o/nextcloud/.well-known/openid-configuration"
|
||||||
discovery_url: "https://auth.int.gymb.souveredu.ch/application/o/nextcloud/.well-known/openid-configuration"
|
|
||||||
scope: "openid email profile"
|
scope: "openid email profile"
|
||||||
unique_uid: true
|
unique_uid: true
|
||||||
mapping:
|
mapping:
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,13 @@ opnform_admin_name: "OpnForm Admin"
|
||||||
opnform_admin_email: "admin@gymb.souveredu.ch"
|
opnform_admin_email: "admin@gymb.souveredu.ch"
|
||||||
opnform_admin_password: "{{ _opnform.admin_password }}"
|
opnform_admin_password: "{{ _opnform.admin_password }}"
|
||||||
|
|
||||||
# OIDC against Authentik. Discovery via the internal FQDN keeps
|
# OIDC against Authentik. The public auth.gymb.* FQDN resolves (internal
|
||||||
# server-to-server traffic in the LAN; Authentik's host-rewrite router
|
# DNS view) to the DMZ reverseproxy, which the backend subnet can reach,
|
||||||
# rewrites the Host header to auth.gymb.* before the request reaches
|
# so OpnForm's discovery/token/userinfo calls stay in the LAN while the
|
||||||
# authentik so the iss claim still matches the public hostname browsers
|
# iss claim matches the public hostname browsers see during login.
|
||||||
# see during login.
|
|
||||||
opnform_oidc_enabled: true
|
opnform_oidc_enabled: true
|
||||||
# Issuer must use the public auth.gymb.* FQDN: OpnForm does OIDC
|
# Issuer must use the public FQDN: OpnForm validates the token's `iss`
|
||||||
# discovery and then validates the token's `iss` claim against this
|
# claim against this value, and Authentik emits the public hostname there.
|
||||||
# value. Authentik emits the public hostname in `iss` (its host-rewrite
|
|
||||||
# middleware keeps the claim aligned with what browsers see), so an
|
|
||||||
# internal-FQDN issuer here would fail iss validation. The extra_hosts
|
|
||||||
# pin below keeps the actual discovery/token/userinfo traffic on the LAN.
|
|
||||||
opnform_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/opnform/"
|
opnform_oidc_issuer: "https://auth.gymb.souveredu.ch/application/o/opnform/"
|
||||||
opnform_oidc_client_id: "opnform"
|
opnform_oidc_client_id: "opnform"
|
||||||
opnform_oidc_client_secret: "{{ _opnform.oidc_client_secret }}"
|
opnform_oidc_client_secret: "{{ _opnform.oidc_client_secret }}"
|
||||||
|
|
@ -53,10 +48,3 @@ opnform_oidc_force_login: true
|
||||||
# Break-glass: /login?bypass=1 reaches the email form when the IdP is
|
# Break-glass: /login?bypass=1 reaches the email form when the IdP is
|
||||||
# down.
|
# down.
|
||||||
opnform_oidc_sso_entrypoint: true
|
opnform_oidc_sso_entrypoint: true
|
||||||
|
|
||||||
# Pin auth.gymb.* to the application host so server-to-server OIDC
|
|
||||||
# calls (token, userinfo, jwks — endpoints discovery returns under the
|
|
||||||
# public hostname even when discovery itself is fetched via auth.int.*)
|
|
||||||
# stay in the LAN.
|
|
||||||
opnform_extra_hosts:
|
|
||||||
- "auth.gymb.souveredu.ch:172.16.19.101"
|
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,19 @@ garage_use_ssl: true
|
||||||
garage_webui_enabled: true
|
garage_webui_enabled: true
|
||||||
# Gate the WebUI behind authentik (admins-only, via policy-binding on the
|
# Gate the WebUI behind authentik (admins-only, via policy-binding on the
|
||||||
# authentik proxy app). Replaces the htpasswd Basic-Auth — AUTH_USER_PASS
|
# authentik proxy app). Replaces the htpasswd Basic-Auth — AUTH_USER_PASS
|
||||||
# is dropped from the compose env when this is true. The forwardauth URL
|
# is dropped from the compose env when this is true.
|
||||||
# uses a dedicated outpost-only FQDN that's deliberately outside
|
#
|
||||||
# authentik_domains so Authentik routes it to the embedded outpost (not
|
# The embedded outpost only serves the /outpost.goauthentik.io/auth path
|
||||||
# ASGI). The public auth.gymb.* FQDN would 404 here — Authentik routes
|
# when the request reaches authentik with Host set to a configured
|
||||||
# any Host matching an auth-domain to ASGI which doesn't serve the outpost
|
# authentik_domain (auth.gymb.*); it then matches the protected app
|
||||||
# path. The outpost itself then matches the protected app via
|
# (console.s3.*) via X-Forwarded-Host. So the ForwardAuth must hit the
|
||||||
# X-Forwarded-Host (Traefik forwards it via trustForwardHeader=true).
|
# app-host's `authentik` router (Host(auth.gymb), passHostHeader=true) —
|
||||||
# The FQDN is pinned to the application host via traefik_extra_hosts so
|
# NOT the DMZ reverseproxy (strips X-Forwarded-Host) and NOT the auth.int
|
||||||
# the request stays in the LAN.
|
# rewrite router (overwrites X-Forwarded-Host). auth.gymb.* is therefore
|
||||||
|
# pinned to the application host in storage/traefik.yml so this single hop
|
||||||
|
# preserves the forwarded headers and stays in the LAN.
|
||||||
garage_webui_authentik_forward_auth: true
|
garage_webui_authentik_forward_auth: true
|
||||||
garage_webui_authentik_forward_auth_url: "https://outpost.auth.int.gymb.souveredu.ch/outpost.goauthentik.io/auth/traefik"
|
garage_webui_authentik_forward_auth_url: "https://auth.gymb.souveredu.ch/outpost.goauthentik.io/auth/traefik"
|
||||||
# Kept for completeness — only used when authentik ForwardAuth is off.
|
# Kept for completeness — only used when authentik ForwardAuth is off.
|
||||||
garage_webui_username: "admin"
|
garage_webui_username: "admin"
|
||||||
garage_webui_password: "{{ _garage.webui_password | default('disabled') }}"
|
garage_webui_password: "{{ _garage.webui_password | default('disabled') }}"
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
---
|
---
|
||||||
# Local traefik needs to reach authentik for the ForwardAuth subrequest
|
# The garage-webui ForwardAuth middleware fires a subrequest to authentik
|
||||||
# the garage-webui router fires. The public IP is unreachable from this
|
# (see garage.yml). It must reach the app-host's `authentik` router
|
||||||
# subnet (no DMZ hairpin), so pin both auth FQDNs directly at the
|
# directly — going via the DMZ reverseproxy strips X-Forwarded-Host, which
|
||||||
# application host where authentik runs. Without this the forwardauth
|
# breaks the embedded outpost's app matching. The internal DNS view points
|
||||||
# middleware would time out and every garage-console request would 502.
|
# auth.gymb.* at the reverseproxy, so pin it to the application host here
|
||||||
# - auth.gymb.* covers any future server-to-server traffic on the public
|
# to force the single direct hop that preserves the forwarded headers.
|
||||||
# FQDN.
|
|
||||||
# - outpost.auth.int.gymb.* is the dedicated outpost endpoint actually
|
|
||||||
# used by the ForwardAuth middleware (see garage.yml). It exists only
|
|
||||||
# to skip Authentik's ASGI handler, which 404s the outpost path when
|
|
||||||
# Host is one of the configured authentik_domains.
|
|
||||||
traefik_extra_hosts:
|
traefik_extra_hosts:
|
||||||
- "auth.gymb.souveredu.ch:172.16.19.101"
|
- "auth.gymb.souveredu.ch:172.16.19.101"
|
||||||
- "outpost.auth.int.gymb.souveredu.ch:172.16.19.101"
|
|
||||||
|
|
||||||
# Services hosted on `storage` that the DMZ reverseproxy should forward
|
# Services hosted on `storage` that the DMZ reverseproxy should forward
|
||||||
# public traffic to. See application/traefik.yml for the mechanism.
|
# public traffic to. See application/traefik.yml for the mechanism.
|
||||||
|
|
@ -24,8 +18,11 @@ traefik_dmz_exposed_services:
|
||||||
protocol: https
|
protocol: https
|
||||||
- name: garage-webui
|
- name: garage-webui
|
||||||
domain: console.s3.gymb.souveredu.ch
|
domain: console.s3.gymb.souveredu.ch
|
||||||
# No internal FQDN/cert SAN for console.s3 yet — would need an
|
# Pre-existing limitation, orthogonal to the DNS cleanup: the DMZ
|
||||||
# extra_domain on garage-webui. Until then this route will 500
|
# verifies the storage backend cert (acme cert_mode), but with no
|
||||||
# against the storage backend (cert mismatch on raw IP).
|
# backend_host set it connects by IP, which the storage cert has no
|
||||||
|
# SAN for, so this route fails the TLS verify. Fixing it needs the
|
||||||
|
# garage role to expose a console extra_domain (e.g. console.s3.int.*)
|
||||||
|
# for the backend_host + cert SAN — tracked separately.
|
||||||
port: 443
|
port: 443
|
||||||
protocol: https
|
protocol: https
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue