From c637fea0d0f302c5c2058cad5d1990e61c48ac7a Mon Sep 17 00:00:00 2001 From: soraefir Date: Sun, 10 May 2026 18:29:53 +0200 Subject: [PATCH] Add authentik blueprints --- .../containers/{defs => apps}/authentik.nix | 27 +++++++- .../containers/{defs => apps}/collabora.nix | 0 .../containers/{defs => apps}/etherpad.nix | 0 .../containers/{defs => apps}/nextcloud.nix | 68 ++++++++++++++----- .../containers/{defs => apps}/traefik.nix | 0 modules/server/containers/builder.nix | 6 ++ .../containers/data/authentik/nextcloud.yaml | 49 +++++++++++++ .../containers/data/authentik/traefik.yaml | 35 ++++++++++ modules/server/containers/default.nix | 10 +-- 9 files changed, 170 insertions(+), 25 deletions(-) rename modules/server/containers/{defs => apps}/authentik.nix (72%) rename modules/server/containers/{defs => apps}/collabora.nix (100%) rename modules/server/containers/{defs => apps}/etherpad.nix (100%) rename modules/server/containers/{defs => apps}/nextcloud.nix (65%) rename modules/server/containers/{defs => apps}/traefik.nix (100%) create mode 100644 modules/server/containers/data/authentik/nextcloud.yaml create mode 100644 modules/server/containers/data/authentik/traefik.yaml diff --git a/modules/server/containers/defs/authentik.nix b/modules/server/containers/apps/authentik.nix similarity index 72% rename from modules/server/containers/defs/authentik.nix rename to modules/server/containers/apps/authentik.nix index 0811c64..708005c 100644 --- a/modules/server/containers/defs/authentik.nix +++ b/modules/server/containers/apps/authentik.nix @@ -1,7 +1,14 @@ { config, containerCfg, pkgs, lib, builder, name, ... }: let -version = "2026.2.2"; -serverCfg = config.syscfg.server; + version = "2026.2.2"; + serverCfg = config.syscfg.server; + authentikData = ${builder.mkData { + name = "authentik"; dir = "authentik"; vars = { + NEXTCLOUD_DOMAIN = "${serverCfg.containers.nextcloud.subdomain or "nextcloud"}.${serverCfg.hostDomain}"; + AUTHENTIK_DOMAIN = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; + COOKIE_DOMAIN = "*.${serverCfg.hostDomain}"; + }; + }}; in { paths = [{ path="${serverCfg.configPath}/authentik/media"; @@ -41,6 +48,7 @@ in { volumes = [ "${serverCfg.configPath}/authentik/media:/media" "${serverCfg.configPath}/authentik/templates:/templates" + "${authentikData}:/blueprints/custom:ro" ]; }; }; @@ -62,9 +70,24 @@ in { volumes = [ "${serverCfg.configPath}/authentik/media:/media" "${serverCfg.configPath}/authentik/templates:/templates" + "${authentikData}:/blueprints/custom:ro" # "/var/run/podman/podman.sock:/var/run/docker.sock" #PODMAN GROUP FOR SOCKET ACCESS ]; }; }; }; + + + setup = { + trigger="worker"; + script = pkgs.writeShellScript "setup" '' + # Define the command wrapper + AK="${pkgs.podman}/bin/podman --events-backend=none exec -u root authentik-worker ak" + + $AK blueprint_apply /blueprints/custom/traefik.yaml + ${lib.optionalString (serverCfg.containers ? nextcloud) ''$AK blueprint_apply /blueprints/custom/nextcloud.yaml''} + + echo "Completed Authentik Setup" + ''; + }; } diff --git a/modules/server/containers/defs/collabora.nix b/modules/server/containers/apps/collabora.nix similarity index 100% rename from modules/server/containers/defs/collabora.nix rename to modules/server/containers/apps/collabora.nix diff --git a/modules/server/containers/defs/etherpad.nix b/modules/server/containers/apps/etherpad.nix similarity index 100% rename from modules/server/containers/defs/etherpad.nix rename to modules/server/containers/apps/etherpad.nix diff --git a/modules/server/containers/defs/nextcloud.nix b/modules/server/containers/apps/nextcloud.nix similarity index 65% rename from modules/server/containers/defs/nextcloud.nix rename to modules/server/containers/apps/nextcloud.nix index fdf7645..bc83957 100644 --- a/modules/server/containers/defs/nextcloud.nix +++ b/modules/server/containers/apps/nextcloud.nix @@ -44,7 +44,7 @@ in { "traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true"; }; extraOptions = [ - "--tmpfs=/tmp:rw,noexec,nosuid,size=256m" + "--tmpfs=/tmp:rw,noexec,nosuid,size=512m" ]; overrides = { ports = if containerCfg.pubPort!=null && containerCfg.port!=null then [ "${toString containerCfg.pubPort}:${toString containerCfg.port}" ] else []; @@ -85,18 +85,19 @@ in { $OCC config:system:set default_locale --value="en_CH" echo "Applying Apps..." - $OCC app:disable activity - $OCC app:disable app_api - $OCC app:disable comments - $OCC app:disable firstrunwizard + $OCC app:disable activity || true + $OCC app:disable app_api || true + $OCC app:disable comments || true + $OCC app:disable firstrunwizard || true $OCC config:system:set show_first_run_wizard --type=bool --value=false - $OCC app:disable nextcloud_announcements - $OCC app:disable oauth2 - $OCC app:disable recommendations - $OCC app:disable sharebymail - $OCC app:disable support - $OCC app:disable updatenotification - $OCC app:disable user_status + $OCC app:disable nextcloud_announcements || true + $OCC app:disable oauth2 || true + $OCC app:disable recommendations || true + $OCC app:disable sharebymail || true + $OCC app:disable support || true + $OCC app:disable survey_client || true + $OCC app:disable updatenotification || true + $OCC app:disable user_status || true $OCC app:install calendar || true $OCC app:install calendar || true @@ -110,11 +111,15 @@ in { $OCC app:install ownpad || true $OCC app:install previewgenerator || true $OCC app:install richdocuments || true + ${lib.optionalString (serverCfg.containers ? collabora == false) ''$OCC app:install richdocumentscode || true''} # $OCC app:install side_menu || true $OCC app:install spreed || true - # $OCC app:install user_saml || true + ${lib.optionalString (serverCfg.containers ? authentik) ''$OCC app:install user_saml || true''} echo "Applying Apps Settings..." + $OCC config:system:set enabledPreviewProviders --value='["OC\\Preview\\Movie", "OC\\Preview\\PNG", "OC\\Preview\\JPEG", "OC\\Preview\\GIF", "OC\\Preview\\HEIC", "OC\\Preview\\RAW"]' --type=json + $OCC config:app:set cospend allow_federation --value="yes" + ${lib.optionalString (serverCfg.containers ? ethercalc) '' $OCC config:app:set ownpad ownpad_ethercalc_enable --value="yes" $OCC config:app:set ownpad ownpad_ethercalc_host --value="https:\/\/${serverCfg.containers.ethercalc.subdomain}.${serverCfg.hostDomain}" @@ -126,17 +131,44 @@ in { ${lib.optionalString (serverCfg.containers ? collabora) '' $OCC config:app:set richdocuments wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.hostDomain}/" $OCC config:app:set richdocuments public_wopi_url --value="https://${serverCfg.containers.collabora.subdomain}.${serverCfg.hostDomain}" + $OCC config:app:set richdocuments wopi_allowlist --value="10.0.0.0/8" + ''} + ${lib.optionalString (serverCfg.containers ? authentik) '' + $OCC saml:config:set --general-idp0_display_name="authentik" + $OCC saml:config:set --general-uid_mapping="http://schemas.goauthentik.io/2021/02/saml/username" + $OCC saml:config:set --idp-entityId="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}" + $OCC saml:config:set --idp-singleSignOnService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/${containerCfg.subdomain}/sso/binding/redirect/" + $OCC saml:config:set --idp-singleLogoutService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/${containerCfg.subdomain}/slo/binding/redirect/" + $OCC saml:config:set --idp-x509cert="MII..." + + $OCC saml:config:set --saml-attribute-mapping-displayName_mapping="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" + $OCC saml:config:set --saml-attribute-mapping-email_mapping="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + $OCC saml:config:set --saml-attribute-mapping-group_mapping="http://schemas.xmlsoap.org/claims/Group" + $OCC saml:config:set --general-group_provisioning="0" + $OCC config:app:set user_saml general-require_provisioning_groups --value="0" + # $OCC saml:config:set --general-allowed_groups="cloud,admin" ''} # configure side_menu ... - # configure user_saml (HOW ?) - - $OCC config:system:set enabledPreviewProviders --value='["OC\\Preview\\Movie", "OC\\Preview\\PNG", "OC\\Preview\\JPEG", "OC\\Preview\\GIF", "OC\\Preview\\HEIC", "OC\\Preview\\RAW"]' --type=json - + FOLDERS=$($OCC teamfolders:list --format=json) + ${builtins.concatStringsSep "\n" (map (name: '' + if ! echo "$FOLDERS" | grep -q '"name":"${name}"'; then + $OCC teamfolders:create "${name}" + fi + '') containerCfg.extra.teamFolders or [])} + SERVERS=$($OCC federation:list-servers --format=json) + ${builtins.concatStringsSep "\n" (map (domain: '' + if ! echo "$SERVERS" | grep -q "${domain}"; then + $OCC federation:add-server "https://${domain}" + fi + '') containerCfg.extra.federatedServers or [])} + $OCC config:app:set systemtags allow_user_creating --value="no" + echo "Applying Theme..." $OCC config:app:set theming url --value="https://${containerCfg.subdomain}.${serverCfg.hostDomain}" ${lib.optionalString (containerCfg.extra ? name) ''$OCC config:app:set theming name --value="${containerCfg.extra.name}"''} ${lib.optionalString (containerCfg.extra ? slogan) ''$OCC config:app:set theming slogan --value="${containerCfg.extra.slogan}"''} - $OCC config:app:set theming color --value="${serverCfg.colorScheme.palette.base0C}" + $OCC config:app:set theming background_color --value="${serverCfg.colorScheme.palette.base0C}" + $OCC config:app:set theming primary_color --value="${serverCfg.colorScheme.palette.base0C}" #$OCC theming:config logo {serverCfg.colorScheme.logo} #$OCC theming:config logoheader {serverCfg.colorScheme.logo} diff --git a/modules/server/containers/defs/traefik.nix b/modules/server/containers/apps/traefik.nix similarity index 100% rename from modules/server/containers/defs/traefik.nix rename to modules/server/containers/apps/traefik.nix diff --git a/modules/server/containers/builder.nix b/modules/server/containers/builder.nix index 7cd74b9..487bdfe 100644 --- a/modules/server/containers/builder.nix +++ b/modules/server/containers/builder.nix @@ -33,5 +33,11 @@ let in lib.recursiveUpdate base overrides; in { mkContainer = builder; + mkData = { name, dir, var?{} }: pkgs.runCommand name vars '' + export PATH="${pkgs.buildPackages.substituteAll}/bin:$PATH" + mkdir -p $out + cp -r ./data/${dir}/. $out/ + find $out -type f -exec substituteAllInPlace {} + + ''; host = "host.containers.internal"; } \ No newline at end of file diff --git a/modules/server/containers/data/authentik/nextcloud.yaml b/modules/server/containers/data/authentik/nextcloud.yaml new file mode 100644 index 0000000..6f207bf --- /dev/null +++ b/modules/server/containers/data/authentik/nextcloud.yaml @@ -0,0 +1,49 @@ +version: 1 +metadata: + name: nextcloud-saml-setup +entries: + # 1. Create the SAML Provider + - model: authentik_providers_saml.samlprovider + identifiers: + name: Nextcloud SAML + attrs: + authorization_flow: + !Find [ + authentik_flows.flow, + [slug, default-provider-authorization-explicit-consent], + ] + # Adjust these URLs to match your Nextcloud domain + acs_url: https://@NEXTCLOUD_DOMAIN@/apps/user_saml/saml/acs + audience: https://@NEXTCLOUD_DOMAIN@/apps/user_saml/saml/metadata + issuer: https://@AUTHENTIK_DOMAIN@ + sp_binding: post + # Map the attributes for Name, Email, and Groups + property_mappings: + - !Find [ + authentik_core.propertymapping, + [managed, goauthentik.io/providers/saml/ms-name], + ] + - !Find [ + authentik_core.propertymapping, + [managed, goauthentik.io/providers/saml/ms-email], + ] + - !Find [ + authentik_core.propertymapping, + [managed, goauthentik.io/providers/saml/ms-groups], + ] + # Select your signing certificate (default is usually self-signed) + signing_kp: + !Find [ + authentik_crypto.certificatekeypair, + [name, "authentik Self-signed Certificate"], + ] + + # 2. Create the Application + - model: authentik_core.application + identifiers: + slug: nextcloud + attrs: + name: Nextcloud + provider: + !Find [authentik_providers_saml.samlprovider, [name, Nextcloud SAML]] + group: "Cloud Services" diff --git a/modules/server/containers/data/authentik/traefik.yaml b/modules/server/containers/data/authentik/traefik.yaml new file mode 100644 index 0000000..441c4cb --- /dev/null +++ b/modules/server/containers/data/authentik/traefik.yaml @@ -0,0 +1,35 @@ +version: 1 +metadata: + name: domain-wide-proxy-setup +entries: + # 1. The Provider + - model: authentik_providers_proxy.proxyprovider + identifiers: + name: Domain Wide Proxy + attrs: + authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-explicit-consent]] + + # For domain-wide, external_host must be the root domain or the auth domain + external_host: https://@AUTHENTIK_DOMAIN@ + + # This allows the cookie to work across *.@COOKIE_DOMAIN@ + cookie_domain: @COOKIE_DOMAIN@ + + mode: forward_auth + intercept_header_auth: true + + # 2. The Application (Required to link the provider) + - model: authentik_core.application + identifiers: + slug: authentik-proxy-root + attrs: + name: "Domain Auth Provider" + provider: !Find [authentik_providers_proxy.proxyprovider, [name, Domain Wide Proxy]] + + # 3. Add to Outpost + - model: authentik_outposts.outpost + identifiers: + name: authentik Embedded Outpost + attrs: + providers: + - !Find [authentik_providers_proxy.proxyprovider, [name, Domain Wide Proxy]] diff --git a/modules/server/containers/default.nix b/modules/server/containers/default.nix index 65bb7d3..e326c42 100644 --- a/modules/server/containers/default.nix +++ b/modules/server/containers/default.nix @@ -4,15 +4,15 @@ let builder = import ./builder.nix { inherit config lib serverCfg; }; enabledConfigs = lib.filterAttrs (name: c: c.enable) serverCfg.containers; containerSetsList = lib.mapAttrsToList (name: containerCfg: - let defs = import (./defs + "/${name}.nix") {inherit config pkgs lib containerCfg builder name;}; + let apps = import (./apps + "/${name}.nix") {inherit config pkgs lib containerCfg builder name;}; in{ name = name; containers = lib.mapAttrs' (cName: cValue: lib.nameValuePair "${name}-${cName}" cValue - ) defs.containers; - paths = defs.paths or []; - setup = defs.setup or null; - cron = defs.cron or []; + ) apps.containers; + paths = apps.paths or []; + setup = apps.setup or null; + cron = apps.cron or []; } ) enabledConfigs; mergedContainers = lib.attrsets.mergeAttrsList (lib.map(e: e.containers) containerSetsList);