chore(demo-gymburgdorf): finish ACME, LDAP, DMZ routing for live inventory
- ACME via DNS-01 against internal NS (172.16.9.169) with TCP-only + disableANSChecks so the DMZ traefik can issue LE certs without reaching public NS IPs. - Migrate single-domain vars to `*_domains` lists (authentik, nextcloud, collabora, garage_s3) so public + *.int.* SANs share one cert and server-to-server traffic stays in the LAN. - Wire `traefik_dmz_exposed_services` per backend host (application, storage) with explicit `backend_host` overrides pointing at internal FQDNs — DMZ traefik now validates upstream certs against SAN names. - Nextcloud notify_push setup on internal FQDN to avoid DMZ hairpin; collabora WOPI / authentik LDAP outpost wired to *.int.* equivalents.
This commit is contained in:
parent
82f0db8fe3
commit
c67e9aac43
13 changed files with 552 additions and 170 deletions
|
|
@ -5,7 +5,13 @@
|
|||
# nextcloud_oidc_secret
|
||||
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
|
||||
|
||||
authentik_domain: "auth.gymb.souveredu.ch"
|
||||
# First entry is the canonical public FQDN. Additional entries cover
|
||||
# internal *.int.* names so server-to-server traffic (e.g. the LDAP
|
||||
# outpost) hits authentik on a name with a valid internal cert and
|
||||
# skips the DMZ hop.
|
||||
authentik_domains:
|
||||
- "auth.gymb.souveredu.ch"
|
||||
- "auth.int.gymb.souveredu.ch"
|
||||
authentik_secret_key: "{{ _authentik.secret_key }}"
|
||||
authentik_postgres_password: "{{ _authentik.postgres_password }}"
|
||||
|
||||
|
|
@ -20,7 +26,9 @@ authentik_ldap_outpost:
|
|||
name: "ldap-outpost"
|
||||
token: "{{ _authentik.ldap_outpost_token }}"
|
||||
config:
|
||||
authentik_host: "https://auth.gymb.souveredu.ch/"
|
||||
# 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"
|
||||
|
||||
# OIDC clients
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@
|
|||
# authenticate against the authentik server it talks to.
|
||||
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
|
||||
|
||||
authentik_outpost_ldap_host: "https://auth.gymb.souveredu.ch"
|
||||
authentik_outpost_ldap_host: "https://auth.int.gymb.souveredu.ch"
|
||||
authentik_outpost_ldap_token: "{{ _authentik.ldap_outpost_token }}"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
---
|
||||
collabora_domain: "office.gymb.souveredu.ch"
|
||||
# First entry is the canonical public FQDN. Additional entries cover
|
||||
# internal *.int.* names so nextcloud's WOPI discovery hits collabora
|
||||
# in the LAN with a valid internal cert.
|
||||
collabora_domains:
|
||||
- "office.gymb.souveredu.ch"
|
||||
- "office.int.gymb.souveredu.ch"
|
||||
|
||||
# Hosts allowed to issue WOPI calls. Both names are listed so collabora
|
||||
# accepts the callback from nextcloud regardless of which FQDN it uses.
|
||||
collabora_allowed_domains:
|
||||
- "cloud.gymb.souveredu.ch"
|
||||
- "cloud.int.gymb.souveredu.ch"
|
||||
|
||||
collabora_frame_ancestors:
|
||||
- "cloud.gymb.souveredu.ch"
|
||||
|
|
|
|||
|
|
@ -4,16 +4,31 @@
|
|||
_nextcloud: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/nextcloud', url=vault_addr) }}"
|
||||
_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}"
|
||||
|
||||
nextcloud_domain: "cloud.gymb.souveredu.ch"
|
||||
# First entry is the canonical public FQDN (used for OVERWRITEHOST and
|
||||
# OIDC redirects). Additional entries cover internal *.int.* names so
|
||||
# collabora's WOPI callbacks hit nextcloud on a name with a valid
|
||||
# internal cert instead of routing through the DMZ.
|
||||
nextcloud_domains:
|
||||
- "cloud.gymb.souveredu.ch"
|
||||
- "cloud.int.gymb.souveredu.ch"
|
||||
nextcloud_postgres_password: "{{ _nextcloud.postgres_password }}"
|
||||
nextcloud_admin_user: admin
|
||||
nextcloud_admin_password: "{{ _nextcloud.admin_password }}"
|
||||
|
||||
nextcloud_enable_notify_push: true
|
||||
# Use the internal FQDN for the notify_push setup check so curl from the
|
||||
# nextcloud container hits the local traefik directly instead of
|
||||
# hairpinning through the DMZ reverseproxy.
|
||||
nextcloud_notify_push_domain: "cloud.int.gymb.souveredu.ch"
|
||||
|
||||
# Collabora integration
|
||||
# wopi_url (server-to-server: nextcloud calls collabora for discovery /
|
||||
# capabilities) goes to the internal FQDN so the call stays in the LAN.
|
||||
# public_wopi_url is what the browser loads the office iframe from — that
|
||||
# stays on the public name reachable through the DMZ.
|
||||
nextcloud_enable_collabora: true
|
||||
nextcloud_collabora_domain: "office.gymb.souveredu.ch"
|
||||
nextcloud_collabora_domain: "office.int.gymb.souveredu.ch"
|
||||
nextcloud_collabora_public_domain: "office.gymb.souveredu.ch"
|
||||
|
||||
# Draw.io integration
|
||||
nextcloud_enable_drawio: true
|
||||
|
|
@ -30,12 +45,14 @@ nextcloud_apps_to_install:
|
|||
- files_lock
|
||||
- notify_push
|
||||
|
||||
# S3 primary storage via Garage
|
||||
# S3 primary storage via Garage — server-to-server, so use the internal FQDN.
|
||||
# Resolves through the internal DNS to the storage host and presents a valid
|
||||
# cert from the local traefik on storage.
|
||||
nextcloud_use_s3_storage: true
|
||||
nextcloud_s3_key: "{{ lookup('digitalboard.core.garage_credentials', 'nextcloud', host='storage')['key_id'] }}"
|
||||
nextcloud_s3_secret: "{{ lookup('digitalboard.core.garage_credentials', 'nextcloud', host='storage')['secret_key'] }}"
|
||||
nextcloud_s3_bucket: "nextcloud"
|
||||
nextcloud_s3_host: "{{ hostvars['storage']['garage_s3_domain'] }}"
|
||||
nextcloud_s3_host: "s3.int.gymb.souveredu.ch"
|
||||
nextcloud_s3_port: 443
|
||||
nextcloud_s3_ssl: true
|
||||
nextcloud_s3_usepath_style: true
|
||||
|
|
@ -81,6 +98,11 @@ nextcloud_oidc_providers:
|
|||
display_name: "Login with Authentik"
|
||||
client_id: nextcloud
|
||||
client_secret: "{{ _authentik.nextcloud_oidc_secret }}"
|
||||
# Stays on the public FQDN: user_oidc validates the iss claim against
|
||||
# the discovery host, and authentik returns iss based on the request
|
||||
# host — using auth.int.* would break the iss match with what the
|
||||
# browser sees (auth.gymb.*). Routed via the DMZ for now; revisit if
|
||||
# this becomes a bottleneck.
|
||||
discovery_url: "https://auth.gymb.souveredu.ch/application/o/nextcloud/.well-known/openid-configuration"
|
||||
scope: "openid email profile"
|
||||
unique_uid: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
# Services hosted on `application` that the DMZ reverseproxy should
|
||||
# forward public traffic to. The DMZ traefik picks this up via
|
||||
# hostvars[backend].traefik_dmz_exposed_services and renders a router +
|
||||
# service for each entry into /config/services.yml.
|
||||
traefik_dmz_exposed_services:
|
||||
- name: authentik
|
||||
domain: auth.gymb.souveredu.ch
|
||||
backend_host: auth.int.gymb.souveredu.ch
|
||||
port: 443
|
||||
protocol: https
|
||||
- name: nextcloud
|
||||
domain: cloud.gymb.souveredu.ch
|
||||
backend_host: cloud.int.gymb.souveredu.ch
|
||||
port: 443
|
||||
protocol: https
|
||||
- name: collabora
|
||||
domain: office.gymb.souveredu.ch
|
||||
backend_host: office.int.gymb.souveredu.ch
|
||||
port: 443
|
||||
protocol: https
|
||||
- name: drawio
|
||||
domain: draw.gymb.souveredu.ch
|
||||
# No internal FQDN/cert for drawio yet — proxy by IP. Combined
|
||||
# with serversTransport `insecureSkipVerify` (handled by the
|
||||
# selfsigned-mode branch in the template), or accept the route's
|
||||
# 500 until the cert is wired up.
|
||||
port: 443
|
||||
protocol: https
|
||||
Loading…
Add table
Add a link
Reference in a new issue