--- # Bao secret /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) }}" # 33.0.2 hits the PHP 8.4 TypeError in UserConfig::getValueBool() that # user_ldap triggers on every authenticated request (nextcloud/server # #59629; fix in 33.0.3). Pin to the patched tag. nextcloud_image: "nextcloud:33.0.3-fpm" # 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 # OIDC server-to-server discovery / token / userinfo goes to # auth.int.gymb.souveredu.ch (LAN, RFC1918). Nextcloud's DnsPinMiddleware # would otherwise block that as "local server access". nextcloud_allow_local_remote_servers: true # Share the LDAP docker network with the authentik LDAP outpost nextcloud_extra_networks: - 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) 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 }}" # Discovery via the internal FQDN (LAN-only) — the DMZ has no # hairpin-NAT for the public IP, so server-to-server calls to # auth.gymb.* would time out. The traefik router for auth.int.* # rewrites the Host header to auth.gymb.souveredu.ch before the # request reaches authentik, so the iss claim authentik emits still # matches the public hostname the browser sees during login. discovery_url: "https://auth.int.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