summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services
diff options
context:
space:
mode:
authorVladimír Čunát <v@cunat.cz>2019-06-03 22:33:52 +0200
committerVladimír Čunát <v@cunat.cz>2019-06-03 22:34:49 +0200
commitee86a325dd067df0da827c2044e8f6e39ffbfed6 (patch)
treee0a4c1946e6101aa41c02c65387b9941fb9b1f48 /nixos/modules/services
parent2812b5ce392370ca671a1f371904a12aa3c6db13 (diff)
parentc4724fb7bcc83a778632ce096e37b7dcdd3b034b (diff)
Merge branch 'staging-next' into staging
Conflicts (simple): nixos/doc/manual/release-notes/rl-1909.xml
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/databases/mysql.nix122
-rw-r--r--nixos/modules/services/misc/octoprint.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix2
-rw-r--r--nixos/modules/services/networking/murmur.nix28
-rw-r--r--nixos/modules/services/networking/networkmanager.nix4
-rw-r--r--nixos/modules/services/networking/syncthing.nix4
-rw-r--r--nixos/modules/services/networking/wireguard.nix96
-rw-r--r--nixos/modules/services/printing/cupsd.nix4
-rw-r--r--nixos/modules/services/web-apps/limesurvey.nix288
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/limesurvey.nix196
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix2
-rw-r--r--nixos/modules/services/web-servers/hydron.nix46
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix11
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix10
-rw-r--r--nixos/modules/services/x11/desktop-managers/lumina.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/lxqt.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/maxx.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/xterm.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix22
-rw-r--r--nixos/modules/services/x11/xserver.nix3
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.&lt;name&gt;</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";