diff options
Diffstat (limited to 'nixos')
59 files changed, 649 insertions, 597 deletions
diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml index e9ab7cce4eb..675a5d9a260 100644 --- a/nixos/doc/manual/configuration/ipv6-config.xml +++ b/nixos/doc/manual/configuration/ipv6-config.xml @@ -39,7 +39,7 @@ <xref linkend="opt-networking.defaultGateway6"/> = { address = "fe00::1"; interface = "enp0s3"; -} +}; </programlisting> </para> diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix index cb78bbafecf..8c9090471dc 100644 --- a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix +++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix @@ -22,7 +22,7 @@ in boot.kernelPackages = pkgs.linuxPackages_rpi; sdImage = { - populateBootCommands = let + populateFirmwareCommands = let configTxt = pkgs.writeText "config.txt" '' # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel # when attempting to show low-voltage or overtemperature warnings. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 6b8c8255c4d..cbd57fad609 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -191,6 +191,7 @@ ./services/audio/liquidsoap.nix ./services/audio/mpd.nix ./services/audio/mopidy.nix + ./services/audio/roon-server.nix ./services/audio/slimserver.nix ./services/audio/snapserver.nix ./services/audio/squeezelite.nix diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index a424e86038e..5be7b25da74 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -213,6 +213,7 @@ with lib; (mkRemovedOptionModule [ "boot" "zfs" "enableLegacyCrypto" ] "The corresponding package was removed from nixpkgs.") (mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.") (mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd") + (mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.") # ZSH (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ]) @@ -240,6 +241,12 @@ with lib; # binfmt (mkRenamedOptionModule [ "boot" "binfmtMiscRegistrations" ] [ "boot" "binfmt" "registrations" ]) + # PHP-FPM + (mkRemovedOptionModule [ "services" "phpfpm" "poolConfigs" ] "Use services.phpfpm.pools instead.") + (mkRemovedOptionModule [ "services" "phpfpm" "phpPackage" ] "Use services.phpfpm.pools.<name>.phpPackage instead.") + (mkRemovedOptionModule [ "services" "phpfpm" "phpOptions" ] "Use services.phpfpm.pools.<name>.phpOptions instead.") + (mkRenamedOptionModule [ "services" "phpfpm" "extraConfig" ] [ "services" "phpfpm" "globalExtraConfig" ]) + ] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter" "jsonExporter" "minioExporter" "nginxExporter" "nodeExporter" "snmpExporter" "unifiExporter" "varnishExporter" ] diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix index e2f4ec39f94..a534b692f17 100644 --- a/nixos/modules/services/audio/mopidy.nix +++ b/nixos/modules/services/audio/mopidy.nix @@ -70,25 +70,25 @@ in { config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - mopidy mopidy - -" + ]; + systemd.services.mopidy = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" "sound.target" ]; description = "mopidy music player daemon"; - preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy ${cfg.dataDir}"; serviceConfig = { ExecStart = "${mopidyEnv}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)}"; User = "mopidy"; - PermissionsStartOnly = true; }; }; systemd.services.mopidy-scan = { description = "mopidy local files scanner"; - preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy ${cfg.dataDir}"; serviceConfig = { ExecStart = "${mopidyEnv}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)} local scan"; User = "mopidy"; - PermissionsStartOnly = true; Type = "oneshot"; }; }; @@ -98,7 +98,7 @@ in { group = "mopidy"; extraGroups = [ "audio" ]; description = "Mopidy daemon user"; - home = "${cfg.dataDir}"; + home = cfg.dataDir; }; users.groups.mopidy.gid = gid; diff --git a/nixos/modules/services/audio/roon-server.nix b/nixos/modules/services/audio/roon-server.nix new file mode 100644 index 00000000000..9562ad1b164 --- /dev/null +++ b/nixos/modules/services/audio/roon-server.nix @@ -0,0 +1,49 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + name = "roon-server"; + cfg = config.services.roon-server; +in { + options = { + services.roon-server = { + enable = mkEnableOption "Roon Server"; + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Open ports in the firewall for the server. + + UDP: 9003 + TCP: 9100 - 9200 + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.roon-server = { + after = [ "network.target" ]; + description = "Roon Server"; + wantedBy = [ "multi-user.target" ]; + + environment.ROON_DATAROOT = "/var/lib/${name}"; + + serviceConfig = { + ExecStart = "${pkgs.roon-server}/opt/start.sh"; + LimitNOFILE = 8192; + DynamicUser = true; + SupplementaryGroups = "audio"; + StateDirectory = name; + }; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPortRanges = [ + { from = 9100; to = 9200; } + ]; + allowedUDPPorts = [ 9003 ]; + }; + }; +} diff --git a/nixos/modules/services/audio/slimserver.nix b/nixos/modules/services/audio/slimserver.nix index 640403d2c97..8f94a2b4940 100644 --- a/nixos/modules/services/audio/slimserver.nix +++ b/nixos/modules/services/audio/slimserver.nix @@ -42,15 +42,17 @@ in { config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - slimserver slimserver - -" + ]; + systemd.services.slimserver = { after = [ "network.target" ]; description = "Slim Server for Logitech Squeezebox Players"; wantedBy = [ "multi-user.target" ]; - preStart = "mkdir -p ${cfg.dataDir} && chown -R slimserver:slimserver ${cfg.dataDir}"; serviceConfig = { User = "slimserver"; - PermissionsStartOnly = true; # Issue 40589: Disable broken image/video support (audio still works!) ExecStart = "${cfg.package}/slimserver.pl --logdir ${cfg.dataDir}/logs --prefsdir ${cfg.dataDir}/prefs --cachedir ${cfg.dataDir}/cache --noimage --novideo"; }; diff --git a/nixos/modules/services/backup/duplicati.nix b/nixos/modules/services/backup/duplicati.nix index d2fe4698e88..0ff720c5897 100644 --- a/nixos/modules/services/backup/duplicati.nix +++ b/nixos/modules/services/backup/duplicati.nix @@ -47,15 +47,11 @@ in wantedBy = [ "multi-user.target" ]; serviceConfig = { User = cfg.user; - PermissionsStartOnly = true; Group = "duplicati"; + StateDirectory = "duplicati"; ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=/var/lib/duplicati"; Restart = "on-failure"; }; - preStart = '' - mkdir -p /var/lib/duplicati - chown -R ${cfg.user}:duplicati /var/lib/duplicati - ''; }; users.users.duplicati = lib.optionalAttrs (cfg.user == "duplicati") { diff --git a/nixos/modules/services/computing/boinc/client.nix b/nixos/modules/services/computing/boinc/client.nix index 8abe3c5b8c9..7022751b3f0 100644 --- a/nixos/modules/services/computing/boinc/client.nix +++ b/nixos/modules/services/computing/boinc/client.nix @@ -105,19 +105,18 @@ in isSystemUser = true; }; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - boinc - - -" + ]; + systemd.services.boinc = { description = "BOINC Client"; after = ["network.target" "local-fs.target"]; wantedBy = ["multi-user.target"]; - preStart = '' - mkdir -p ${cfg.dataDir} - chown boinc ${cfg.dataDir} - ''; script = '' ${fhsEnvExecutable} --dir ${cfg.dataDir} --redirectio ${allowRemoteGuiRpcFlag} ''; serviceConfig = { - PermissionsStartOnly = true; # preStart must be run as root User = "boinc"; Nice = 10; }; diff --git a/nixos/modules/services/databases/firebird.nix b/nixos/modules/services/databases/firebird.nix index cc81b440450..042c9841df5 100644 --- a/nixos/modules/services/databases/firebird.nix +++ b/nixos/modules/services/databases/firebird.nix @@ -95,6 +95,11 @@ in environment.systemPackages = [cfg.package]; + systemd.tmpfiles.rules = [ + "d '${dataDir}' 0700 ${cfg.user} - - -" + "d '${systemDir}' 0700 ${cfg.user} - - -" + ]; + systemd.services.firebird = { description = "Firebird Super-Server"; @@ -104,21 +109,16 @@ in # is a better way preStart = '' - mkdir -m 0700 -p \ - "${dataDir}" \ - "${systemDir}" \ - /var/log/firebird - if ! test -e "${systemDir}/security2.fdb"; then cp ${firebird}/security2.fdb "${systemDir}" fi - chown -R ${cfg.user} "${dataDir}" "${systemDir}" /var/log/firebird chmod -R 700 "${dataDir}" "${systemDir}" /var/log/firebird ''; - serviceConfig.PermissionsStartOnly = true; # preStart must be run as root serviceConfig.User = cfg.user; + serviceConfig.LogsDirectory = "firebird"; + serviceConfig.LogsDirectoryMode = "0700"; serviceConfig.ExecStart = ''${firebird}/bin/fbserver -d''; # TODO think about shutdown diff --git a/nixos/modules/services/databases/foundationdb.nix b/nixos/modules/services/databases/foundationdb.nix index 490c5e9d005..6182da5e7d6 100644 --- a/nixos/modules/services/databases/foundationdb.nix +++ b/nixos/modules/services/databases/foundationdb.nix @@ -359,6 +359,13 @@ in } ]; + systemd.tmpfiles.rules = [ + "d /etc/foundationdb 0755 ${cfg.user} ${cfg.group} - -" + "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" + "d '${cfg.logDir}' 0770 ${cfg.user} ${cfg.group} - -" + "F '${cfg.pidFile}' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.foundationdb = { description = "FoundationDB Service"; @@ -396,25 +403,12 @@ in path = [ pkg pkgs.coreutils ]; preStart = '' - rm -f ${cfg.pidfile} && \ - touch ${cfg.pidfile} && \ - chown -R ${cfg.user}:${cfg.group} ${cfg.pidfile} - - for x in "${cfg.logDir}" "${cfg.dataDir}"; do - [ ! -d "$x" ] && mkdir -m 0770 -vp "$x"; - chown -R ${cfg.user}:${cfg.group} "$x"; - done - - [ ! -d /etc/foundationdb ] && \ - mkdir -m 0775 -vp /etc/foundationdb && \ - chown -R ${cfg.user}:${cfg.group} "/etc/foundationdb" - if [ ! -f /etc/foundationdb/fdb.cluster ]; then cf=/etc/foundationdb/fdb.cluster desc=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8) rand=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8) echo ''${desc}:''${rand}@${initialIpAddr}:${builtins.toString cfg.listenPortStart} > $cf - chmod 0664 $cf && chown -R ${cfg.user}:${cfg.group} $cf + chmod 0664 $cf touch "${cfg.dataDir}/.first_startup" fi ''; diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix index 52f2d95b4e0..589c8cf5ec8 100644 --- a/nixos/modules/services/databases/hbase.nix +++ b/nixos/modules/services/databases/hbase.nix @@ -94,6 +94,11 @@ in { config = mkIf config.services.hbase.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -" + "d '${cfg.logDir}' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.hbase = { description = "HBase Server"; wantedBy = [ "multi-user.target" ]; @@ -103,19 +108,7 @@ in { HBASE_LOG_DIR = cfg.logDir; }; - preStart = - '' - mkdir -p ${cfg.dataDir}; - mkdir -p ${cfg.logDir}; - - if [ "$(id -u)" = 0 ]; then - chown ${cfg.user}:${cfg.group} ${cfg.dataDir} - chown ${cfg.user}:${cfg.group} ${cfg.logDir} - fi - ''; - serviceConfig = { - PermissionsStartOnly = true; User = cfg.user; Group = cfg.group; ExecStart = "${cfg.package}/bin/hbase --config ${configDir} master start"; diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 66d55b650a4..177e742d65e 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -204,12 +204,6 @@ in ''; }; - # FIXME: remove this option; it's a really bad idea. - rootPassword = mkOption { - default = null; - description = "Path to a file containing the root password, modified on the first startup. Not specifying a root password will leave the root password empty."; - }; - replication = { role = mkOption { type = types.enum [ "master" "slave" "none" ]; @@ -323,114 +317,105 @@ in 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 = - 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 - ''} + ExecStartPost = + let + setupScript = pkgs.writeShellScript "mysql-setup" '' + ${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 + ''} + + 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} + + ${optionalString (cfg.replication.role == "master") + '' + # Set up the replication master + + ( echo "use mysql;" + echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;" + echo "SET PASSWORD FOR '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' = PASSWORD('${cfg.replication.masterPassword}');" + echo "GRANT REPLICATION SLAVE ON *.* TO '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}';" + ) | ${mysql}/bin/mysql -u root -N + ''} + + ${optionalString (cfg.replication.role == "slave") + '' + # Set up the replication slave + + ( echo "stop slave;" + echo "change master to master_host='${cfg.replication.masterHost}', master_user='${cfg.replication.masterUser}', master_password='${cfg.replication.masterPassword}';" + echo "start slave;" + ) | ${mysql}/bin/mysql -u root -N + ''} + + ${optionalString (cfg.initialScript != null) + '' + # Execute initial script + # using toString to avoid copying the file to nix store if given as path instead of string, + # as it might contain credentials + cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N + ''} + + rm /tmp/mysql_init + fi + + ${optionalString (cfg.ensureDatabases != []) '' + ( + ${concatMapStrings (database: '' + echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" + '') cfg.ensureDatabases} ) | ${mysql}/bin/mysql -u root -N - fi - '') cfg.initialDatabases; - in - - lib.optionalString (!hasNotify) cmdWatchForMysqlSocket + '' - if [ -f /tmp/mysql_init ] - then - ${cmdInitialDatabases} - ${optionalString (cfg.replication.role == "master") - '' - # Set up the replication master - - ( echo "use mysql;" - echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;" - echo "SET PASSWORD FOR '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' = PASSWORD('${cfg.replication.masterPassword}');" - echo "GRANT REPLICATION SLAVE ON *.* TO '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}';" - ) | ${mysql}/bin/mysql -u root -N - ''} + ''} - ${optionalString (cfg.replication.role == "slave") + ${concatMapStrings (user: '' - # Set up the replication slave - - ( echo "stop slave;" - echo "change master to master_host='${cfg.replication.masterHost}', master_user='${cfg.replication.masterUser}', master_password='${cfg.replication.masterPassword}';" - echo "start slave;" + ( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};" + ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' + echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" + '') user.ensurePermissions)} ) | ${mysql}/bin/mysql -u root -N - ''} - - ${optionalString (cfg.initialScript != null) - '' - # Execute initial script - # using toString to avoid copying the file to nix store if given as path instead of string, - # as it might contain credentials - cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N - ''} - - ${optionalString (cfg.rootPassword != null) - '' - # Change root password - - ( echo "use mysql;" - echo "update user set Password=password('$(cat ${cfg.rootPassword})') where User='root';" - echo "flush privileges;" - ) | ${mysql}/bin/mysql -u root -N - ''} - - rm /tmp/mysql_init - fi - - ${optionalString (cfg.ensureDatabases != []) '' - ( - ${concatMapStrings (database: '' - echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" - '') cfg.ensureDatabases} - ) | ${mysql}/bin/mysql -u root -N - ''} - - ${concatMapStrings (user: - '' - ( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};" - ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' - echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" - '') user.ensurePermissions)} - ) | ${mysql}/bin/mysql -u root -N - '') cfg.ensureUsers} - - ''; # */ + '') cfg.ensureUsers} + ''; + in + # ensureDatbases & ensureUsers depends on this script being run as root + # when the user has secured their mysql install + "+${setupScript}"; + }; }; }; diff --git a/nixos/modules/services/desktops/deepin/deepin.nix b/nixos/modules/services/desktops/deepin/deepin.nix index d9d5d539e42..931bac58ace 100644 --- a/nixos/modules/services/desktops/deepin/deepin.nix +++ b/nixos/modules/services/desktops/deepin/deepin.nix @@ -33,8 +33,10 @@ environment.systemPackages = [ pkgs.deepin.dde-api pkgs.deepin.dde-calendar + pkgs.deepin.dde-control-center pkgs.deepin.dde-daemon pkgs.deepin.dde-dock + pkgs.deepin.dde-launcher pkgs.deepin.dde-file-manager pkgs.deepin.dde-session-ui pkgs.deepin.deepin-anything @@ -45,8 +47,10 @@ services.dbus.packages = [ pkgs.deepin.dde-api pkgs.deepin.dde-calendar + pkgs.deepin.dde-control-center pkgs.deepin.dde-daemon pkgs.deepin.dde-dock + pkgs.deepin.dde-launcher pkgs.deepin.dde-file-manager pkgs.deepin.dde-session-ui pkgs.deepin.deepin-anything diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix index 74a7b3c9b47..ee566825498 100644 --- a/nixos/modules/services/logging/graylog.nix +++ b/nixos/modules/services/logging/graylog.nix @@ -134,6 +134,10 @@ in }; }; + systemd.tmpfiles.rules = [ + "d '${cfg.messageJournalDir}' - ${cfg.user} - - -" + ]; + systemd.services.graylog = with pkgs; { description = "Graylog Server"; wantedBy = [ "multi-user.target" ]; @@ -143,8 +147,6 @@ in }; path = [ pkgs.jre_headless pkgs.which pkgs.procps ]; preStart = '' - mkdir -p /var/lib/graylog -m 755 - rm -rf /var/lib/graylog/plugins || true mkdir -p /var/lib/graylog/plugins -m 755 @@ -154,14 +156,10 @@ in for includedplugin in `ls ${cfg.package}/plugin/`; do ln -s ${cfg.package}/plugin/$includedplugin /var/lib/graylog/plugins/$includedplugin || true done - chown -R ${cfg.user} /var/lib/graylog - - mkdir -p ${cfg.messageJournalDir} -m 755 - chown -R ${cfg.user} ${cfg.messageJournalDir} ''; serviceConfig = { User="${cfg.user}"; - PermissionsStartOnly=true; + StateDirectory = "graylog"; ExecStart = "${cfg.package}/bin/graylogctl run"; }; }; diff --git a/nixos/modules/services/logging/heartbeat.nix b/nixos/modules/services/logging/heartbeat.nix index b595ac07bf5..56fb4deabda 100644 --- a/nixos/modules/services/logging/heartbeat.nix +++ b/nixos/modules/services/logging/heartbeat.nix @@ -54,16 +54,18 @@ in config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.stateDir}' - nobody nogroup - -" + ]; + systemd.services.heartbeat = with pkgs; { description = "heartbeat log shipper"; wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p "${cfg.stateDir}"/{data,logs} - chown nobody:nogroup "${cfg.stateDir}"/{data,logs} ''; serviceConfig = { User = "nobody"; - PermissionsStartOnly = true; AmbientCapabilities = "cap_net_raw"; ExecStart = "${pkgs.heartbeat}/bin/heartbeat -c \"${heartbeatYml}\" -path.data \"${cfg.stateDir}/data\" -path.logs \"${cfg.stateDir}/logs\""; }; diff --git a/nixos/modules/services/mail/dspam.nix b/nixos/modules/services/mail/dspam.nix index 167b5aeccc8..72b8c4c08b9 100644 --- a/nixos/modules/services/mail/dspam.nix +++ b/nixos/modules/services/mail/dspam.nix @@ -113,19 +113,14 @@ in { Group = cfg.group; RuntimeDirectory = optional (cfg.domainSocket == defaultSock) "dspam"; RuntimeDirectoryMode = optional (cfg.domainSocket == defaultSock) "0750"; - PermissionsStartOnly = true; + StateDirectory = "dspam"; + StateDirectoryMode = "0750"; + LogsDirectory = "dspam"; + LogsDirectoryMode = "0750"; # DSPAM segfaults on just about every error Restart = "on-abort"; RestartSec = "1s"; }; - - preStart = '' - mkdir -m750 -p /var/lib/dspam - chown -R "${cfg.user}:${cfg.group}" /var/lib/dspam - - mkdir -m750 -p /var/log/dspam - chown -R "${cfg.user}:${cfg.group}" /var/log/dspam - ''; }; } diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix index 7855efb46c7..253823cbaf9 100644 --- a/nixos/modules/services/mail/opendkim.nix +++ b/nixos/modules/services/mail/opendkim.nix @@ -101,13 +101,16 @@ in { environment.systemPackages = [ pkgs.opendkim ]; + systemd.tmpfiles.rules = [ + "d '${cfg.keyPath}' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.opendkim = { description = "OpenDKIM signing and verification daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' - mkdir -p "${cfg.keyPath}" cd "${cfg.keyPath}" if ! test -f ${cfg.selector}.private; then ${pkgs.opendkim}/bin/opendkim-genkey -s ${cfg.selector} -d all-domains-generic-key @@ -116,7 +119,6 @@ in { cat ${cfg.selector}.txt echo "-------------------------------------------------------------" fi - chown ${cfg.user}:${cfg.group} ${cfg.selector}.private ''; serviceConfig = { @@ -124,7 +126,6 @@ in { User = cfg.user; Group = cfg.group; RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim"; - PermissionsStartOnly = true; }; }; diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix index e8b2e11bf72..12837f7efe7 100644 --- a/nixos/modules/services/mail/roundcube.nix +++ b/nixos/modules/services/mail/roundcube.nix @@ -105,7 +105,7 @@ in extraConfig = '' location ~* \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:/run/phpfpm/roundcube; + fastcgi_pass unix:/run/phpfpm-roundcube/roundcube.sock; include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi.conf; } @@ -119,24 +119,28 @@ in enable = true; }; - services.phpfpm.poolConfigs.roundcube = '' - listen = /run/phpfpm/roundcube - listen.owner = nginx - listen.group = nginx - listen.mode = 0660 - user = nginx - pm = dynamic - pm.max_children = 75 - pm.start_servers = 2 - pm.min_spare_servers = 1 - pm.max_spare_servers = 20 - pm.max_requests = 500 - php_admin_value[error_log] = 'stderr' - php_admin_flag[log_errors] = on - php_admin_value[post_max_size] = 25M - php_admin_value[upload_max_filesize] = 25M - catch_workers_output = yes - ''; + services.phpfpm.pools.roundcube = { + socketName = "roundcube"; + phpPackage = pkgs.php; + user = "${config.services.nginx.user}"; + group = "${config.services.nginx.group}"; + extraConfig = '' + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} + listen.mode = 0600 + pm = dynamic + pm.max_children = 75 + pm.start_servers = 2 + pm.min_spare_servers = 1 + pm.max_spare_servers = 20 + pm.max_requests = 500 + php_admin_value[error_log] = 'stderr' + php_admin_flag[log_errors] = on + php_admin_value[post_max_size] = 25M + php_admin_value[upload_max_filesize] = 25M + catch_workers_output = yes + ''; + }; systemd.services.phpfpm-roundcube.after = [ "roundcube-setup.service" ]; systemd.services.roundcube-setup = let diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix index 363ac4411e1..9eeae955699 100644 --- a/nixos/modules/services/misc/apache-kafka.nix +++ b/nixos/modules/services/misc/apache-kafka.nix @@ -131,6 +131,8 @@ in { home = head cfg.logDirs; }; + systemd.tmpfiles.rules = map (logDir: "d '${logDir} 0700 apache-kafka - - -") cfg.logDirs; + systemd.services.apache-kafka = { description = "Apache Kafka Daemon"; wantedBy = [ "multi-user.target" ]; @@ -145,15 +147,8 @@ in { ${serverConfig} ''; User = "apache-kafka"; - PermissionsStartOnly = true; SuccessExitStatus = "0 143"; }; - preStart = '' - mkdir -m 0700 -p ${concatStringsSep " " cfg.logDirs} - if [ "$(id -u)" = 0 ]; then - chown apache-kafka ${concatStringsSep " " cfg.logDirs}; - fi - ''; }; }; diff --git a/nixos/modules/services/misc/couchpotato.nix b/nixos/modules/services/misc/couchpotato.nix index 70aa895f76d..528af486b41 100644 --- a/nixos/modules/services/misc/couchpotato.nix +++ b/nixos/modules/services/misc/couchpotato.nix @@ -19,16 +19,11 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - preStart = '' - mkdir -p /var/lib/couchpotato - chown -R couchpotato:couchpotato /var/lib/couchpotato - ''; - serviceConfig = { Type = "simple"; User = "couchpotato"; Group = "couchpotato"; - PermissionsStartOnly = "true"; + StateDirectory = "couchpotato"; ExecStart = "${pkgs.couchpotato}/bin/couchpotato"; Restart = "on-failure"; }; diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index d1807a90619..5a964e672ed 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -38,6 +38,7 @@ let HTTP_PORT = ${toString cfg.httpPort} ROOT_URL = ${cfg.rootUrl} STATIC_ROOT_PATH = ${cfg.staticRootPath} + LFS_JWT_SECRET = #jwtsecret# [session] COOKIE_NAME = session @@ -326,21 +327,28 @@ in preStart = let runConfig = "${cfg.stateDir}/custom/conf/app.ini"; secretKey = "${cfg.stateDir}/custom/conf/secret_key"; + jwtSecret = "${cfg.stateDir}/custom/conf/jwt_secret"; in '' # copy custom configuration and generate a random secret key if needed ${optionalString (cfg.useWizard == false) '' cp -f ${configFile} ${runConfig} if [ ! -e ${secretKey} ]; then - head -c 16 /dev/urandom | base64 > ${secretKey} + ${gitea.bin}/bin/gitea generate secret SECRET_KEY > ${secretKey} fi - KEY=$(head -n1 ${secretKey}) - DBPASS=$(head -n1 ${cfg.database.passwordFile}) + if [ ! -e ${jwtSecret} ]; then + ${gitea.bin}/bin/gitea generate secret LFS_JWT_SECRET > ${jwtSecret} + fi + + KEY="$(head -n1 ${secretKey})" + DBPASS="$(head -n1 ${cfg.database.passwordFile})" + JWTSECRET="$(head -n1 ${jwtSecret})" sed -e "s,#secretkey#,$KEY,g" \ -e "s,#dbpass#,$DBPASS,g" \ + -e "s,#jwtsecet#,$JWTSECET,g" \ -i ${runConfig} - chmod 640 ${runConfig} ${secretKey} + chmod 640 ${runConfig} ${secretKey} ${jwtSecret} ''} # update all hooks' binary paths diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix index d1823bc6d4d..7653b415bf0 100644 --- a/nixos/modules/services/misc/gollum.nix +++ b/nixos/modules/services/misc/gollum.nix @@ -75,27 +75,24 @@ in users.groups.gollum = { }; + systemd.tmpfiles.rules = [ + "d '${cfg.stateDir}' - ${config.users.users.gollum.name} ${config.users.groups.gollum.name} - -" + ]; + systemd.services.gollum = { description = "Gollum wiki"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; path = [ pkgs.git ]; - preStart = let - userName = config.users.users.gollum.name; - groupName = config.users.groups.gollum.name; - in '' - # All of this is safe to be run on an existing repo - mkdir -p ${cfg.stateDir} + preStart = '' + # This is safe to be run on an existing repo git init ${cfg.stateDir} - chmod 755 ${cfg.stateDir} - chown -R ${userName}:${groupName} ${cfg.stateDir} ''; serviceConfig = { User = config.users.users.gollum.name; Group = config.users.groups.gollum.name; - PermissionsStartOnly = true; ExecStart = '' ${pkgs.gollum}/bin/gollum \ --port ${toString cfg.port} \ diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix index f466402abfc..92108ec5508 100644 --- a/nixos/modules/services/misc/lidarr.nix +++ b/nixos/modules/services/misc/lidarr.nix @@ -9,6 +9,13 @@ in options = { services.lidarr = { enable = mkEnableOption "Lidarr"; + + package = mkOption { + type = types.package; + default = pkgs.lidarr; + defaultText = "pkgs.lidarr"; + description = "The Lidarr package to use"; + }; }; }; @@ -22,7 +29,7 @@ in Type = "simple"; User = "lidarr"; Group = "lidarr"; - ExecStart = "${pkgs.lidarr}/bin/Lidarr"; + ExecStart = "${cfg.package}/bin/Lidarr"; Restart = "on-failure"; StateDirectory = "lidarr"; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 8db3c44246f..d8f90f1539c 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -272,10 +272,12 @@ in binaryCaches = mkOption { type = types.listOf types.str; - default = [ https://cache.nixos.org/ ]; description = '' List of binary cache URLs used to obtain pre-built binaries of Nix packages. + + By default https://cache.nixos.org/ is added, + to override it use <literal>lib.mkForce []</literal>. ''; }; @@ -386,6 +388,7 @@ in config = { nix.binaryCachePublicKeys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; + nix.binaryCaches = [ "https://cache.nixos.org/" ]; environment.etc."nix/nix.conf".source = nixConf; diff --git a/nixos/modules/services/misc/octoprint.nix b/nixos/modules/services/misc/octoprint.nix index 52ae25201c3..8950010773c 100644 --- a/nixos/modules/services/misc/octoprint.nix +++ b/nixos/modules/services/misc/octoprint.nix @@ -97,6 +97,10 @@ in gid = config.ids.gids.octoprint; }); + systemd.tmpfiles.rules = [ + "d '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.octoprint = { description = "OctoPrint, web interface for 3D printers"; wantedBy = [ "multi-user.target" ]; @@ -105,7 +109,6 @@ in environment.PYTHONPATH = makeSearchPathOutput "lib" pkgs.python.sitePackages [ pluginsEnv ]; preStart = '' - mkdir -p "${cfg.stateDir}" if [ -e "${cfg.stateDir}/config.yaml" ]; then ${pkgs.yaml-merge}/bin/yaml-merge "${cfg.stateDir}/config.yaml" "${cfgUpdate}" > "${cfg.stateDir}/config.yaml.tmp" mv "${cfg.stateDir}/config.yaml.tmp" "${cfg.stateDir}/config.yaml" @@ -113,14 +116,12 @@ in cp "${cfgUpdate}" "${cfg.stateDir}/config.yaml" chmod 600 "${cfg.stateDir}/config.yaml" fi - chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}" ''; serviceConfig = { ExecStart = "${pkgs.octoprint}/bin/octoprint serve -b ${cfg.stateDir}"; User = cfg.user; Group = cfg.group; - PermissionsStartOnly = true; }; }; diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix index 9c555e8031c..b0ee961c77f 100644 --- a/nixos/modules/services/misc/zoneminder.nix +++ b/nixos/modules/services/misc/zoneminder.nix @@ -19,7 +19,7 @@ let useCustomDir = cfg.storageDir != null; - socket = "/run/phpfpm/${dirName}.sock"; + socket = "/run/phpfpm-zoneminder/zoneminder.sock"; zms = "/cgi-bin/zms"; @@ -50,7 +50,7 @@ let ZM_DB_TYPE=mysql ZM_DB_HOST=${cfg.database.host} ZM_DB_NAME=${cfg.database.name} - ZM_DB_USER=${if cfg.database.createLocally then user else cfg.database.username} + ZM_DB_USER=${cfg.database.username} ZM_DB_PASS=${cfg.database.password} # Web @@ -155,6 +155,7 @@ in { default = "zmpass"; description = '' Username for accessing the database. + Not used if <literal>createLocally</literal> is set. ''; }; }; @@ -189,6 +190,12 @@ in { config = lib.mkIf cfg.enable { + assertions = [ + { assertion = cfg.database.createLocally -> cfg.database.username == user; + message = "services.zoneminder.database.username must be set to ${user} if services.zoneminder.database.createLocally is set true"; + } + ]; + environment.etc = { "zoneminder/60-defaults.conf".source = defaultsFile; "zoneminder/80-nixos.conf".source = configFile; @@ -204,10 +211,9 @@ in { }; mysql = lib.mkIf cfg.database.createLocally { + enable = true; + package = lib.mkDefault pkgs.mariadb; ensureDatabases = [ cfg.database.name ]; - initialDatabases = [{ - inherit (cfg.database) name; schema = "${pkg}/share/zoneminder/db/zm_create.sql"; - }]; ensureUsers = [{ name = cfg.database.username; ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; }; @@ -278,7 +284,10 @@ in { phpfpm = lib.mkIf useNginx { pools.zoneminder = { - listen = socket; + socketName = "zoneminder"; + phpPackage = pkgs.php; + user = "${user}"; + group = "${group}"; phpOptions = '' date.timezone = "${config.time.timeZone}" @@ -286,9 +295,6 @@ in { "extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)} ''; extraConfig = '' - user = ${user} - group = ${group} - listen.owner = ${user} listen.group = ${group} listen.mode = 0660 @@ -315,11 +321,16 @@ in { procps psmisc ]; - after = [ "mysql.service" "nginx.service" ]; + after = [ "nginx.service" ] ++ lib.optional cfg.database.createLocally "mysql.service"; wantedBy = [ "multi-user.target" ]; restartTriggers = [ defaultsFile configFile ]; - preStart = lib.mkIf useCustomDir '' + preStart = lib.optionalString useCustomDir '' install -dm775 -o ${user} -g ${group} ${cfg.storageDir}/{${lib.concatStringsSep "," libDirs}} + '' + lib.optionalString cfg.database.createLocally '' + if ! test -e "/var/lib/${dirName}/db-created"; then + ${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql + touch "/var/lib/${dirName}/db-created" + fi ''; serviceConfig = { User = user; diff --git a/nixos/modules/services/monitoring/alerta.nix b/nixos/modules/services/monitoring/alerta.nix index d423a91993c..34f2d41706a 100644 --- a/nixos/modules/services/monitoring/alerta.nix +++ b/nixos/modules/services/monitoring/alerta.nix @@ -83,6 +83,10 @@ in }; config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.logDir}' - alerta alerta - -" + ]; + systemd.services.alerta = { description = "Alerta Monitoring System"; wantedBy = [ "multi-user.target" ]; @@ -94,12 +98,7 @@ in ExecStart = "${pkgs.python36Packages.alerta-server}/bin/alertad run --port ${toString cfg.port} --host ${cfg.bind}"; User = "alerta"; Group = "alerta"; - PermissionsStartOnly = true; }; - preStart = '' - mkdir -p ${cfg.logDir} - chown alerta:alerta ${cfg.logDir} - ''; }; environment.systemPackages = [ pkgs.python36Packages.alerta ]; diff --git a/nixos/modules/services/monitoring/kapacitor.nix b/nixos/modules/services/monitoring/kapacitor.nix index cc4074be111..0f236d25c9e 100644 --- a/nixos/modules/services/monitoring/kapacitor.nix +++ b/nixos/modules/services/monitoring/kapacitor.nix @@ -163,6 +163,10 @@ in config = mkIf cfg.enable { environment.systemPackages = [ pkgs.kapacitor ]; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.kapacitor = { description = "Kapacitor Real-Time Stream Processing Engine"; wantedBy = [ "multi-user.target" ]; @@ -171,12 +175,7 @@ in ExecStart = "${pkgs.kapacitor}/bin/kapacitord -config ${kapacitorConf}"; User = "kapacitor"; Group = "kapacitor"; - PermissionsStartOnly = true; }; - preStart = '' - mkdir -p ${cfg.dataDir} - chown ${cfg.user}:${cfg.group} ${cfg.dataDir} - ''; }; users.users.kapacitor = { diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index a49555cf677..12a0961c406 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -143,7 +143,6 @@ in { User = cfg.user; Group = cfg.group; Environment="PYTHONPATH=${pkgs.netdata}/libexec/netdata/python.d/python_modules"; - PermissionsStartOnly = true; ExecStart = "${pkgs.netdata}/bin/netdata -D -c ${configFile}"; TimeoutStopSec = 60; }; diff --git a/nixos/modules/services/monitoring/riemann-dash.nix b/nixos/modules/services/monitoring/riemann-dash.nix index 7eb4d888b0c..16eb8300850 100644 --- a/nixos/modules/services/monitoring/riemann-dash.nix +++ b/nixos/modules/services/monitoring/riemann-dash.nix @@ -59,18 +59,20 @@ in { group = "riemanndash"; }; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - riemanndash riemanndash - -" + ]; + systemd.services.riemann-dash = { wantedBy = [ "multi-user.target" ]; wants = [ "riemann.service" ]; after = [ "riemann.service" ]; preStart = '' - mkdir -p ${cfg.dataDir}/config - chown -R riemanndash:riemanndash ${cfg.dataDir} + mkdir -p '${cfg.dataDir}/config' ''; serviceConfig = { User = "riemanndash"; ExecStart = "${launcher}/bin/riemann-dash"; - PermissionsStartOnly = true; }; }; diff --git a/nixos/modules/services/monitoring/riemann-tools.nix b/nixos/modules/services/monitoring/riemann-tools.nix index 4e8832dadc5..9c400a1e3e4 100644 --- a/nixos/modules/services/monitoring/riemann-tools.nix +++ b/nixos/modules/services/monitoring/riemann-tools.nix @@ -54,7 +54,6 @@ in { serviceConfig = { User = "riemanntools"; ExecStart = "${healthLauncher}/bin/riemann-health"; - PermissionsStartOnly = true; }; }; diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix index fbded746a5f..dc0899c7e68 100644 --- a/nixos/modules/services/monitoring/scollector.nix +++ b/nixos/modules/services/monitoring/scollector.nix @@ -116,7 +116,6 @@ in { path = [ pkgs.coreutils pkgs.iproute ]; serviceConfig = { - PermissionsStartOnly = true; User = cfg.user; Group = cfg.group; ExecStart = "${cfg.package.bin}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}"; diff --git a/nixos/modules/services/networking/aria2.nix b/nixos/modules/services/networking/aria2.nix index 98eb0086101..53829bf1886 100644 --- a/nixos/modules/services/networking/aria2.nix +++ b/nixos/modules/services/networking/aria2.nix @@ -102,22 +102,19 @@ in users.groups.aria2.gid = config.ids.gids.aria2; + systemd.tmpfiles.rules = [ + "d '${homeDir}' 0770 aria2 aria2 - -" + "d '${config.services.aria2.downloadDir}' 0770 aria2 aria2 - -" + ]; + systemd.services.aria2 = { description = "aria2 Service"; after = [ "local-fs.target" "network.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' - mkdir -m 0770 -p "${homeDir}" - chown aria2:aria2 "${homeDir}" - if [[ ! -d "${config.services.aria2.downloadDir}" ]] - then - mkdir -m 0770 -p "${config.services.aria2.downloadDir}" - chown aria2:aria2 "${config.services.aria2.downloadDir}" - fi if [[ ! -e "${sessionFile}" ]] then touch "${sessionFile}" - chown aria2:aria2 "${sessionFile}" fi cp -f "${settingsFile}" "${settingsDir}/aria2.conf" ''; @@ -128,7 +125,6 @@ in ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; User = "aria2"; Group = "aria2"; - PermissionsStartOnly = true; }; }; }; diff --git a/nixos/modules/services/networking/autossh.nix b/nixos/modules/services/networking/autossh.nix index 9ea17469870..a098a155e99 100644 --- a/nixos/modules/services/networking/autossh.nix +++ b/nixos/modules/services/networking/autossh.nix @@ -99,7 +99,6 @@ in serviceConfig = { User = "${s.user}"; - PermissionsStartOnly = true; # AutoSSH may exit with 0 code if the SSH session was # gracefully terminated by either local or remote side. Restart = "on-success"; diff --git a/nixos/modules/services/networking/charybdis.nix b/nixos/modules/services/networking/charybdis.nix index 3d02dc8d137..e3aba063f87 100644 --- a/nixos/modules/services/networking/charybdis.nix +++ b/nixos/modules/services/networking/charybdis.nix @@ -83,6 +83,10 @@ in gid = config.ids.gids.ircd; }; + systemd.tmpfiles.rules = [ + "d ${cfg.statedir} - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.charybdis = { description = "Charybdis IRC daemon"; wantedBy = [ "multi-user.target" ]; @@ -93,12 +97,7 @@ in ExecStart = "${charybdis}/bin/charybdis -foreground -logfile /dev/stdout -configfile ${configFile}"; Group = cfg.group; User = cfg.user; - PermissionsStartOnly = true; # preStart needs to run with root permissions }; - preStart = '' - ${coreutils}/bin/mkdir -p ${cfg.statedir} - ${coreutils}/bin/chown ${cfg.user}:${cfg.group} ${cfg.statedir} - ''; }; } diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix index 7add48308f8..54a5bed2563 100644 --- a/nixos/modules/services/networking/hostapd.nix +++ b/nixos/modules/services/networking/hostapd.nix @@ -30,10 +30,11 @@ let ctrl_interface=/run/hostapd ctrl_interface_group=${cfg.group} - ${if cfg.wpa then '' + ${optionalString cfg.wpa '' wpa=2 wpa_passphrase=${cfg.wpaPassphrase} - '' else ""} + ''} + ${optionalString cfg.noScan "noscan=1"} ${cfg.extraConfig} '' ; @@ -69,6 +70,14 @@ in ''; }; + noScan = mkOption { + default = false; + description = '' + Do not scan for overlapping BSSs in HT40+/- mode. + Caution: turning this on will violate regulatory requirements! + ''; + }; + driver = mkOption { default = "nl80211"; example = "hostapd"; @@ -162,6 +171,7 @@ in after = [ "sys-subsystem-net-devices-${escapedInterface}.device" ]; bindsTo = [ "sys-subsystem-net-devices-${escapedInterface}.device" ]; requiredBy = [ "network-link-${cfg.interface}.service" ]; + wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.hostapd}/bin/hostapd ${configFile}"; diff --git a/nixos/modules/services/networking/minidlna.nix b/nixos/modules/services/networking/minidlna.nix index 1858f03cac1..ed0c1044a57 100644 --- a/nixos/modules/services/networking/minidlna.nix +++ b/nixos/modules/services/networking/minidlna.nix @@ -98,16 +98,10 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" "local-fs.target" ]; - preStart = - '' - mkdir -p /var/cache/minidlna - chown -R minidlna:minidlna /var/cache/minidlna - ''; - serviceConfig = { User = "minidlna"; Group = "minidlna"; - PermissionsStartOnly = true; + CacheDirectory = "minidlna"; RuntimeDirectory = "minidlna"; PIDFile = "/run/minidlna/pid"; ExecStart = diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix index b223a48e055..b495b3948fb 100644 --- a/nixos/modules/services/networking/quassel.nix +++ b/nixos/modules/services/networking/quassel.nix @@ -104,6 +104,10 @@ in gid = config.ids.gids.quassel; }]; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - ${user} - - -" + ]; + systemd.services.quassel = { description = "Quassel IRC client daemon"; @@ -111,11 +115,6 @@ in after = [ "network.target" ] ++ optional config.services.postgresql.enable "postgresql.service" ++ optional config.services.mysql.enable "mysql.service"; - preStart = '' - mkdir -p ${cfg.dataDir} - chown ${user} ${cfg.dataDir} - ''; - serviceConfig = { ExecStart = concatStringsSep " " ([ @@ -126,7 +125,6 @@ in ] ++ optional cfg.requireSSL "--require-ssl" ++ optional (cfg.certificateFile != null) "--ssl-cert=${cfg.certificateFile}"); User = user; - PermissionsStartOnly = true; }; }; diff --git a/nixos/modules/services/networking/squid.nix b/nixos/modules/services/networking/squid.nix index b220c21b604..9d063b92aa1 100644 --- a/nixos/modules/services/networking/squid.nix +++ b/nixos/modules/services/networking/squid.nix @@ -159,11 +159,10 @@ in serviceConfig = { Type="forking"; PIDFile="/run/squid.pid"; - PermissionsStartOnly = true; ExecStart = "${pkgs.squid}/bin/squid -YCs -f ${squidConfig}"; }; }; }; -} \ No newline at end of file +} diff --git a/nixos/modules/services/networking/teamspeak3.nix b/nixos/modules/services/networking/teamspeak3.nix index 9ea9c83e37c..fadb32dcd77 100644 --- a/nixos/modules/services/networking/teamspeak3.nix +++ b/nixos/modules/services/networking/teamspeak3.nix @@ -111,16 +111,15 @@ in gid = config.ids.gids.teamspeak; }; + systemd.tmpfiles.rules = [ + "d '${cfg.logPath}' - ${user} ${group} - -" + ]; + systemd.services.teamspeak3-server = { description = "Teamspeak3 voice communication server daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - preStart = '' - mkdir -p ${cfg.logPath} - chown ${user}:${group} ${cfg.logPath} - ''; - serviceConfig = { ExecStart = '' ${ts3}/bin/ts3server \ @@ -135,7 +134,6 @@ in WorkingDirectory = cfg.dataDir; User = user; Group = group; - PermissionsStartOnly = true; }; }; }; diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix index c82e0af2803..9057a1e12b3 100644 --- a/nixos/modules/services/networking/unifi.nix +++ b/nixos/modules/services/networking/unifi.nix @@ -146,6 +146,11 @@ in where = where; }) mountPoints; + systemd.tmpfiles.rules = [ + "e '${stateDir}' 0700 unifi - - -" + "e '${stateDir}/data' 0700 unifi - - -" + ]; + systemd.services.unifi = { description = "UniFi controller daemon"; wantedBy = [ "multi-user.target" ]; @@ -157,14 +162,9 @@ in environment.LD_LIBRARY_PATH = with pkgs.stdenv; "${cc.cc.lib}/lib"; preStart = '' - # Ensure privacy of state and data. - chown unifi "${stateDir}" "${stateDir}/data" - chmod 0700 "${stateDir}" "${stateDir}/data" - # Create the volatile webapps rm -rf "${stateDir}/webapps" mkdir -p "${stateDir}/webapps" - chown unifi "${stateDir}/webapps" ln -s "${cfg.unifiPackage}/webapps/ROOT" "${stateDir}/webapps/ROOT" ''; @@ -177,7 +177,6 @@ in ExecStart = "${(removeSuffix "\n" cmd)} start"; ExecStop = "${(removeSuffix "\n" cmd)} stop"; User = "unifi"; - PermissionsStartOnly = true; UMask = "0077"; WorkingDirectory = "${stateDir}"; }; diff --git a/nixos/modules/services/networking/zeronet.nix b/nixos/modules/services/networking/zeronet.nix index 611a51c74ce..f4988a90268 100644 --- a/nixos/modules/services/networking/zeronet.nix +++ b/nixos/modules/services/networking/zeronet.nix @@ -86,20 +86,17 @@ in with lib; { ''; }; + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' 750 zeronet zeronet - -" + "d '${cfg.logDir}' 750 zeronet zeronet - -" + ]; + systemd.services.zeronet = { description = "zeronet"; after = [ "network.target" (optionalString cfg.tor "tor.service") ]; wantedBy = [ "multi-user.target" ]; - preStart = '' - # Ensure folder exists or create it and permissions are correct - mkdir -p ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir} - chmod 750 ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir} - chown zeronet:zeronet ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir} - ''; - serviceConfig = { - PermissionsStartOnly = true; PrivateTmp = "yes"; User = "zeronet"; Group = "zeronet"; diff --git a/nixos/modules/services/web-apps/atlassian/confluence.nix b/nixos/modules/services/web-apps/atlassian/confluence.nix index 15744d90cc7..cf163271d27 100644 --- a/nixos/modules/services/web-apps/atlassian/confluence.nix +++ b/nixos/modules/services/web-apps/atlassian/confluence.nix @@ -149,6 +149,17 @@ in users.groups."${cfg.group}" = {}; + systemd.tmpfiles.rules = [ + "d '${cfg.home}' - ${cfg.user} - - -" + "d /run/confluence - - - - -" + + "L+ /run/confluence/home - - - - ${cfg.home}" + "L+ /run/confluence/logs - - - - ${cfg.home}/logs" + "L+ /run/confluence/temp - - - - ${cfg.home}/temp" + "L+ /run/confluence/work - - - - ${cfg.home}/work" + "L+ /run/confluence/server.xml - - - - ${cfg.home}/server.xml" + ]; + systemd.services.confluence = { description = "Atlassian Confluence"; @@ -167,12 +178,6 @@ in preStart = '' mkdir -p ${cfg.home}/{logs,work,temp,deploy} - mkdir -p /run/confluence - ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/confluence - ln -sf ${cfg.home} /run/confluence/home - - chown ${cfg.user} ${cfg.home} - sed -e 's,port="8090",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \ '' + (lib.optionalString cfg.proxy.enable '' -e 's,protocol="org.apache.coyote.http11.Http11NioProtocol",protocol="org.apache.coyote.http11.Http11NioProtocol" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}",' \ @@ -184,7 +189,6 @@ in User = cfg.user; Group = cfg.group; PrivateTmp = true; - PermissionsStartOnly = true; ExecStart = "${pkg}/bin/start-confluence.sh -fg"; ExecStop = "${pkg}/bin/stop-confluence.sh"; }; diff --git a/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixos/modules/services/web-apps/atlassian/crowd.nix index c144b21bdaf..020ca8d89db 100644 --- a/nixos/modules/services/web-apps/atlassian/crowd.nix +++ b/nixos/modules/services/web-apps/atlassian/crowd.nix @@ -117,6 +117,16 @@ in users.groups."${cfg.group}" = {}; + systemd.tmpfiles.rules = [ + "d '${cfg.home}' - ${cfg.user} ${cfg.group} - -" + "d /run/atlassian-crowd - - - - -" + + "L+ /run/atlassian-crowd/database - - - - ${cfg.home}/database" + "L+ /run/atlassian-crowd/logs - - - - ${cfg.home}/logs" + "L+ /run/atlassian-crowd/work - - - - ${cfg.home}/work" + "L+ /run/atlassian-crowd/server.xml - - - - ${cfg.home}/server.xml" + ]; + systemd.services.atlassian-crowd = { description = "Atlassian Crowd"; @@ -136,12 +146,6 @@ in rm -rf ${cfg.home}/work mkdir -p ${cfg.home}/{logs,database,work} - mkdir -p /run/atlassian-crowd - ln -sf ${cfg.home}/{database,logs,work,server.xml} /run/atlassian-crowd - - chown ${cfg.user}:${cfg.group} ${cfg.home} - chown ${cfg.user}:${cfg.group} ${cfg.home}/{logs,database,work} - sed -e 's,port="8095",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \ '' + (lib.optionalString cfg.proxy.enable '' -e 's,compression="on",compression="off" protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${boolToString cfg.proxy.secure}",' \ @@ -153,7 +157,6 @@ in User = cfg.user; Group = cfg.group; PrivateTmp = true; - PermissionsStartOnly = true; ExecStart = "${pkg}/start_crowd.sh -fg"; }; }; diff --git a/nixos/modules/services/web-apps/atlassian/jira.nix b/nixos/modules/services/web-apps/atlassian/jira.nix index 0b3a5722d6c..b0019e77ac2 100644 --- a/nixos/modules/services/web-apps/atlassian/jira.nix +++ b/nixos/modules/services/web-apps/atlassian/jira.nix @@ -155,6 +155,17 @@ in users.groups."${cfg.group}" = {}; + systemd.tmpfiles.rules = [ + "d '${cfg.home}' - ${cfg.user} - - -" + "d /run/atlassian-jira - - - - -" + + "L+ /run/atlassian-jira/home - - - - ${cfg.home}" + "L+ /run/atlassian-jira/logs - - - - ${cfg.home}/logs" + "L+ /run/atlassian-jira/work - - - - ${cfg.home}/work" + "L+ /run/atlassian-jira/temp - - - - ${cfg.home}/temp" + "L+ /run/atlassian-jira/server.xml - - - - ${cfg.home}/server.xml" + ]; + systemd.services.atlassian-jira = { description = "Atlassian JIRA"; @@ -174,12 +185,6 @@ in preStart = '' mkdir -p ${cfg.home}/{logs,work,temp,deploy} - mkdir -p /run/atlassian-jira - ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/atlassian-jira - ln -sf ${cfg.home} /run/atlassian-jira/home - - chown ${cfg.user} ${cfg.home} - sed -e 's,port="8080",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \ '' + (lib.optionalString cfg.proxy.enable '' -e 's,protocol="HTTP/1.1",protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \ @@ -191,7 +196,6 @@ in User = cfg.user; Group = cfg.group; PrivateTmp = true; - PermissionsStartOnly = true; ExecStart = "${pkg}/bin/start-jira.sh -fg"; ExecStop = "${pkg}/bin/stop-jira.sh"; }; diff --git a/nixos/modules/services/web-apps/frab.nix b/nixos/modules/services/web-apps/frab.nix index fb95e024817..e885dc69b3c 100644 --- a/nixos/modules/services/web-apps/frab.nix +++ b/nixos/modules/services/web-apps/frab.nix @@ -182,16 +182,16 @@ in users.groups = [ { name = cfg.group; } ]; + systemd.tmpfiles.rules = [ + "d '${cfg.statePath}/system/attachments' - ${cfg.user} ${cfg.group} - -" + ]; + systemd.services.frab = { after = [ "network.target" "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; environment = frabEnv; preStart = '' - mkdir -p ${cfg.statePath}/system/attachments - chown ${cfg.user}:${cfg.group} -R ${cfg.statePath} - - mkdir /run/frab -p ln -sf ${pkgs.writeText "frab-database.yml" databaseConfig} /run/frab/database.yml ln -sf ${cfg.statePath}/system /run/frab/system @@ -204,7 +204,6 @@ in ''; serviceConfig = { - PermissionsStartOnly = true; PrivateTmp = true; PrivateDevices = true; Type = "simple"; @@ -213,6 +212,7 @@ in TimeoutSec = "300s"; Restart = "on-failure"; RestartSec = "10s"; + RuntimeDirectory = "frab"; WorkingDirectory = "${package}/share/frab"; ExecStart = "${frab-rake}/bin/frab-bundle exec rails server " + "--binding=${cfg.listenAddress} --port=${toString cfg.listenPort}"; diff --git a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix index 910e1d937bf..e83270fda5c 100644 --- a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix +++ b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix @@ -1,7 +1,6 @@ { config, lib, pkgs, ... }: with lib; let cfg = config.services.icingaweb2; poolName = "icingaweb2"; - phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock"; defaultConfig = { global = { @@ -162,19 +161,23 @@ in { }; config = mkIf cfg.enable { - services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { - "${poolName}" = '' - listen = "${phpfpmSocketName}" - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = icingaweb2 - pm = dynamic - pm.max_children = 75 - pm.start_servers = 2 - pm.min_spare_servers = 2 - pm.max_spare_servers = 10 - ''; + services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { + "${poolName}" = { + socketName = "${poolName}"; + phpPackage = pkgs.php; + user = "icingaweb2"; + group = "icingaweb2"; + extraConfig = '' + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} + listen.mode = 0600 + pm = dynamic + pm.max_children = 75 + pm.start_servers = 2 + pm.min_spare_servers = 2 + pm.max_spare_servers = 10 + ''; + }; }; services.phpfpm.phpOptions = mkIf (cfg.pool == "${poolName}") @@ -206,7 +209,7 @@ in { include ${config.services.nginx.package}/conf/fastcgi.conf; try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_pass unix:/run/phpfpm-${poolName}/${poolName}.sock; fastcgi_param SCRIPT_FILENAME ${pkgs.icingaweb2}/public/index.php; ''; }; @@ -239,5 +242,8 @@ in { group = "icingaweb2"; isSystemUser = true; }; + users.users.nginx = { + extraGroups = [ "icingaweb2" ]; + }; }; } diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix index f23b3075574..99a33b8371c 100644 --- a/nixos/modules/services/web-apps/limesurvey.nix +++ b/nixos/modules/services/web-apps/limesurvey.nix @@ -202,13 +202,13 @@ in }; services.phpfpm.pools.limesurvey = { + socketName = "limesurvey"; phpPackage = php; - listen = "/run/phpfpm/limesurvey.sock"; + user = "${user}"; + group = "${group}"; extraConfig = '' listen.owner = ${config.services.httpd.user}; listen.group = ${config.services.httpd.group}; - user = ${user}; - group = ${group}; env[LIMESURVEY_CONFIG] = ${limesurveyConfig} @@ -241,7 +241,7 @@ in <Directory "${pkg}/share/limesurvey"> <FilesMatch "\.php$"> <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:/run/phpfpm/limesurvey.sock|fcgi://localhost/" + SetHandler "proxy:unix:/run/phpfpm-limesurvey/limesurvey.sock|fcgi://localhost/" </If> </FilesMatch> diff --git a/nixos/modules/services/web-apps/matomo.nix b/nixos/modules/services/web-apps/matomo.nix index 14aca45a342..e058c18ad87 100644 --- a/nixos/modules/services/web-apps/matomo.nix +++ b/nixos/modules/services/web-apps/matomo.nix @@ -4,13 +4,14 @@ let cfg = config.services.matomo; user = "matomo"; + group = "matomo"; dataDir = "/var/lib/${user}"; deprecatedDataDir = "/var/lib/piwik"; pool = user; - # it's not possible to use /run/phpfpm/${pool}.sock because /run/phpfpm/ is root:root 0770, + # it's not possible to use /run/phpfpm-${pool}/${pool}.sock because /run/phpfpm/ is root:root 0770, # and therefore is not accessible by the web server. - phpSocket = "/run/phpfpm-${pool}.sock"; + phpSocket = "/run/phpfpm-${pool}/${pool}.sock"; phpExecutionUnit = "phpfpm-${pool}"; databaseService = "mysql.service"; @@ -137,9 +138,12 @@ in { isSystemUser = true; createHome = true; home = dataDir; - group = user; + group = "${group}"; }; - users.groups.${user} = {}; + users.users.${config.services.nginx.user} = { + extraGroups = [ "${group}" ]; + }; + users.groups.${group} = {}; systemd.services.matomo-setup-update = { # everything needs to set up and up to date before Matomo php files are executed @@ -169,7 +173,7 @@ in { echo "Migrating from ${deprecatedDataDir} to ${dataDir}" mv -T ${deprecatedDataDir} ${dataDir} fi - chown -R ${user}:${user} ${dataDir} + chown -R ${user}:${group} ${dataDir} chmod -R ug+rwX,o-rwx ${dataDir} ''; script = '' @@ -225,22 +229,26 @@ in { serviceConfig.UMask = "0007"; }; - services.phpfpm.poolConfigs = let + services.phpfpm.pools = let # workaround for when both are null and need to generate a string, # which is illegal, but as assertions apparently are being triggered *after* config generation, # we have to avoid already throwing errors at this previous stage. socketOwner = if (cfg.nginx != null) then config.services.nginx.user else if (cfg.webServerUser != null) then cfg.webServerUser else ""; in { - ${pool} = '' - listen = "${phpSocket}" - listen.owner = ${socketOwner} - listen.group = root - listen.mode = 0600 - user = ${user} - env[PIWIK_USER_PATH] = ${dataDir} - ${cfg.phpfpmProcessManagerConfig} - ''; + ${pool} = { + socketName = "${pool}"; + phpPackage = pkgs.php; + user = "${user}"; + group = "${group}"; + extraConfig = '' + listen.owner = ${socketOwner} + listen.group = ${group} + listen.mode = 0600 + env[PIWIK_USER_PATH] = ${dataDir} + ${cfg.phpfpmProcessManagerConfig} + ''; + }; }; diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index fa9a36d1189..9475af12fdd 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -394,13 +394,14 @@ in { phpOptions))); in { phpOptions = phpOptionsExtensions; + socketName = "nextcloud"; phpPackage = phpPackage; - listen = "/run/phpfpm/nextcloud"; + user = "nextcloud"; + group = "${config.services.nginx.group}"; extraConfig = '' - listen.owner = nginx - listen.group = nginx - user = nextcloud - group = nginx + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} + listen.mode = 0600 ${cfg.poolConfig} env[NEXTCLOUD_CONFIG_DIR] = ${cfg.home}/config env[PATH] = /run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin @@ -466,7 +467,7 @@ in { fastcgi_param HTTPS ${if cfg.https then "on" else "off"}; fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; - fastcgi_pass unix:/run/phpfpm/nextcloud; + fastcgi_pass unix:/run/phpfpm-nextcloud/nextcloud.sock; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_read_timeout 120s; diff --git a/nixos/modules/services/web-apps/restya-board.nix b/nixos/modules/services/web-apps/restya-board.nix index 2e5e0ea6622..d4c99d6c44b 100644 --- a/nixos/modules/services/web-apps/restya-board.nix +++ b/nixos/modules/services/web-apps/restya-board.nix @@ -13,7 +13,7 @@ let runDir = "/run/restya-board"; poolName = "restya-board"; - phpfpmSocketName = "/run/phpfpm/${poolName}.sock"; + phpfpmSocketName = "/run/phpfpm-${poolName}/${poolName}.sock"; in @@ -178,9 +178,12 @@ in config = mkIf cfg.enable { - services.phpfpm.poolConfigs = { + services.phpfpm.pools = { "${poolName}" = { - listen = phpfpmSocketName; + socketName = "${poolName}"; + phpPackage = pkgs.php; + user = "${cfg.user}"; + group = "${cfg.group}"; phpOptions = '' date.timezone = "CET" @@ -192,11 +195,9 @@ in ''} ''; extraConfig = '' - listen.owner = nginx - listen.group = nginx + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} listen.mode = 0600 - user = ${cfg.user} - group = ${cfg.group} pm = dynamic pm.max_children = 75 pm.start_servers = 10 @@ -365,6 +366,9 @@ in home = runDir; group = "restya-board"; }; + users.users.nginx = { + extraGroups = [ "restya-board" ]; + }; users.groups.restya-board = {}; services.postgresql.enable = mkIf (cfg.database.host == null) true; diff --git a/nixos/modules/services/web-apps/selfoss.nix b/nixos/modules/services/web-apps/selfoss.nix index cd0f743a5fb..6c5942d1e17 100644 --- a/nixos/modules/services/web-apps/selfoss.nix +++ b/nixos/modules/services/web-apps/selfoss.nix @@ -3,9 +3,9 @@ with lib; let cfg = config.services.selfoss; - poolName = "selfoss_pool"; - phpfpmSocketName = "/run/phpfpm/${poolName}.sock"; - + poolName = "selfoss"; + phpfpmSocketName = "/run/phpfpm-${poolName}/${poolName}.sock"; + group = "${cfg.user}"; dataDir = "/var/lib/selfoss"; selfoss-config = @@ -116,21 +116,25 @@ in config = mkIf cfg.enable { - services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { - "${poolName}" = '' - listen = "${phpfpmSocketName}"; - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = nginx - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - catch_workers_output = 1 - ''; + services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { + "${poolName}" = { + socketName = "${poolName}"; + phpPackage = pkgs.php; + user = "${cfg.user}"; + group = "${group}"; + extraConfig = '' + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} + listen.mode = 0600 + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + catch_workers_output = 1 + ''; + }; }; systemd.services.selfoss-config = { @@ -145,7 +149,7 @@ in # Create the files cp -r "${pkgs.selfoss}/"* "${dataDir}" ln -sf "${selfoss-config}" "${dataDir}/config.ini" - chown -R "${cfg.user}" "${dataDir}" + chown -R "${cfg.user}":"${group}" "${dataDir}" chmod -R 755 "${dataDir}" ''; wantedBy = [ "multi-user.target" ]; @@ -162,5 +166,8 @@ in }; + users.users.nginx = { + extraGroups = [ "${group}" ]; + }; }; } diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index b882f6c2ae7..e59988ef7b2 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -512,12 +512,14 @@ let services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { "${poolName}" = { - listen = "/var/run/phpfpm/${poolName}.sock"; + socketName = "${poolName}"; + phpPackage = pkgs.php; + user = "${config.services.nginx.user}"; + group = "${config.services.nginx.group}"; extraConfig = '' - listen.owner = nginx - listen.group = nginx + listen.owner = ${config.services.nginx.user} + listen.group = ${config.services.nginx.group} listen.mode = 0600 - user = ${cfg.user} pm = dynamic pm.max_children = 75 pm.start_servers = 10 @@ -543,7 +545,7 @@ let locations."~ \.php$" = { extraConfig = '' fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.listen}; + fastcgi_pass unix:/run/phpfpm-${poolName}/${poolName}.sock; fastcgi_index index.php; ''; }; diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix index 4ec4a5a3359..9f25dc34f3f 100644 --- a/nixos/modules/services/web-servers/lighttpd/cgit.nix +++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix @@ -42,10 +42,10 @@ in configText = mkOption { default = ""; example = '' - cache-size=1000 - scan-path=/srv/git source-filter=''${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py about-filter=''${pkgs.cgit}/lib/cgit/filters/about-formatting.sh + cache-size=1000 + scan-path=/srv/git ''; type = types.lines; description = '' diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index ffafbc5e92f..5c650210f9f 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -4,37 +4,26 @@ with lib; let cfg = config.services.phpfpm; - enabled = cfg.poolConfigs != {} || cfg.pools != {}; + enabled = cfg.pools != {}; - stateDir = "/run/phpfpm"; - - poolConfigs = - (mapAttrs mapPoolConfig cfg.poolConfigs) // - (mapAttrs mapPool cfg.pools); - - mapPoolConfig = n: p: { - phpPackage = cfg.phpPackage; - phpOptions = cfg.phpOptions; - config = p; - }; + poolConfigs = (mapAttrs mapPool cfg.pools); mapPool = n: p: { phpPackage = p.phpPackage; phpOptions = p.phpOptions; - config = '' - listen = ${p.listen} - ${p.extraConfig} - ''; + userPool = p.user; + groupPool = p.group; }; fpmCfgFile = pool: conf: pkgs.writeText "phpfpm-${pool}.conf" '' [global] error_log = syslog daemonize = no - ${cfg.extraConfig} + ${cfg.globalExtraConfig} [${pool}] - ${conf} + listen = /run/phpfpm-${pool}/${cfg.pools.${pool}.socketName}.sock + ${cfg.pools.${pool}.extraConfig} ''; phpIni = pool: pkgs.runCommand "php.ini" { @@ -49,87 +38,99 @@ let ''; in { - options = { services.phpfpm = { - extraConfig = mkOption { + globalExtraConfig = mkOption { type = types.lines; default = ""; description = '' - Extra configuration that should be put in the global section of + Global extra configuration that should be put in the global section of the PHP-FPM configuration file. Do not specify the options <literal>error_log</literal> or - <literal>daemonize</literal> here, since they are generated by - NixOS. - ''; - }; - - phpPackage = mkOption { - type = types.package; - default = pkgs.php; - defaultText = "pkgs.php"; - description = '' - The PHP package to use for running the PHP-FPM service. + <literal>daemonize</literal> here, since they are generated by NixOS. ''; }; - phpOptions = mkOption { - type = types.lines; - default = ""; - example = - '' - date.timezone = "CET" - ''; - description = - "Options appended to the PHP configuration file <filename>php.ini</filename>."; - }; - - poolConfigs = mkOption { + pools = mkOption { default = {}; - type = types.attrsOf types.lines; + type = types.attrsOf (types.submodule { + options = { + socketName = mkOption { + type = types.str; + example = "php-fpm"; + description = '' + The address on which to accept FastCGI requests. + ''; + }; + + phpPackage = mkOption { + type = types.package; + default = pkgs.php; + defaultText = "pkgs.php"; + description = '' + The PHP package to use for running this PHP-FPM pool. + ''; + }; + + phpOptions = mkOption { + type = types.lines; + default = ""; + description = '' + Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool. + ''; + }; + + user = mkOption { + type = types.string; + default = "phpfpm"; + description = "User account under which phpfpm runs."; + }; + + group = mkOption { + type = types.string; + default = "phpfpm"; + description = "Group account under which phpfpm runs."; + }; + + extraConfig = mkOption { + type = types.lines; + example = '' + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + ''; + + description = '' + Extra lines that go into the pool configuration. + See the documentation on <literal>php-fpm.conf</literal> for + details on configuration directives. + ''; + }; + }; + }); + example = literalExample '' - { mypool = ''' - listen = /run/phpfpm/mypool - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - '''; + { + mypool = { + socketName = "example"; + phpPackage = pkgs.php; + user = "phpfpm"; + group = "phpfpm"; + extraConfig = ''' + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + '''; + } } ''; description = '' - A mapping between PHP-FPM pool names and their configurations. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. If no pools are defined, - the phpfpm service is disabled. - ''; - }; - - pools = mkOption { - type = types.attrsOf (types.submodule (import ./pool-options.nix { - inherit lib config; - })); - default = {}; - example = literalExample '' - { - mypool = { - listen = "/path/to/unix/socket"; - phpPackage = pkgs.php; - extraConfig = ''' - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - '''; - } - }''; - description = '' PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM service is disabled. ''; @@ -154,9 +155,6 @@ in { after = [ "network.target" ]; wantedBy = [ "phpfpm.target" ]; partOf = [ "phpfpm.target" ]; - preStart = '' - mkdir -p ${stateDir} - ''; serviceConfig = let cfgFile = fpmCfgFile pool poolConfig.config; iniFile = phpIni poolConfig; @@ -166,10 +164,19 @@ in { ProtectSystem = "full"; ProtectHome = true; # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work - RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK" ]; Type = "notify"; - ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${iniFile}"; + ExecStart = "${poolConfig.phpPackage}/bin/php-fpm -y '${cfgFile}' -c '${iniFile}'"; ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + # User and group + User = "${poolConfig.userPool}"; + Group = "${poolConfig.groupPool}"; + # Runtime directory and mode + RuntimeDirectory = "phpfpm-${pool}"; + RuntimeDirectoryMode = "0750"; + # Capabilities + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SETGID" "CAP_SETUID" "CAP_CHOWN" "CAP_SYS_RESOURCE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SETGID" "CAP_SETUID" "CAP_CHOWN" "CAP_SYS_RESOURCE" ]; }; } ); diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix deleted file mode 100644 index d9ad7eff71f..00000000000 --- a/nixos/modules/services/web-servers/phpfpm/pool-options.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ lib, config }: - -let - fpmCfg = config.services.phpfpm; -in - -with lib; { - - options = { - - listen = mkOption { - type = types.str; - example = "/path/to/unix/socket"; - description = '' - The address on which to accept FastCGI requests. - ''; - }; - - phpPackage = mkOption { - type = types.package; - default = fpmCfg.phpPackage; - defaultText = "config.services.phpfpm.phpPackage"; - description = '' - The PHP package to use for running this PHP-FPM pool. - ''; - }; - - phpOptions = mkOption { - type = types.lines; - default = fpmCfg.phpOptions; - defaultText = "config.services.phpfpm.phpOptions"; - description = '' - "Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool." - ''; - }; - - extraConfig = mkOption { - type = types.lines; - example = '' - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - ''; - - description = '' - Extra lines that go into the pool configuration. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. - ''; - }; - }; -} - diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index f4d7af1664a..394b4ce5656 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -23,14 +23,16 @@ let ''} ${cfg.qemuVerbatimConfig} ''; + dirName = "libvirt"; + subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list; in { ###### interface - options = { + options.virtualisation.libvirtd = { - virtualisation.libvirtd.enable = mkOption { + enable = mkOption { type = types.bool; default = false; description = '' @@ -41,7 +43,7 @@ in { ''; }; - virtualisation.libvirtd.qemuPackage = mkOption { + qemuPackage = mkOption { type = types.package; default = pkgs.qemu; description = '' @@ -51,7 +53,7 @@ in { ''; }; - virtualisation.libvirtd.extraConfig = mkOption { + extraConfig = mkOption { type = types.lines; default = ""; description = '' @@ -60,7 +62,7 @@ in { ''; }; - virtualisation.libvirtd.qemuRunAsRoot = mkOption { + qemuRunAsRoot = mkOption { type = types.bool; default = true; description = '' @@ -72,7 +74,7 @@ in { ''; }; - virtualisation.libvirtd.qemuVerbatimConfig = mkOption { + qemuVerbatimConfig = mkOption { type = types.lines; default = '' namespaces = [] @@ -84,7 +86,7 @@ in { ''; }; - virtualisation.libvirtd.qemuOvmf = mkOption { + qemuOvmf = mkOption { type = types.bool; default = true; description = '' @@ -93,7 +95,7 @@ in { ''; }; - virtualisation.libvirtd.extraOptions = mkOption { + extraOptions = mkOption { type = types.listOf types.str; default = [ ]; example = [ "--verbose" ]; @@ -102,7 +104,7 @@ in { ''; }; - virtualisation.libvirtd.onShutdown = mkOption { + onShutdown = mkOption { type = types.enum ["shutdown" "suspend" ]; default = "suspend"; description = '' @@ -113,6 +115,14 @@ in { ''; }; + allowedBridges = mkOption { + type = types.listOf types.str; + default = [ "virbr0" ]; + description = '' + List of bridge devices that can be used by qemu:///session + ''; + }; + }; @@ -120,7 +130,12 @@ in { config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ libvirt libressl.nc cfg.qemuPackage ]; + environment = { + # this file is expected in /etc/qemu and not sysconfdir (/var/lib) + etc."qemu/bridge.conf".text = lib.concatMapStringsSep "\n" (e: + "allow ${e}") cfg.allowedBridges; + systemPackages = with pkgs; [ libvirt libressl.nc cfg.qemuPackage ]; + }; boot.kernelModules = [ "tun" ]; @@ -134,30 +149,15 @@ in { group = "qemu-libvirtd"; }; - systemd.packages = [ pkgs.libvirt ]; - - systemd.services.libvirtd = { - description = "Libvirt Virtual Machine Management Daemon"; - - wantedBy = [ "multi-user.target" ]; - after = [ "systemd-udev-settle.service" ] - ++ optional vswitch.enable "vswitchd.service"; - - environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}''; - - path = [ cfg.qemuPackage ] # libvirtd requires qemu-img to manage disk images - ++ optional vswitch.enable vswitch.package; - - preStart = '' - mkdir -p /var/log/libvirt/qemu -m 755 - rm -f /var/run/libvirtd.pid - - mkdir -p /var/lib/libvirt - mkdir -p /var/lib/libvirt/dnsmasq + security.wrappers.qemu-bridge-helper = { + source = "/run/${dirName}/nix-helpers/qemu-bridge-helper"; + }; - chmod 755 /var/lib/libvirt - chmod 755 /var/lib/libvirt/dnsmasq + systemd.packages = [ pkgs.libvirt ]; + systemd.services.libvirtd-config = { + description = "Libvirt Virtual Machine Management Daemon - configuration"; + script = '' # Copy default libvirt network config .xml files to /var/lib # Files modified by the user will not be overwritten for i in $(cd ${pkgs.libvirt}/var/lib && echo \ @@ -169,22 +169,46 @@ in { done # Copy generated qemu config to libvirt directory - cp -f ${qemuConfigFile} /var/lib/libvirt/qemu.conf + cp -f ${qemuConfigFile} /var/lib/${dirName}/qemu.conf # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs - mkdir -p /run/libvirt/nix-emulators for emulator in ${pkgs.libvirt}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do - ln -s --force "$emulator" /run/libvirt/nix-emulators/ + ln -s --force "$emulator" /run/${dirName}/nix-emulators/ + done + + for helper in libexec/qemu-bridge-helper bin/qemu-pr-helper; do + ln -s --force ${cfg.qemuPackage}/$helper /run/${dirName}/nix-helpers/ done ${optionalString cfg.qemuOvmf '' - mkdir -p /run/libvirt/nix-ovmf - ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/libvirt/nix-ovmf/ - ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/libvirt/nix-ovmf/ + ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/${dirName}/nix-ovmf/ + ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/${dirName}/nix-ovmf/ ''} ''; serviceConfig = { + Type = "oneshot"; + RuntimeDirectoryPreserve = "yes"; + LogsDirectory = subDirs [ "qemu" ]; + RuntimeDirectory = subDirs [ "nix-emulators" "nix-helpers" "nix-ovmf" ]; + StateDirectory = subDirs [ "dnsmasq" ]; + }; + }; + + systemd.services.libvirtd = { + description = "Libvirt Virtual Machine Management Daemon"; + + wantedBy = [ "multi-user.target" ]; + requires = [ "libvirtd-config.service" ]; + after = [ "systemd-udev-settle.service" "libvirtd-config.service" ] + ++ optional vswitch.enable "vswitchd.service"; + + environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}''; + + path = [ cfg.qemuPackage ] # libvirtd requires qemu-img to manage disk images + ++ optional vswitch.enable vswitch.package; + + serviceConfig = { Type = "notify"; KillMode = "process"; # when stopping, leave the VMs alone Restart = "no"; @@ -203,7 +227,7 @@ in { systemd.sockets.virtlogd = { description = "Virtual machine log manager socket"; wantedBy = [ "sockets.target" ]; - listenStreams = [ "/run/libvirt/virtlogd-sock" ]; + listenStreams = [ "/run/${dirName}/virtlogd-sock" ]; }; systemd.services.virtlogd = { @@ -215,7 +239,7 @@ in { systemd.sockets.virtlockd = { description = "Virtual machine lock manager socket"; wantedBy = [ "sockets.target" ]; - listenStreams = [ "/run/libvirt/virtlockd-sock" ]; + listenStreams = [ "/run/${dirName}/virtlockd-sock" ]; }; systemd.services.virtlockd = { diff --git a/nixos/tests/mysql.nix b/nixos/tests/mysql.nix index cfe10bc41b0..f712357b9ff 100644 --- a/nixos/tests/mysql.nix +++ b/nixos/tests/mysql.nix @@ -28,6 +28,12 @@ import ./make-test.nix ({ pkgs, ...} : { { users.users.testuser = { }; services.mysql.enable = true; + services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" '' + echo "ALTER USER root@localhost IDENTIFIED WITH unix_socket;" + echo "DELETE FROM mysql.user WHERE password = ''' AND plugin = ''';" + echo "DELETE FROM mysql.user WHERE user = ''';" + echo "FLUSH PRIVILEGES;" + ''; services.mysql.ensureDatabases = [ "testdb" ]; services.mysql.ensureUsers = [{ name = "testuser"; |