{ lib, pkgs, config, ... }: let cfg = config.myServices.tools.cloud.farm; apacheUser = config.services.httpd.Prod.user; apacheGroup = config.services.httpd.Prod.group; toVardir = name: "/var/lib/nextcloud_farm/${name}"; varDirs = lib.mapAttrsToList (name: v: toVardir name) cfg.instances; toPhpBaseDir = name: [ cfg.rootDirs."${name}" (toVardir name) ] ++ cfg.rootDirs."${name}".apps; phpBaseDir = builtins.concatStringsSep ":" (lib.unique (lib.flatten (lib.mapAttrsToList (name: v: toPhpBaseDir name) cfg.instances))); toVhost = name: '' SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 SetEnv NEXTCLOUD_CONFIG_DIR "${toVardir name}" AcceptPathInfo On DirectoryIndex index.php Options FollowSymlinks Require all granted AllowOverride all Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" CGIPassAuth on SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud_farm.socket}|fcgi://localhost" ''; phpPackage = (pkgs.php74.withExtensions({ enabled, all }: enabled ++ [ all.redis all.apcu all.opcache all.imagick ])).override { extraConfig = '' apc.enable_cli = 1 ''; }; in { options.myServices.tools.cloud.farm = { instances = lib.mkOption { description = "Instances names for the nextcloud Farm"; default = {}; type = lib.types.attrsOf (lib.types.submodule { options = { nextcloud = lib.mkOption { description = "Nextcloud version to use"; default = pkgs.webapps.nextcloud_20; type = lib.types.package; }; apps = lib.mkOption { description = "Applications to use"; default = a: []; #type = functionTo (listOf packages) type = lib.types.unspecified; }; }; }); }; rootDirs = lib.mkOption { description = "Instance root dirs"; readOnly = true; type = lib.types.attrsOf lib.types.package; default = lib.mapAttrs (name: v: (v.nextcloud.override { varDir = null; }).withApps v.apps) cfg.instances; }; vhosts = lib.mkOption { description = "Instance vhosts configs"; readOnly = true; type = lib.types.attrsOf lib.types.str; default = lib.mapAttrs (name: v: toVhost name) cfg.instances; }; }; config = lib.mkIf (builtins.length (builtins.attrNames cfg.instances) > 0) { system.activationScripts.cloud_farm_vardirs = { deps = [ "httpd" ]; text = '' install -m 0755 -o ${apacheUser} -g ${apacheGroup} -d ${builtins.concatStringsSep " " varDirs} install -m 0755 -o ${apacheUser} -g ${apacheGroup} -d /var/lib/nextcloud_farm/phpSessions ''; }; systemd.services.phpfpm-nextcloud_farm.after = lib.mkAfter [ "postgresql.service" ]; systemd.services.phpfpm-nextcloud_farm.wants = [ "postgresql.service" ]; services.phpfpm.pools.nextcloud_farm = { user = apacheUser; group = apacheGroup; settings = let instanceNb = builtins.length (builtins.attrNames cfg.instances); in { "listen.owner" = apacheUser; "listen.group" = apacheGroup; "pm" = "dynamic"; "pm.max_children" = builtins.toString (60 * instanceNb); "pm.start_servers" = builtins.toString (3 * instanceNb); "pm.min_spare_servers" = builtins.toString (3 * instanceNb); "pm.max_spare_servers" = builtins.toString (5 * instanceNb); "pm.process_idle_timeout" = "60"; "php_admin_value[output_buffering]" = "0"; "php_admin_value[max_execution_time]" = "1800"; "php_admin_value[zend_extension]" = "opcache"; "php_value[apcu.enable_cli]" = "1"; "php_value[apcu.enabled]" = "1"; #already enabled by default? #"php_value[opcache.enable]" = "1"; "php_value[opcache.enable_cli]" = "1"; "php_value[opcache.interned_strings_buffer]" = "8"; "php_value[opcache.max_accelerated_files]" = "10000"; "php_value[opcache.memory_consumption]" = "128"; "php_value[opcache.save_comments]" = "1"; "php_value[opcache.revalidate_freq]" = "1"; "php_admin_value[memory_limit]" = "512M"; "php_admin_value[open_basedir]" = "/run/wrappers/bin/sendmail:${phpBaseDir}:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp"; "php_admin_value[session.save_path]" = "/var/lib/nextcloud_farm/phpSessions"; }; inherit phpPackage; }; users.users.root.packages = let toOcc = name: pkgs.writeScriptBin "nextcloud-occ-${name}" '' #! ${pkgs.stdenv.shell} cd ${cfg.rootDirs."${name}"} NEXTCLOUD_CONFIG_DIR="${toVardir name}" \ exec \ sudo -E -u wwwrun ${phpPackage}/bin/php \ -c ${phpPackage}/etc/php.ini \ occ $* ''; in lib.mapAttrsToList (name: v: toOcc name) cfg.instances; services.cron = { enable = true; systemCronJobs = let toScript = name: pkgs.writeScriptBin "nextcloud-cron" '' #! ${pkgs.stdenv.shell} export LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive export PATH=/run/wrappers/bin:$PATH export NEXTCLOUD_CONFIG_DIR="${toVardir name}" ${phpPackage}/bin/php -c ${phpPackage}/etc/php.ini -d memory_limit=512M -f ${cfg.rootDirs."${name}"}/cron.php ''; toLine = name: '' */15 * * * * wwwrun ${toScript name}/bin/nextcloud-cron ''; in lib.mapAttrsToList (name: v: toLine name) cfg.instances; }; }; }