{ config, containerCfg, pkgs, lib, builder, name,... }: let version = "31"; serverCfg = config.syscfg.server; in { paths = [{ path="${serverCfg.dataPath}/nextcloud/www"; owner = "33:33"; mode = "0755"; }{ path="${serverCfg.dataPath}/nextcloud/data"; owner = "33:33"; mode = "0755"; backup = true; }]; containers = { server = builder.mkContainer { subdomain = containerCfg.subdomain; image = "nextcloud:${version}"; port = containerCfg.port; ip = containerCfg.ip; secret = name; extraEnv = { REDIS_HOST = builder.host; POSTGRES_HOST = builder.host; POSTGRES_USER = "nextcloud_user"; POSTGRES_DB = "nextcloud_db"; AUTHENTIK_POSTGRESQL__SSLMODE = "disable"; "NEXTCLOUD_TRUSTED_DOMAINS " = "${containerCfg.subdomain}.${serverCfg.hostDomain}"; "SMTP_HOST" = serverCfg.mailServer; "SMTP_NAME" = "mail_user"; "SMTP_PASSWORD" = "mail_password"; "MAIL_FROM_ADDRESS" = "${containerCfg.subdomain}@${serverCfg.hostDomain}"; "MAIL_DOMAIN" = serverCfg.mailDomain; "TRUSTED_PROXIES" = "10.10.0.0/16 192.168.0.0/16"; }; extraLabels = { "traefik.http.routers.${containerCfg.subdomain}.middlewares" = "sts_headers,${containerCfg.subdomain}-caldav"; "traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.permanent" = "true"; "traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.regex" = "https://(.*)/.well-known/(?:card|cal)dav"; "traefik.http.middlewares.${containerCfg.subdomain}-caldav.redirectregex.replacement" = "https://$1/remote.php/dav"; "traefik.http.middlewares.sts_headers.headers.stsSeconds" = "15552000"; "traefik.http.middlewares.sts_headers.headers.stsIncludeSubdomains" = "true"; }; extraOptions = [ "--tmpfs=/tmp:rw,noexec,nosuid,size=512m" ]; overrides = { ports = if containerCfg.pubPort!=null && containerCfg.port!=null then [ "${toString containerCfg.pubPort}:${toString containerCfg.port}" ] else []; volumes = [ "${serverCfg.dataPath}/nextcloud/www:/var/www/html" "${serverCfg.dataPath}/nextcloud/data:/var/www/html/data" ]; }; }; }; setup = { trigger="server"; script = pkgs.writeShellScript "setup" '' # Define the command wrapper OCC="${pkgs.podman}/bin/podman --events-backend=none exec -u www-data nextcloud-server php occ" echo "Waiting for Nextcloud container to start..." until $OCC status > /dev/null 2>&1; do sleep 2 done INSTALLED=$($OCC status --output=json | grep -o '"installed":false') if [ -z "$INSTALLED" ]; then echo "Running first-time setup..." # $OCC maintenance:install \ # --admin-user "admin" \ # --admin-pass "adminpassword" echo "Applying Settings..." $OCC config:system:set default_phone_region --value="CH" $OCC config:system:set overwriteprotocol --value="https" $OCC config:app:set core backgroundjobs_mode --value="cron" $OCC config:system:set maintenance_window_start --type=integer --value=1 $OCC config:system:set default_language --value="en" $OCC config:system:set default_locale --value="en_CH" echo "Applying Apps..." $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 || 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 $OCC app:install contacts || true $OCC app:install camerarawpreviews || true $OCC app:install cospend || true $OCC app:install deck || true $OCC app:install files_markdown || true $OCC app:install forms || true $OCC app:install groupfolders || true $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 ${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}" ''} ${lib.optionalString (serverCfg.containers ? etherpad) '' $OCC config:app:set ownpad ownpad_etherpad_enable --value="yes" $OCC config:app:set ownpad ownpad_etherpad_host --value="https:\/\/${serverCfg.containers.etherpad.subdomain}.${serverCfg.hostDomain}" ''} ${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 idp0 --general-idp0_display_name="authentik" $OCC saml:config:set idp0 --general-uid_mapping="http://schemas.goauthentik.io/2021/02/saml/username" $OCC saml:config:set idp0 --idp-entityId="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}" $OCC saml:config:set idp0 --idp-singleSignOnService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/${containerCfg.subdomain}/sso/binding/redirect/" $OCC saml:config:set idp0 --idp-singleLogoutService.url="https://${serverCfg.containers.authentik.subdomain}.${serverCfg.hostDomain}/application/saml/${containerCfg.subdomain}/slo/binding/redirect/" AUTHENTIK_CERT=$(${pkgs.postgresql}/bin/psql -h localhost -U authentik_user -d authentik_db -t -c "SELECT certificate_data FROM authentik_crypto_certificatekeypair WHERE name = 'authentik Self-signed Certificate';" | sed '/---/d' | tr -d '+ \n') $OCC saml:config:set idp0 --idp-x509cert="$AUTHENTIK_CERT" $OCC saml:config:set idp0 --saml-attribute-mapping-displayName_mapping="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" $OCC saml:config:set idp0 --saml-attribute-mapping-email_mapping="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" $OCC saml:config:set idp0 --saml-attribute-mapping-group_mapping="http://schemas.xmlsoap.org/claims/Group" $OCC saml:config:set idp0 --general-group_provisioning="0" $OCC config:app:set idp0 user_saml general-require_provisioning_groups --value="0" # $OCC saml:config:set idp0 --general-allowed_groups="cloud,admin" ''} # configure side_menu ... 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 background_color --value="${serverCfg.colorScheme.palette.base02}" $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} #$OCC theming:config background {serverCfg.colorScheme.bg} else echo "Nextcloud is already installed. Skipping setup." fi echo "Maintenance..." $OCC app:update --all $OCC maintenance:repair --include-expensive --no-interaction $OCC db:add-missing-indices --no-interaction echo "Completed Setup" ''; }; cron = [ "*/5 * * * * root ${pkgs.podman}/bin/podman --events-backend=none exec -u www-data nextcloud-server php -f /var/www/html/cron.php" ]; }