reference-ansible/inventories/demo-gymburgdorf/host_vars/application/nextcloud.yml
Simon Bärlocher c67e9aac43
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.
2026-05-27 23:18:58 +02:00

112 lines
4.3 KiB
YAML

---
# Bao secret <mount>/data/nextcloud expected to contain:
# postgres_password, admin_password
_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) }}"
# 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.int.gymb.souveredu.ch"
nextcloud_collabora_public_domain: "office.gymb.souveredu.ch"
# Draw.io integration
nextcloud_enable_drawio: true
nextcloud_drawio_url: "https://draw.gymb.souveredu.ch"
nextcloud_apps_to_install:
- groupfolders
- richdocuments
- spreed
- user_ldap
- user_oidc
- whiteboard
- drawio
- files_lock
- notify_push
# 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: "s3.int.gymb.souveredu.ch"
nextcloud_s3_port: 443
nextcloud_s3_ssl: true
nextcloud_s3_usepath_style: true
# Share the LDAP docker network with the authentik LDAP outpost
nextcloud_extra_networks:
- ldap
# LDAP backend (Authentik LDAP outpost)
nextcloud_ldap_enabled: true
nextcloud_ldap_config:
ldapHost: "ldap://authentik-outpost-ldap-ldap-1"
ldapPort: "3389"
ldapAgentName: "cn=akadmin,ou=users,dc=gymb,dc=souveredu,dc=ch"
ldapAgentPassword: "{{ _authentik.admin_password }}"
ldapBase: "dc=gymb,dc=souveredu,dc=ch"
ldapBaseUsers: "ou=users,dc=gymb,dc=souveredu,dc=ch"
ldapTLS: "0"
turnOffCertCheck: "1"
ldapUserFilter: "(&(objectClass=user)(cn=*))"
ldapUserFilterObjectclass: "user"
ldapLoginFilter: "(&(objectClass=user)(cn=%uid))"
ldapLoginFilterUsername: "1"
ldapUserDisplayName: "cn"
ldapEmailAttribute: "mail"
ldapExpertUsernameAttr: "cn"
ldapExpertUUIDUserAttr: "uid"
ldapExpertUUIDGroupAttr: "uid"
ldapBaseGroups: "ou=groups,dc=gymb,dc=souveredu,dc=ch"
ldapGroupFilter: "(&(objectClass=group))"
ldapGroupFilterObjectclass: "group"
ldapGroupDisplayName: "cn"
ldapGroupMemberAssocAttr: "member"
ldapAdminGroup: "admins"
ldapCacheTTL: "600"
ldapPagingSize: "500"
ldapExperiencedAdmin: "1"
ldapConfigurationActive: "1"
# OIDC providers for login (Authentik)
nextcloud_oidc_providers:
- identifier: authentik
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
mapping:
uid: preferred_username
display_name: name
email: email