diff options
author | Vladimír Čunát <v@cunat.cz> | 2019-06-03 22:33:52 +0200 |
---|---|---|
committer | Vladimír Čunát <v@cunat.cz> | 2019-06-03 22:34:49 +0200 |
commit | ee86a325dd067df0da827c2044e8f6e39ffbfed6 (patch) | |
tree | e0a4c1946e6101aa41c02c65387b9941fb9b1f48 /nixos/modules/services | |
parent | 2812b5ce392370ca671a1f371904a12aa3c6db13 (diff) | |
parent | c4724fb7bcc83a778632ce096e37b7dcdd3b034b (diff) |
Merge branch 'staging-next' into staging
Conflicts (simple):
nixos/doc/manual/release-notes/rl-1909.xml
Diffstat (limited to 'nixos/modules/services')
22 files changed, 506 insertions, 347 deletions
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 7e3c230fff71..66d55b650a45 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -18,16 +18,12 @@ let in (pName mysql == pName pkgs.mysql57) && ((builtins.compareVersions mysql.version "5.7") >= 0); - pidFile = "${cfg.pidDir}/mysqld.pid"; - - mysqldAndInstallOptions = - "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}"; mysqldOptions = - "${mysqldAndInstallOptions} --pid-file=${pidFile}"; + "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}"; # For MySQL 5.7+, --insecure creates the root user without password # (earlier versions and MariaDB do this by default). installOptions = - "${mysqldAndInstallOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}"; + "${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}"; in @@ -80,11 +76,6 @@ in description = "Location where MySQL stores its table files"; }; - pidDir = mkOption { - default = "/run/mysqld"; - description = "Location of the file which stores the PID of the MySQL server"; - }; - extraOptions = mkOption { type = types.lines; default = ""; @@ -296,6 +287,10 @@ in ${cfg.extraOptions} ''; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' 0700 ${cfg.user} mysql -" + ]; + systemd.services.mysql = let hasNotify = (cfg.package == pkgs.mariadb); in { @@ -313,70 +308,69 @@ in pkgs.nettools ]; - preStart = - '' - if ! test -e ${cfg.dataDir}/mysql; then - mkdir -m 0700 -p ${cfg.dataDir} - chown -R ${cfg.user} ${cfg.dataDir} - ${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${installOptions} - touch /tmp/mysql_init - fi - - mkdir -m 0755 -p ${cfg.pidDir} - chown -R ${cfg.user} ${cfg.pidDir} - ''; + preStart = '' + if ! test -e ${cfg.dataDir}/mysql; then + ${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${installOptions} + touch /tmp/mysql_init + fi + ''; serviceConfig = { + User = cfg.user; + Group = "mysql"; Type = if hasNotify then "notify" else "simple"; RuntimeDirectory = "mysqld"; + RuntimeDirectoryMode = "0755"; # The last two environment variables are used for starting Galera clusters ExecStart = "${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION"; }; - postStart = '' - ${lib.optionalString (!hasNotify) '' - # Wait until the MySQL server is available for use - count=0 - while [ ! -e /run/mysqld/mysqld.sock ] - do - if [ $count -eq 30 ] - then - echo "Tried 30 times, giving up..." - exit 1 - fi - - echo "MySQL daemon not yet started. Waiting for 1 second..." - count=$((count++)) - sleep 1 - done - ''} + postStart = + let + cmdWatchForMysqlSocket = '' + # Wait until the MySQL server is available for use + count=0 + while [ ! -e /run/mysqld/mysqld.sock ] + do + if [ $count -eq 30 ] + then + echo "Tried 30 times, giving up..." + exit 1 + fi + + echo "MySQL daemon not yet started. Waiting for 1 second..." + count=$((count++)) + sleep 1 + done + ''; + cmdInitialDatabases = concatMapStrings (database: '' + # Create initial databases + if ! test -e "${cfg.dataDir}/${database.name}"; then + echo "Creating initial database: ${database.name}" + ( echo 'create database `${database.name}`;' + + ${optionalString (database.schema != null) '' + echo 'use `${database.name}`;' + + # TODO: this silently falls through if database.schema does not exist, + # we should catch this somehow and exit, but can't do it here because we're in a subshell. + if [ -f "${database.schema}" ] + then + cat ${database.schema} + elif [ -d "${database.schema}" ] + then + cat ${database.schema}/mysql-databases/*.sql + fi + ''} + ) | ${mysql}/bin/mysql -u root -N + fi + '') cfg.initialDatabases; + in + lib.optionalString (!hasNotify) cmdWatchForMysqlSocket + '' if [ -f /tmp/mysql_init ] then - ${concatMapStrings (database: - '' - # Create initial databases - if ! test -e "${cfg.dataDir}/${database.name}"; then - echo "Creating initial database: ${database.name}" - ( echo 'create database `${database.name}`;' - - ${optionalString (database.schema != null) '' - echo 'use `${database.name}`;' - - # TODO: this silently falls through if database.schema does not exist, - # we should catch this somehow and exit, but can't do it here because we're in a subshell. - if [ -f "${database.schema}" ] - then - cat ${database.schema} - elif [ -d "${database.schema}" ] - then - cat ${database.schema}/mysql-databases/*.sql - fi - ''} - ) | ${mysql}/bin/mysql -u root -N - fi - '') cfg.initialDatabases} - + ${cmdInitialDatabases} ${optionalString (cfg.replication.role == "master") '' # Set up the replication master diff --git a/nixos/modules/services/misc/octoprint.nix b/nixos/modules/services/misc/octoprint.nix index baa7c3ade52e..52ae25201c35 100644 --- a/nixos/modules/services/misc/octoprint.nix +++ b/nixos/modules/services/misc/octoprint.nix @@ -7,7 +7,7 @@ let cfg = config.services.octoprint; baseConfig = { - plugins.cura.cura_engine = "${pkgs.curaengine_stable}/bin/CuraEngine"; + plugins.curalegacy.cura_engine = "${pkgs.curaengine_stable}/bin/CuraEngine"; server.host = cfg.host; server.port = cfg.port; webcam.ffmpeg = "${pkgs.ffmpeg.bin}/bin/ffmpeg"; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix index a3f1d9d31323..530206681d36 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix @@ -28,7 +28,7 @@ in serviceConfig = { DynamicUser = true; ExecStart = '' - ${pkgs.prometheus-fritzbox-exporter}/bin/fritzbox_exporter \ + ${pkgs.prometheus-fritzbox-exporter}/bin/exporter \ -listen-address ${cfg.listenAddress}:${toString cfg.port} \ -gateway-address ${cfg.gatewayAddress} \ -gateway-port ${toString cfg.gatewayPort} \ diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix index a6e90feff7ea..7ac4d0c6419d 100644 --- a/nixos/modules/services/networking/murmur.nix +++ b/nixos/modules/services/networking/murmur.nix @@ -4,6 +4,7 @@ with lib; let cfg = config.services.murmur; + forking = cfg.logFile != null; configFile = pkgs.writeText "murmurd.ini" '' database=/var/lib/murmur/murmur.sqlite dbDriver=QSQLITE @@ -12,8 +13,8 @@ let autobanTimeframe=${toString cfg.autobanTimeframe} autobanTime=${toString cfg.autobanTime} - logfile=/var/log/murmur/murmurd.log - pidfile=${cfg.pidfile} + logfile=${optionalString (cfg.logFile != null) cfg.logFile} + ${optionalString forking "pidfile=/run/murmur/murmurd.pid"} welcometext="${cfg.welcometext}" port=${toString cfg.port} @@ -78,10 +79,11 @@ in description = "The amount of time an IP ban lasts (in seconds)."; }; - pidfile = mkOption { - type = types.path; - default = "/run/murmur/murmurd.pid"; - description = "Path to PID file for Murmur daemon."; + logFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/log/murmur/murmurd.log"; + description = "Path to the log file for Murmur daemon. Empty means log to journald."; }; welcometext = mkOption { @@ -251,19 +253,13 @@ in after = [ "network-online.target "]; serviceConfig = { - Type = "forking"; - RuntimeDirectory = "murmur"; - PIDFile = cfg.pidfile; - Restart = "always"; + # murmurd doesn't fork when logging to the console. + Type = if forking then "forking" else "simple"; + PIDFile = mkIf forking "/run/murmur/murmurd.pid"; + RuntimeDirectory = mkIf forking "murmur"; User = "murmur"; ExecStart = "${pkgs.murmur}/bin/murmurd -ini ${configFile}"; - PermissionsStartOnly = true; }; - - preStart = '' - mkdir -p /var/log/murmur - chown -R murmur /var/log/murmur - ''; }; }; } diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 5e5544471818..f1ba7dd4e4f2 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -477,6 +477,10 @@ in { ''; }; + systemd.services.NetworkManager-wait-online = { + wantedBy = [ "network-online.target" ]; + }; + systemd.services.nm-setup-hostsdirs = mkIf dynamicHostsEnabled { wantedBy = [ "NetworkManager.service" ]; before = [ "NetworkManager.service" ]; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index e011172ffa7d..d78a54a3327b 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -426,7 +426,9 @@ in { ''; }; }; - syncthing-init = { + syncthing-init = mkIf ( + cfg.declarative.devices != {} || cfg.declarative.folders != {} + ) { after = [ "syncthing.service" ]; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix index 3a65f7ff32c7..c07481582c2f 100644 --- a/nixos/modules/services/networking/wireguard.nix +++ b/nixos/modules/services/networking/wireguard.nix @@ -229,8 +229,61 @@ let ''; }; + generatePeerUnit = { interfaceName, interfaceCfg, peer }: + let + keyToUnitName = replaceChars + [ "/" "-" " " "+" "=" ] + [ "-" "\\x2d" "\\x20" "\\x2b" "\\x3d" ]; + unitName = keyToUnitName peer.publicKey; + psk = + if peer.presharedKey != null + then pkgs.writeText "wg-psk" peer.presharedKey + else peer.presharedKeyFile; + in nameValuePair "wireguard-${interfaceName}-peer-${unitName}" + { + description = "WireGuard Peer - ${interfaceName} - ${peer.publicKey}"; + requires = [ "wireguard-${interfaceName}.service" ]; + after = [ "wireguard-${interfaceName}.service" ]; + wantedBy = [ "multi-user.target" ]; + environment.DEVICE = interfaceName; + environment.WG_ENDPOINT_RESOLUTION_RETRIES = "infinity"; + path = with pkgs; [ iproute wireguard-tools ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = let + wg_setup = "wg set ${interfaceName} peer ${peer.publicKey}" + + optionalString (psk != null) " preshared-key ${psk}" + + optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + + optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + + optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"; + route_setup = + optionalString (interfaceCfg.allowedIPsAsRoutes != false) + (concatMapStringsSep "\n" + (allowedIP: + "ip route replace ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}" + ) peer.allowedIPs); + in '' + ${wg_setup} + ${route_setup} + ''; - generateSetupServiceUnit = name: values: + postStop = let + route_destroy = optionalString (interfaceCfg.allowedIPsAsRoutes != false) + (concatMapStringsSep "\n" + (allowedIP: + "ip route delete ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}" + ) peer.allowedIPs); + in '' + wg set ${interfaceName} peer ${peer.publicKey} remove + ${route_destroy} + ''; + }; + + generateInterfaceUnit = name: values: # exactly one way to specify the private key must be set #assert (values.privateKey != null) != (values.privateKeyFile != null); let privKey = if values.privateKeyFile != null then values.privateKeyFile else pkgs.writeText "wg-key" values.privateKey; @@ -245,9 +298,7 @@ let path = with pkgs; [ kmod iproute wireguard-tools ]; serviceConfig = { - Type = "simple"; - Restart = "on-failure"; - RestartSec = "5s"; + Type = "oneshot"; RemainAfterExit = true; }; @@ -265,25 +316,8 @@ let wg set ${name} private-key ${privKey} ${ optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}"} - ${concatMapStringsSep "\n" (peer: - assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set - let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile; - in - "wg set ${name} peer ${peer.publicKey}" + - optionalString (psk != null) " preshared-key ${psk}" + - optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + - optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + - optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}" - ) values.peers} - ip link set up dev ${name} - ${optionalString (values.allowedIPsAsRoutes != false) (concatStringsSep "\n" (concatMap (peer: - (map (allowedIP: - "ip route replace ${allowedIP} dev ${name} table ${values.table}" - ) peer.allowedIPs) - ) values.peers))} - ${values.postSetup} ''; @@ -335,7 +369,12 @@ in ###### implementation - config = mkIf cfg.enable { + config = mkIf cfg.enable (let + all_peers = flatten + (mapAttrsToList (interfaceName: interfaceCfg: + map (peer: { inherit interfaceName interfaceCfg peer;}) interfaceCfg.peers + ) cfg.interfaces); + in { assertions = (attrValues ( mapAttrs (name: value: { @@ -346,19 +385,24 @@ in mapAttrs (name: value: { assertion = value.generatePrivateKeyFile -> (value.privateKey == null); message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set."; - }) cfg.interfaces)); - + }) cfg.interfaces)) + ++ map ({ interfaceName, peer, ... }: { + assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null); + message = "networking.wireguard.interfaces.${interfaceName} peer «${peer.publicKey}» has both presharedKey and presharedKeyFile set, but only one can be used."; + }) all_peers; boot.extraModulePackages = [ kernel.wireguard ]; environment.systemPackages = [ pkgs.wireguard-tools ]; - systemd.services = (mapAttrs' generateSetupServiceUnit cfg.interfaces) + systemd.services = + (mapAttrs' generateInterfaceUnit cfg.interfaces) + // (listToAttrs (map generatePeerUnit all_peers)) // (mapAttrs' generateKeyServiceUnit (filterAttrs (name: value: value.generatePrivateKeyFile) cfg.interfaces)); systemd.paths = mapAttrs' generatePathUnit (filterAttrs (name: value: value.privateKeyFile != null) cfg.interfaces); - }; + }); } diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index 9e9bdedff126..86b0c8d69beb 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -60,6 +60,8 @@ let TempDir ${cfg.tempDir} + SetEnv PATH /var/lib/cups/path/lib/cups/filter:/var/lib/cups/path/bin + # User and group used to run external programs, including # those that actually send the job to the printer. Note that # Udev sets the group of printer devices to `lp', so we want @@ -76,8 +78,6 @@ let '') cfg.listenAddresses} Listen /run/cups/cups.sock - SetEnv PATH /var/lib/cups/path/lib/cups/filter:/var/lib/cups/path/bin - DefaultShared ${if cfg.defaultShared then "Yes" else "No"} Browsing ${if cfg.browsing then "Yes" else "No"} diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix new file mode 100644 index 000000000000..f9e12e3642ea --- /dev/null +++ b/nixos/modules/services/web-apps/limesurvey.nix @@ -0,0 +1,288 @@ +{ config, lib, pkgs, ... }: + +let + + inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption; + inherit (lib) mapAttrs optional optionalString types; + + cfg = config.services.limesurvey; + + user = "limesurvey"; + group = config.services.httpd.group; + stateDir = "/var/lib/limesurvey"; + + php = pkgs.php; + pkg = pkgs.limesurvey; + + configType = with types; either (either (attrsOf configType) str) (either int bool) // { + description = "limesurvey config type (str, int, bool or attribute set thereof)"; + }; + + limesurveyConfig = pkgs.writeText "config.php" '' + <?php + return json_decode('${builtins.toJSON cfg.config}', true); + ?> + ''; + + mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql"; + pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql"; + +in +{ + # interface + + options.services.limesurvey = { + enable = mkEnableOption "Limesurvey web application."; + + database = { + type = mkOption { + type = types.enum [ "mysql" "pgsql" "odbc" "mssql" ]; + example = "pgsql"; + default = "mysql"; + description = "Database engine to use."; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + description = "Database host address."; + }; + + port = mkOption { + type = types.int; + default = if cfg.database.type == "pgsql" then 5442 else 3306; + defaultText = "3306"; + description = "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "limesurvey"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "limesurvey"; + description = "Database user."; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/limesurvey-dbpassword"; + description = '' + A file containing the password corresponding to + <option>database.user</option>. + ''; + }; + + socket = mkOption { + type = types.nullOr types.path; + default = + if mysqlLocal then "/run/mysqld/mysqld.sock" + else if pgsqlLocal then "/run/postgresql" + else null + ; + defaultText = "/run/mysqld/mysqld.sock"; + description = "Path to the unix socket file to use for authentication."; + }; + + createLocally = mkOption { + type = types.bool; + default = cfg.database.type == "mysql"; + defaultText = "true"; + description = '' + Create the database and database user locally. + This currently only applies if database type "mysql" is selected. + ''; + }; + }; + + virtualHost = mkOption { + type = types.submodule ({ + options = import ../web-servers/apache-httpd/per-server-options.nix { + inherit lib; + forMainServer = false; + }; + }); + example = { + hostName = "survey.example.org"; + enableSSL = true; + adminAddr = "webmaster@example.org"; + sslServerCert = "/var/lib/acme/survey.example.org/full.pem"; + sslServerKey = "/var/lib/acme/survey.example.org/key.pem"; + }; + description = '' + Apache configuration can be done by adapting <literal>services.httpd.virtualHosts.<name></literal>. + See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. + ''; + }; + + poolConfig = mkOption { + type = types.lines; + default = '' + pm = dynamic + pm.max_children = 32 + pm.start_servers = 2 + pm.min_spare_servers = 2 + pm.max_spare_servers = 4 + pm.max_requests = 500 + ''; + description = '' + Options for LimeSurvey's PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives. + ''; + }; + + config = mkOption { + type = configType; + default = {}; + description = '' + LimeSurvey configuration. Refer to + <link xlink:href="https://manual.limesurvey.org/Optional_settings"/> + for details on supported values. + ''; + }; + }; + + # implementation + + config = mkIf cfg.enable { + + assertions = [ + { assertion = cfg.database.createLocally -> cfg.database.type == "mysql"; + message = "services.limesurvey.createLocally is currently only supported for database type 'mysql'"; + } + { assertion = cfg.database.createLocally -> cfg.database.user == user; + message = "services.limesurvey.database.user must be set to ${user} if services.limesurvey.database.createLocally is set true"; + } + { assertion = cfg.database.createLocally -> cfg.database.socket != null; + message = "services.limesurvey.database.socket must be set if services.limesurvey.database.createLocally is set to true"; + } + { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; + message = "a password cannot be specified if services.limesurvey.database.createLocally is set to true"; + } + ]; + + services.limesurvey.config = mapAttrs (name: mkDefault) { + runtimePath = "${stateDir}/tmp/runtime"; + components = { + db = { + connectionString = "${cfg.database.type}:dbname=${cfg.database.name};host=${if pgsqlLocal then cfg.database.socket else cfg.database.host};port=${toString cfg.database.port}" + + optionalString mysqlLocal ";socket=${cfg.database.socket}"; + username = cfg.database.user; + password = mkIf (cfg.database.passwordFile != null) "file_get_contents(\"${toString cfg.database.passwordFile}\");"; + tablePrefix = "limesurvey_"; + }; + assetManager.basePath = "${stateDir}/tmp/assets"; + urlManager = { + urlFormat = "path"; + showScriptName = false; + }; + }; + config = { + tempdir = "${stateDir}/tmp"; + uploaddir = "${stateDir}/upload"; + force_ssl = mkIf cfg.virtualHost.enableSSL "on"; + config.defaultlang = "en"; + }; + }; + + services.mysql = mkIf mysqlLocal { + enable = true; + package = mkDefault pkgs.mariadb; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { name = cfg.database.user; + ensurePermissions = { + "${cfg.database.name}.*" = "SELECT, CREATE, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX"; + }; + } + ]; + }; + + services.phpfpm.pools.limesurvey = { + phpPackage = php; + listen = "/run/phpfpm/limesurvey.sock"; + extraConfig = '' + listen.owner = ${config.services.httpd.user}; + listen.group = ${config.services.httpd.group}; + user = ${user}; + group = ${group}; + + env[LIMESURVEY_CONFIG] = ${limesurveyConfig} + + ${cfg.poolConfig} + ''; + }; + + services.httpd = { + enable = true; + adminAddr = mkDefault cfg.virtualHost.adminAddr; + extraModules = [ "proxy_fcgi" ]; + virtualHosts = [ + (cfg.virtualHost // { + documentRoot = mkForce "${pkg}/share/limesurvey"; + extraConfig = '' + Alias "/tmp" "${stateDir}/tmp" + <Directory "${stateDir}"> + AllowOverride all + Require all granted + Options -Indexes +FollowSymlinks + </Directory> + + Alias "/upload" "${stateDir}/upload" + <Directory "${stateDir}/upload"> + AllowOverride all + Require all granted + Options -Indexes + </Directory> + + <Directory "${pkg}/share/limesurvey"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:/run/phpfpm/limesurvey.sock|fcgi://localhost/" + </If> + </FilesMatch> + + AllowOverride all + Options -Indexes + DirectoryIndex index.php + </Directory> + ''; + }) + ]; + }; + + systemd.tmpfiles.rules = [ + "d ${stateDir} 0750 ${user} ${group} - -" + "d ${stateDir}/tmp 0750 ${user} ${group} - -" + "d ${stateDir}/tmp/assets 0750 ${user} ${group} - -" + "d ${stateDir}/tmp/runtime 0750 ${user} ${group} - -" + "d ${stateDir}/tmp/upload 0750 ${user} ${group} - -" + "C ${stateDir}/upload 0750 ${user} ${group} - ${pkg}/share/limesurvey/upload" + ]; + + systemd.services.limesurvey-init = { + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-limesurvey.service" ]; + after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service"; + environment.LIMESURVEY_CONFIG = limesurveyConfig; + script = '' + # update or install the database as required + ${php}/bin/php ${pkg}/share/limesurvey/application/commands/console.php updatedb || \ + ${php}/bin/php ${pkg}/share/limesurvey/application/commands/console.php install admin password admin admin@example.com verbose + ''; + serviceConfig = { + User = user; + Group = group; + Type = "oneshot"; + }; + }; + + systemd.services.httpd.after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service"; |