{ config, pkgs, lib, ... }: lib.mkIf config.sovran_systemsOS.services.nextcloud { # ── PostgreSQL database ─────────────────────────────────── services.postgresql = { enable = true; }; # ── Auto-generate DB password and initialize ────────────── systemd.services.nextcloud-db-init = { description = "Initialize Nextcloud PostgreSQL database with auto-generated password"; after = [ "postgresql.service" ]; requires = [ "postgresql.service" ]; before = [ "nextcloud-init.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; path = [ config.services.postgresql.package pkgs.pwgen pkgs.coreutils ]; script = '' set -euo pipefail SECRET_FILE="/var/lib/secrets/nextclouddb" if [ ! -f "$SECRET_FILE" ]; then mkdir -p /var/lib/secrets pwgen -s 64 1 > "$SECRET_FILE" chmod 600 "$SECRET_FILE" fi DB_PASS=$(cat "$SECRET_FILE") psql -U postgres </dev/null; then echo "Database ready." break fi sleep 2 done echo "Running Nextcloud installation..." /run/wrappers/bin/su -s /bin/sh caddy -c " php $INSTALL_DIR/occ maintenance:install \ --database 'pgsql' \ --database-name '$DB_NAME' \ --database-user '$DB_USER' \ --database-pass '$DB_PASS' \ --database-host '$DB_HOST' \ --admin-user '$ADMIN_USER' \ --admin-pass '$ADMIN_PASS' \ --data-dir '$DATA_DIR' " /run/wrappers/bin/su -s /bin/sh caddy -c " php $INSTALL_DIR/occ config:system:set trusted_domains 0 --value='$DOMAIN' php $INSTALL_DIR/occ config:system:set overwrite.cli.url --value='https://$DOMAIN' php $INSTALL_DIR/occ config:system:set overwritehost --value='$DOMAIN' php $INSTALL_DIR/occ config:system:set overwriteprotocol --value='https' " /run/wrappers/bin/su -s /bin/sh caddy -c " php $INSTALL_DIR/occ config:system:set trusted_proxies 0 --value='127.0.0.1' php $INSTALL_DIR/occ config:system:set trusted_proxies 1 --value='::1' php $INSTALL_DIR/occ config:system:set forwarded_for_headers 0 --value='HTTP_X_FORWARDED_FOR' php $INSTALL_DIR/occ config:system:set default_phone_region --value='US' php $INSTALL_DIR/occ config:system:set maintenance_window_start --type=integer --value=1 php $INSTALL_DIR/occ config:system:set memcache.local --value='\OC\Memcache\APCu' php $INSTALL_DIR/occ config:system:set memcache.locking --value='\OC\Memcache\APCu' php $INSTALL_DIR/occ config:system:set server_id --value='$SERVER_ID' php $INSTALL_DIR/occ background:cron " /run/wrappers/bin/su -s /bin/sh caddy -c " php $INSTALL_DIR/occ integrity:check-core php $INSTALL_DIR/occ maintenance:repair php $INSTALL_DIR/occ db:add-missing-indices php $INSTALL_DIR/occ db:add-missing-columns php $INSTALL_DIR/occ db:add-missing-primary-keys php $INSTALL_DIR/occ maintenance:repair --include-expensive # AppAPI deploy daemon warnings are avoided by disabling app_api when present. if php $INSTALL_DIR/occ app:info app_api >/dev/null 2>&1; then php $INSTALL_DIR/occ app:disable app_api fi " /run/wrappers/bin/su -s /bin/sh caddy -c " php $INSTALL_DIR/occ app:install calendar || true php $INSTALL_DIR/occ app:install contacts || true php $INSTALL_DIR/occ app:install tasks || true php $INSTALL_DIR/occ app:install notes || true php $INSTALL_DIR/occ app:install deck || true php $INSTALL_DIR/occ app:enable calendar || true php $INSTALL_DIR/occ app:enable contacts || true php $INSTALL_DIR/occ app:enable tasks || true php $INSTALL_DIR/occ app:enable notes || true php $INSTALL_DIR/occ app:enable deck || true " CREDS_FILE="/var/lib/secrets/nextcloud-admin" cat > "$CREDS_FILE" << CREDS Nextcloud Admin Credentials ═══════════════════════════ URL: https://$DOMAIN/ Username: $ADMIN_USER Password: $ADMIN_PASS CREDS chmod 600 "$CREDS_FILE" echo "" echo "══════════════════════════════════════════════" echo " Nextcloud installation complete!" echo " Credentials saved to: $CREDS_FILE" echo "══════════════════════════════════════════════" ''; }; systemd.services.nextcloud-detect-existing = { description = "Detect pre-existing Nextcloud installation and populate hub credentials"; after = [ "postgresql.service" ]; wants = [ "postgresql.service" ]; wantedBy = [ "multi-user.target" ]; unitConfig = { ConditionPathExists = [ "/var/lib/www/nextcloud/config/config.php" "!/var/lib/secrets/nextcloud-admin" ]; }; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; path = with pkgs; [ php coreutils gnused ]; script = '' set -euo pipefail CONFIG_FILE="/var/lib/www/nextcloud/config/config.php" CREDS_FILE="/var/lib/secrets/nextcloud-admin" DOMAIN_FILE="/var/lib/domains/nextcloud" DOMAIN="" DOMAIN="$(php -r '$cfg = @include "/var/lib/www/nextcloud/config/config.php"; if (!is_array($cfg)) { exit(0); } $url = $cfg["overwrite.cli.url"] ?? ""; if (is_string($url) && $url !== "") { $host = parse_url($url, PHP_URL_HOST); if (is_string($host) && $host !== "") { echo $host; exit(0); } } $trusted = $cfg["trusted_domains"] ?? []; if (is_array($trusted)) { foreach ($trusted as $entry) { if (is_string($entry) && $entry !== "") { $entry = preg_replace("#^https?://#", "", $entry); $entry = preg_replace("#/.*$#", "", $entry); if ($entry !== "") { echo $entry; exit(0); } } } } if (is_string($trusted) && $trusted !== "") { $trusted = preg_replace("#^https?://#", "", $trusted); $trusted = preg_replace("#/.*$#", "", $trusted); echo $trusted; }' 2>/dev/null || true)" mkdir -p /var/lib/secrets /var/lib/domains cat > "$CREDS_FILE" << CREDS Nextcloud Existing Installation ═══════════════════════════════ URL: ''${DOMAIN:+https://$DOMAIN/}''${DOMAIN:-Unknown (set in $CONFIG_FILE)} Note: Credentials were set before this flake. Use existing credentials or reset via: php /var/lib/www/nextcloud/occ user:resetpassword CREDS chmod 600 "$CREDS_FILE" if [ -n "$DOMAIN" ] && [ ! -f "$DOMAIN_FILE" ]; then printf '%s\n' "$DOMAIN" > "$DOMAIN_FILE" fi ''; }; services.cron.systemCronJobs = [ "*/5 * * * * caddy /run/current-system/sw/bin/php -f /var/lib/www/nextcloud/cron.php" ]; systemd.tmpfiles.rules = [ "d /var/lib/www 0755 caddy php -" "d /var/lib/www/nextcloud 0750 caddy php -" "d /var/lib/nextcloud 0770 caddy php -" ]; services.phpfpm.pools.mypool.phpOptions = lib.mkAfter '' output_buffering = 0 ''; services.phpfpm.pools.nextcloud = { user = "caddy"; group = "php"; phpPackage = config.services.phpfpm.pools.mypool.phpPackage; settings = { "pm" = "dynamic"; "pm.max_children" = 75; "pm.start_servers" = 10; "pm.min_spare_servers" = 5; "pm.max_spare_servers" = 20; "pm.max_requests" = 500; "clear_env" = "no"; "listen" = "/run/phpfpm/nextcloud.sock"; }; }; environment.systemPackages = with pkgs; [ unzip ]; sovran_systemsOS.domainRequirements = [ { name = "nextcloud"; label = "Nextcloud"; example = "cloud.yourdomain.com"; } ]; }