{ config, pkgs, lib, ... }: with lib; let # Version tagging nextcloudVersion = "32.0.6"; redisVersion = "8.6-alpine"; databaseVersion = "11.8"; onlyofficeVersion = "9.2"; whiteboardVersion = "v1.5.6"; # Helper helper = import ./lib.nix { inherit config pkgs lib; }; cfg = config.numbus.services.nextcloud; # Container config name = "nextcloud"; in helper.mkPodmanService { inherit name; description = "Nextcloud, your own online office suite"; defaultPort = "1100"; generatedSecrets = { DB_NAME = "xkcdpass -n 2 -d -"; DB_USERNAME = "xkcdpass -n 2 -d -"; DB_PASSWORD = "xkcdpass -n 10 -d -"; REDIS_PASSWORD = "xkcdpass -n 10 -d -"; ONLYOFFICE_PASSWORD = "xkcdpass -n 10 -d -"; WHITEBOARD_PASSWORD = "xkcdpass -n 10 -d -"; SMTP_PASSWORD = "cat ${config.numbus.mail.smtpPasswordPath}"; }; dirPermissions = [ "100032:100 ${cfg.configDir}/web" "100999:100 ${cfg.configDir}/redis" "100999:100 ${cfg.configDir}/database" "100999:100 ${cfg.configDir}/onlyoffice" "100999:100 ${cfg.configDir}/onlyoffice/log" "100999:100 ${cfg.configDir}/onlyoffice/cache" "100999:100 ${cfg.configDir}/onlyoffice/database" "100032:100 ${cfg.dataDir}" ]; # Compose file good composeText = '' services: nextcloud-server: image: docker.io/library/nextcloud:${nextcloudVersion} container_name: nextcloud-server hostname: nextcloud-server networks: nextcloud: ports: - "${cfg.port}:80/tcp" volumes: - ${cfg.configDir}/web:/var/www/html - ${cfg.dataDir}:/mnt/ncdata environment: MYSQL_HOST: nextcloud-database:3306 MYSQL_DATABASE: $DB_NAME MYSQL_USER: $DB_USERNAME MYSQL_PASSWORD: $DB_PASSWORD REDIS_HOST: nextcloud-redis REDIS_HOST_PASSWORD: $REDIS_PASSWORD NEXTCLOUD_TRUSTED_DOMAINS: ${cfg.subdomain}.${config.numbus.services.domain} NEXTCLOUD_DATA_DIR: /mnt/ncdata SMTP_SECURE: tls SMTP_HOST: ${config.numbus.mail.smtpServer} SMTP_PORT: ${toString config.numbus.mail.smtpPort} SMTP_NAME: ${config.numbus.mail.smtpUsername} SMTP_PASSWORD: $SMTP_PASSWORD MAIL_FROM_ADDRESS: nextcloud-noreply MAIL_DOMAIN: ${config.numbus.services.domain} APACHE_DISABLE_REWRITE_IP: 1 TRUSTED_PROXIES: ${config.numbus.networking.ipAddress} OVERWRITEPROTOCOL: https NC_default_phone_region: "${config.numbus.language}" NC_default_language: "${config.numbus.language}" NC_default_locale: "${config.numbus.locale}" NC_default_timezone: "${config.time.timeZone}" NC_maintenance_window_start: "1" depends_on: - nextcloud-database security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped nextcloud-redis: image: docker.io/library/redis:${redisVersion} container_name: nextcloud-redis hostname: nextcloud-redis user: '1000:1000' networks: nextcloud: volumes: - ${cfg.configDir}/redis:/data command: redis-server --requirepass $REDIS_PASSWORD --save 60 1 --loglevel warning security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped nextcloud-database: image: docker.io/library/mariadb:${databaseVersion} container_name: nextcloud-database hostname: nextcloud-database user: '1000:1000' networks: nextcloud: volumes: - ${cfg.configDir}/database:/var/lib/mysql environment: MARIADB_DATABASE: $DB_NAME MARIADB_USER: $DB_USERNAME MARIADB_PASSWORD: $DB_PASSWORD MARIADB_RANDOM_ROOT_PASSWORD: true security_opt: - no-new-privileges:true cap_drop: - NET_RAW command: - "--transaction-isolation=READ-COMMITTED" - "--binlog-format=ROW" restart: unless-stopped nextcloud-onlyoffice: container_name: nextcloud-onlyoffice hostname: nextcloud-onlyoffice image: docker.io/onlyoffice/documentserver:${onlyofficeVersion} environment: - JWT_SECRET=$ONLYOFFICE_PASSWORD ports: - "9980:80/tcp" volumes: - ${cfg.configDir}/onlyoffice/log:/var/log/onlyoffice - ${cfg.configDir}/onlyoffice/cache:/var/lib/onlyoffice - ${cfg.configDir}/onlyoffice/database:/var/lib/postgresql security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped nextcloud-whiteboard: image: ghcr.io/nextcloud-releases/whiteboard:${whiteboardVersion} container_name: nextcloud-whiteboard hostname: nextcloud-whiteboard user: '1000:1000' ports: - "3002:3002/tcp" environment: NEXTCLOUD_URL: https://${cfg.subdomain}.${config.numbus.services.domain} JWT_SECRET_KEY: $WHITEBOARD_PASSWORD security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped networks: nextcloud: name: nextcloud driver: bridge ''; extraConfig = { environment.etc."traefik/rules/nextcloud-onlyoffice.yaml".text = '' http: routers: nextcloud-onlyoffice: rule: "Host(`onlyoffice.${config.numbus.services.domain}`)" entrypoints: - "websecure" service: nextcloud-onlyoffice middlewares: - "secureHeaders" tls: certresolver: "cloudflare" options: "secureTLS" services: nextcloud-onlyoffice: loadBalancer: servers: - url: "http://host.containers.internal:9980" ''; environment.etc."traefik/rules/nextcloud-whiteboard.yaml".text = '' http: routers: nextcloud-whiteboard: rule: "Host(`whiteboard.${config.numbus.services.domain}`)" entrypoints: - "websecure" service: nextcloud-whiteboard middlewares: - "secureHeaders" tls: certresolver: "cloudflare" options: "secureTLS" services: nextcloud-whiteboard: loadBalancer: servers: - url: "http://host.containers.internal:3002" ''; systemd.services."${name}-quirk" = { description = "Podman container quirk : ${name}"; wantedBy = [ "multi-user.target" ]; after = [ "${name}.service" "${name}-secrets.service" ]; onFailure = [ "service-failure-notify@%n.service" ]; startLimitBurst = 5; startLimitIntervalSec = 600; path = [ pkgs.coreutils pkgs.sudo pkgs.podman ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' mkdir -p /var/lib/numbus-server/${name} [[ -e /var/lib/numbus-server/${name}/quirk.true ]] && exit 0 [[ ! -e /var/lib/numbus-server/${name}/.env ]] && systemctl start ${name}-secrets.service until [[ -e /var/lib/numbus-server/${name}/.env ]]; do echo "Waiting for secrets generation..." sleep 15 done source /var/lib/numbus-server/${name}/.env sleep 300 sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ background:cron sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ db:add-missing-indices sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ maintenance:repair --include-expensive sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ files:scan --all sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ files:repair-tree for app in calendar contacts mail note onlyoffice cookbook whiteboard; do sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:install $app sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:enable $app done for app in activity app_api federatedfilesharing federation webhook_listeners photos recommendations sharebymail teams support richdocumentscode; do sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:disable $app sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:remove $app done sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice DocumentServerInternalUrl --value="https://onlyoffice.${config.numbus.services.domain}/" sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice DocumentServerUrl --value="https://onlyoffice.${config.numbus.services.domain}/" sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_PASSWORD" sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:app:set whiteboard collabBackendUrl --value="https://whiteboard.${config.numbus.services.domain}" sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:app:set whiteboard jwt_secret_key --value="$WHITEBOARD_PASSWORD" touch /var/lib/numbus-server/${name}/quirk.true ''; }; systemd.services."${name}-cron" = { description = "Podman container crontab : ${name}"; after = [ "${name}.service" "${name}-quirk.service" ]; onFailure = [ "service-failure-notify@%n.service" ]; path = [ pkgs.sudo pkgs.podman ]; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.sudo}/bin/sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php"; }; }; systemd.timers."${name}-cron" = { description = "Timer for Nextcloud cron"; wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "5m"; OnUnitActiveSec = "5m"; Unit = "${name}-cron.service"; }; }; }; }