diff options
Diffstat (limited to 'nixos/modules')
23 files changed, 530 insertions, 100 deletions
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index 9d49d4055e4..ea9667995e1 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -125,7 +125,7 @@ fi # Resolve the flake. if [[ -n $flake ]]; then - flake=$(nix "${flakeFlags[@]}" flake info --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url) + flake=$(nix "${flakeFlags[@]}" flake metadata --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url) fi if [[ ! -e $NIXOS_CONFIG && -z $system && -z $flake ]]; then diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 11c18a9df4b..3720b24f395 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -133,6 +133,7 @@ ./programs/file-roller.nix ./programs/firejail.nix ./programs/fish.nix + ./programs/flexoptix-app.nix ./programs/freetds.nix ./programs/fuse.nix ./programs/geary.nix @@ -529,6 +530,7 @@ ./services/misc/parsoid.nix ./services/misc/plex.nix ./services/misc/plikd.nix + ./services/misc/podgrab.nix ./services/misc/tautulli.nix ./services/misc/pinnwand.nix ./services/misc/pykms.nix @@ -700,6 +702,9 @@ ./services/networking/iodine.nix ./services/networking/iperf3.nix ./services/networking/ircd-hybrid/default.nix + ./services/networking/iscsi/initiator.nix + ./services/networking/iscsi/root-initiator.nix + ./services/networking/iscsi/target.nix ./services/networking/iwd.nix ./services/networking/jicofo.nix ./services/networking/jitsi-videobridge.nix diff --git a/nixos/modules/programs/flexoptix-app.nix b/nixos/modules/programs/flexoptix-app.nix new file mode 100644 index 00000000000..93dcdfeb514 --- /dev/null +++ b/nixos/modules/programs/flexoptix-app.nix @@ -0,0 +1,25 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.flexoptix-app; +in { + options = { + programs.flexoptix-app = { + enable = mkEnableOption "FLEXOPTIX app + udev rules"; + + package = mkOption { + description = "FLEXOPTIX app package to use"; + type = types.package; + default = pkgs.flexoptix-app; + defaultText = "\${pkgs.flexoptix-app}"; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + services.udev.packages = [ cfg.package ]; + }; +} diff --git a/nixos/modules/services/hardware/pcscd.nix b/nixos/modules/services/hardware/pcscd.nix index f3fc4c3cc79..54b6693f85a 100644 --- a/nixos/modules/services/hardware/pcscd.nix +++ b/nixos/modules/services/hardware/pcscd.nix @@ -10,39 +10,37 @@ let paths = map (p: "${p}/pcsc/drivers") config.services.pcscd.plugins; }; -in { +in +{ ###### interface - options = { + options.services.pcscd = { + enable = mkEnableOption "PCSC-Lite daemon"; - services.pcscd = { - enable = mkEnableOption "PCSC-Lite daemon"; - - plugins = mkOption { - type = types.listOf types.package; - default = [ pkgs.ccid ]; - defaultText = "[ pkgs.ccid ]"; - example = literalExample "[ pkgs.pcsc-cyberjack ]"; - description = "Plugin packages to be used for PCSC-Lite."; - }; - - readerConfig = mkOption { - type = types.lines; - default = ""; - example = '' - FRIENDLYNAME "Some serial reader" - DEVICENAME /dev/ttyS0 - LIBPATH /path/to/serial_reader.so - CHANNELID 1 - ''; - description = '' - Configuration for devices that aren't hotpluggable. + plugins = mkOption { + type = types.listOf types.package; + default = [ pkgs.ccid ]; + defaultText = "[ pkgs.ccid ]"; + example = literalExample "[ pkgs.pcsc-cyberjack ]"; + description = "Plugin packages to be used for PCSC-Lite."; + }; - See <citerefentry><refentrytitle>reader.conf</refentrytitle> - <manvolnum>5</manvolnum></citerefentry> for valid options. - ''; - }; + readerConfig = mkOption { + type = types.lines; + default = ""; + example = '' + FRIENDLYNAME "Some serial reader" + DEVICENAME /dev/ttyS0 + LIBPATH /path/to/serial_reader.so + CHANNELID 1 + ''; + description = '' + Configuration for devices that aren't hotpluggable. + + See <citerefentry><refentrytitle>reader.conf</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for valid options. + ''; }; }; @@ -50,20 +48,15 @@ in { config = mkIf config.services.pcscd.enable { - systemd.sockets.pcscd = { - description = "PCSC-Lite Socket"; - wantedBy = [ "sockets.target" ]; - before = [ "multi-user.target" ]; - socketConfig.ListenStream = "/run/pcscd/pcscd.comm"; - }; + environment.etc."reader.conf".source = cfgFile; + + systemd.packages = [ (getBin pkgs.pcsclite) ]; + + systemd.sockets.pcscd.wantedBy = [ "sockets.target" ]; systemd.services.pcscd = { - description = "PCSC-Lite daemon"; environment.PCSCLITE_HP_DROPDIR = pluginEnv; - serviceConfig = { - ExecStart = "${getBin pkgs.pcsclite}/sbin/pcscd -f -x -c ${cfgFile}"; - ExecReload = "${getBin pkgs.pcsclite}/sbin/pcscd -H"; - }; + restartTriggers = [ "/etc/reader.conf" ]; }; }; } diff --git a/nixos/modules/services/mail/exim.nix b/nixos/modules/services/mail/exim.nix index 892fbd33214..8927d84b478 100644 --- a/nixos/modules/services/mail/exim.nix +++ b/nixos/modules/services/mail/exim.nix @@ -67,6 +67,13 @@ in ''; }; + queueRunnerInterval = mkOption { + type = types.str; + default = "5m"; + description = '' + How often to spawn a new queue runner. + ''; + }; }; }; @@ -104,7 +111,7 @@ in wantedBy = [ "multi-user.target" ]; restartTriggers = [ config.environment.etc."exim.conf".source ]; serviceConfig = { - ExecStart = "${cfg.package}/bin/exim -bdf -q30m"; + ExecStart = "${cfg.package}/bin/exim -bdf -q${cfg.queueRunnerInterval}"; ExecReload = "${coreutils}/bin/kill -HUP $MAINPID"; }; preStart = '' diff --git a/nixos/modules/services/mail/spamassassin.nix b/nixos/modules/services/mail/spamassassin.nix index 4e642542ec6..ac878222b26 100644 --- a/nixos/modules/services/mail/spamassassin.nix +++ b/nixos/modules/services/mail/spamassassin.nix @@ -126,19 +126,36 @@ in }; systemd.services.sa-update = { + # Needs to be able to contact the update server. + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + serviceConfig = { + Type = "oneshot"; + User = "spamd"; + Group = "spamd"; + StateDirectory = "spamassassin"; + ExecStartPost = "+${pkgs.systemd}/bin/systemctl -q --no-block try-reload-or-restart spamd.service"; + }; + script = '' set +e - ${pkgs.su}/bin/su -s "${pkgs.bash}/bin/bash" -c "${pkgs.spamassassin}/bin/sa-update --gpghomedir=/var/lib/spamassassin/sa-update-keys/" spamd - - v=$? + ${pkgs.spamassassin}/bin/sa-update --verbose --gpghomedir=/var/lib/spamassassin/sa-update-keys/ + rc=$? set -e - if [ $v -gt 1 ]; then - echo "sa-update execution error" - exit $v + + if [[ $rc -gt 1 ]]; then + # sa-update failed. + exit $rc fi - if [ $v -eq 0 ]; then - systemctl reload spamd.service + + if [[ $rc -eq 1 ]]; then + # No update was available, exit successfully. + exit 0 fi + + # An update was available and installed. Compile the rules. + ${pkgs.spamassassin}/bin/sa-compile ''; }; @@ -153,32 +170,22 @@ in }; systemd.services.spamd = { - description = "Spam Assassin Server"; + description = "SpamAssassin Server"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; + wants = [ "sa-update.service" ]; + after = [ + "network.target" + "sa-update.service" + ]; serviceConfig = { - ExecStart = "${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --virtual-config-dir=/var/lib/spamassassin/user-%u --allow-tell --pidfile=/run/spamd.pid"; - ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + User = "spamd"; + Group = "spamd"; + ExecStart = "+${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --virtual-config-dir=%S/spamassassin/user-%u --allow-tell --pidfile=/run/spamd.pid"; + ExecReload = "+${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + StateDirectory = "spamassassin"; }; - - # 0 and 1 no error, exitcode > 1 means error: - # https://spamassassin.apache.org/full/3.1.x/doc/sa-update.html#exit_codes - preStart = '' - echo "Recreating '/var/lib/spamasassin' with creating '3.004001' (or similar) and 'sa-update-keys'" - mkdir -p /var/lib/spamassassin - chown spamd:spamd /var/lib/spamassassin -R - set +e - ${pkgs.su}/bin/su -s "${pkgs.bash}/bin/bash" -c "${pkgs.spamassassin}/bin/sa-update --gpghomedir=/var/lib/spamassassin/sa-update-keys/" spamd - v=$? - set -e - if [ $v -gt 1 ]; then - echo "sa-update execution error" - exit $v - fi - chown spamd:spamd /var/lib/spamassassin -R - ''; }; }; } diff --git a/nixos/modules/services/misc/podgrab.nix b/nixos/modules/services/misc/podgrab.nix new file mode 100644 index 00000000000..7077408b794 --- /dev/null +++ b/nixos/modules/services/misc/podgrab.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.services.podgrab; +in +{ + options.services.podgrab = with lib; { + enable = mkEnableOption "Podgrab, a self-hosted podcast manager"; + + passwordFile = mkOption { + type = with types; nullOr str; + default = null; + example = "/run/secrets/password.env"; + description = '' + The path to a file containing the PASSWORD environment variable + definition for Podgrab's authentification. + ''; + }; + + port = mkOption { + type = types.port; + default = 8080; + example = 4242; + description = "The port on which Podgrab will listen for incoming HTTP traffic."; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.podgrab = { + description = "Podgrab podcast manager"; + wantedBy = [ "multi-user.target" ]; + environment = { + CONFIG = "/var/lib/podgrab/config"; + DATA = "/var/lib/podgrab/data"; + GIN_MODE = "release"; + PORT = toString cfg.port; + }; + serviceConfig = { + DynamicUser = true; + EnvironmentFile = lib.optional (cfg.passwordFile != null) [ + cfg.passwordFile + ]; + ExecStart = "${pkgs.podgrab}/bin/podgrab"; + WorkingDirectory = "${pkgs.podgrab}/share"; + StateDirectory = [ "podgrab/config" "podgrab/data" ]; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ ambroisie ]; +} diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix index 9ac6869068f..61214508a9c 100644 --- a/nixos/modules/services/monitoring/nagios.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -192,6 +192,7 @@ in path = [ pkgs.nagios ] ++ cfg.plugins; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + restartTriggers = [ nagiosCfgFile ]; serviceConfig = { User = "nagios"; @@ -201,7 +202,6 @@ in LogsDirectory = "nagios"; StateDirectory = "nagios"; ExecStart = "${pkgs.nagios}/bin/nagios /etc/nagios.cfg"; - X-ReloadIfChanged = nagiosCfgFile; }; }; diff --git a/nixos/modules/services/networking/babeld.nix b/nixos/modules/services/networking/babeld.nix index e16e56121c4..97dca002a00 100644 --- a/nixos/modules/services/networking/babeld.nix +++ b/nixos/modules/services/networking/babeld.nix @@ -19,7 +19,10 @@ let "interface ${name} ${paramsString interface}\n"; configFile = with cfg; pkgs.writeText "babeld.conf" ( - (optionalString (cfg.interfaceDefaults != null) '' + '' + skip-kernel-setup true + '' + + (optionalString (cfg.interfaceDefaults != null) '' default ${paramsString cfg.interfaceDefaults} '') + (concatMapStrings interfaceConfig (attrNames cfg.interfaces)) @@ -84,13 +87,22 @@ in config = mkIf config.services.babeld.enable { + boot.kernel.sysctl = { + "net.ipv6.conf.all.forwarding" = 1; + "net.ipv6.conf.all.accept_redirects" = 0; + "net.ipv4.conf.all.forwarding" = 1; + "net.ipv4.conf.all.rp_filter" = 0; + } // lib.mapAttrs' (ifname: _: lib.nameValuePair "net.ipv4.conf.${ifname}.rp_filter" (lib.mkDefault 0)) config.services.babeld.interfaces; + systemd.services.babeld = { description = "Babel routing daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile} -I /run/babeld/babeld.pid -S /var/lib/babeld/state"; + AmbientCapabilities = [ "CAP_NET_ADMIN" ]; CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; + DynamicUser = true; IPAddressAllow = [ "fe80::/64" "ff00::/8" "::1/128" "127.0.0.0/8" ]; IPAddressDeny = "any"; LockPersonality = true; @@ -98,7 +110,7 @@ in MemoryDenyWriteExecute = true; ProtectSystem = "strict"; ProtectClock = true; - ProtectKernelTunables = false; # Couldn't write sysctl: Read-only file system + ProtectKernelTunables = true; ProtectKernelModules = true; ProtectKernelLogs = true; ProtectControlGroups = true; diff --git a/nixos/modules/services/networking/iscsi/initiator.nix b/nixos/modules/services/networking/iscsi/initiator.nix new file mode 100644 index 00000000000..cbc919a2f76 --- /dev/null +++ b/nixos/modules/services/networking/iscsi/initiator.nix @@ -0,0 +1,84 @@ +{ config, lib, pkgs, ... }: with lib; +let + cfg = config.services.openiscsi; +in +{ + options.services.openiscsi = with types; { + enable = mkEnableOption "the openiscsi iscsi daemon"; + enableAutoLoginOut = mkEnableOption '' + automatic login and logout of all automatic targets. + You probably do not want this. + ''; + discoverPortal = mkOption { + type = nullOr str; + default = null; + description = "Portal to discover targets on"; + }; + name = mkOption { + type = str; + description = "Name of this iscsi initiator"; + example = "iqn.2020-08.org.linux-iscsi.initiatorhost:example"; + }; + package = mkOption { + type = package; + description = "openiscsi package to use"; + default = pkgs.openiscsi; + defaultText = "pkgs.openiscsi"; + }; + + extraConfig = mkOption { + type = str; + default = ""; + description = "Lines to append to default iscsid.conf"; + }; + + extraConfigFile = mkOption { + description = '' + Append an additional file's contents to /etc/iscsid.conf. Use a non-store path + and store passwords in this file. + ''; + default = null; + type = nullOr str; + }; + }; + + config = mkIf cfg.enable { + environment.etc."iscsi/iscsid.conf.fragment".source = pkgs.runCommand "iscsid.conf" {} '' + cat "${cfg.package}/etc/iscsi/iscsid.conf" > $out + cat << 'EOF' >> $out + ${cfg.extraConfig} + ${optionalString cfg.enableAutoLoginOut "node.startup = automatic"} + EOF + ''; + environment.etc."iscsi/initiatorname.iscsi".text = "InitiatorName=${cfg.name}"; + + system.activationScripts.iscsid = let + extraCfgDumper = optionalString (cfg.extraConfigFile != null) '' + if [ -f "${cfg.extraConfigFile}" ]; then + printf "\n# The following is from ${cfg.extraConfigFile}:\n" + cat "${cfg.extraConfigFile}" + else + echo "Warning: services.openiscsi.extraConfigFile ${cfg.extraConfigFile} does not exist!" >&2 + fi + ''; + in '' + ( + cat ${config.environment.etc."iscsi/iscsid.conf.fragment".source} + ${extraCfgDumper} + ) > /etc/iscsi/iscsid.conf + ''; + + systemd.packages = [ cfg.package ]; + + systemd.services."iscsid".wantedBy = [ "multi-user.target" ]; + systemd.sockets."iscsid".wantedBy = [ "sockets.target" ]; + + systemd.services."iscsi" = mkIf cfg.enableAutoLoginOut { + wantedBy = [ "remote-fs.target" ]; + serviceConfig.ExecStartPre = mkIf (cfg.discoverPortal != null) "${cfg.package}/bin/iscsiadm --mode discoverydb --type sendtargets --portal ${escapeShellArg cfg.discoverPortal} --discover"; + }; + + environment.systemPackages = [ cfg.package ]; + boot.kernelModules = [ "iscsi_tcp" ]; + }; +} diff --git a/nixos/modules/services/networking/iscsi/root-initiator.nix b/nixos/modules/services/networking/iscsi/root-initiator.nix new file mode 100644 index 00000000000..3274878c4fa --- /dev/null +++ b/nixos/modules/services/networking/iscsi/root-initiator.nix @@ -0,0 +1,181 @@ +{ config, lib, pkgs, ... }: with lib; +let + cfg = config.boot.iscsi-initiator; +in +{ + # If you're booting entirely off another machine you may want to add + # this snippet to always boot the latest "system" version. It is not + # enabled by default in case you have an initrd on a local disk: + # + # boot.initrd.postMountCommands = '' + # ln -sfn /nix/var/nix/profiles/system/init /mnt-root/init + # stage2Init=/init + # ''; + # + # Note: Theoretically you might want to connect to multiple portals and + # log in to multiple targets, however the authors of this module so far + # don't have the need or expertise to reasonably implement it. Also, + # consider carefully before making your boot chain depend on multiple + # machines to be up. + options.boot.iscsi-initiator = with types; { + name = mkOption { + description = '' + Name of the iSCSI initiator to boot from. Note, booting from iscsi + requires networkd based networking. + ''; + default = null; + example = "iqn.2020-08.org.linux-iscsi.initiatorhost:example"; + type = nullOr str; + }; + + discoverPortal = mkOption { + description = '' + iSCSI portal to boot from. + ''; + default = null; + example = "192.168.1.1:3260"; + type = nullOr str; + }; + + target = mkOption { + description = '' + Name of the iSCSI target to boot from. + ''; + default = null; + example = "iqn.2020-08.org.linux-iscsi.targethost:example"; + type = nullOr str; + }; + + logLevel = mkOption { + description = '' + Higher numbers elicits more logs. + ''; + default = 1; + example = 8; + type = int; + }; + + loginAll = mkOption { + description = '' + Do not log into a specific target on the portal, but to all that we discover. + This overrides setting target. + ''; + type = bool; + default = false; + }; + + extraConfig = mkOption { + description = "Extra lines to append to /etc/iscsid.conf"; + default = null; + type = nullOr lines; + }; + + extraConfigFile = mkOption { + description = '' + Append an additional file's contents to `/etc/iscsid.conf`. Use a non-store path + and store passwords in this file. Note: the file specified here must be available + in the initrd, see: `boot.initrd.secrets`. + ''; + default = null; + type = nullOr str; + }; + }; + + config = mkIf (cfg.name != null) { + # The "scripted" networking configuration (ie: non-networkd) + # doesn't properly order the start and stop of the interfaces, and the + # network interfaces are torn down before unmounting disks. Since this + # module is specifically for very-early-boot network mounts, we need + # the network to stay on. + # + # We could probably fix the scripted options to properly order, but I'm + # not inclined to invest that time today. Hopefully this gets users far + # enough along and they can just use networkd. + networking.useNetworkd = true; + networking.useDHCP = false; # Required to set useNetworkd = true + + boot.initrd = { + network.enable = true; + + # By default, the stage-1 disables the network and resets the interfaces + # on startup. Since our startup disks are on the network, we can't let + # the network not work. + network.flushBeforeStage2 = false; + + kernelModules = [ "iscsi_tcp" ]; + + extraUtilsCommands = '' + copy_bin_and_libs ${pkgs.openiscsi}/bin/iscsid + copy_bin_and_libs ${pkgs.openiscsi}/bin/iscsiadm + ${optionalString (!config.boot.initrd.network.ssh.enable) "cp -pv ${pkgs.glibc.out}/lib/libnss_files.so.* $out/lib"} + + mkdir -p $out/etc/iscsi + cp ${config.environment.etc.hosts.source} $out/etc/hosts + cp ${pkgs.openiscsi}/etc/iscsi/iscsid.conf $out/etc/iscsi/iscsid.fragment.conf + chmod +w $out/etc/iscsi/iscsid.fragment.conf + cat << 'EOF' >> $out/etc/iscsi/iscsid.fragment.conf + ${optionalString (cfg.extraConfig != null) cfg.extraConfig} + EOF + ''; + + extraUtilsCommandsTest = '' + $out/bin/iscsiadm --version + ''; + + preLVMCommands = let + extraCfgDumper = optionalString (cfg.extraConfigFile != null) '' + if [ -f "${cfg.extraConfigFile}" ]; then + printf "\n# The following is from ${cfg.extraConfigFile}:\n" + cat "${cfg.extraConfigFile}" + else + echo "Warning: boot.iscsi-initiator.extraConfigFile ${cfg.extraConfigFile} does not exist!" >&2 + fi + ''; + in '' + ${optionalString (!config.boot.initrd.network.ssh.enable) '' + # stolen from initrd-ssh.nix + echo 'root:x:0:0:root:/root:/bin/ash' > /etc/passwd + echo 'passwd: files' > /etc/nsswitch.conf + ''} + + cp -f $extraUtils/etc/hosts /etc/hosts + + mkdir -p /etc/iscsi /run/lock/iscsi + echo "InitiatorName=${cfg.name}" > /etc/iscsi/initiatorname.iscsi + + ( + cat "$extraUtils/etc/iscsi/iscsid.fragment.conf" + printf "\n" + ${optionalString cfg.loginAll ''echo "node.startup = automatic"''} + ${extraCfgDumper} + ) > /etc/iscsi/iscsid.conf + + iscsid --foreground --no-pid-file --debug ${toString cfg.logLevel} & + iscsiadm --mode discoverydb \ + --type sendtargets \ + --discover \ + --portal ${escapeShellArg cfg.discoverPortal} \ + --debug ${toString cfg.logLevel} + + ${if cfg.loginAll then '' + iscsiadm --mode node --loginall all + '' else '' + iscsiadm --mode node --targetname ${escapeShellArg cfg.target} --login + ''} + pkill -9 iscsid + ''; + }; + + services.openiscsi = { + enable = true; + inherit (cfg) name; + }; + + assertions = [ + { + assertion = cfg.loginAll -> cfg.target == null; + message = "iSCSI target name is set while login on all portals is enabled."; + } + ]; + }; +} diff --git a/nixos/modules/services/networking/iscsi/target.nix b/nixos/modules/services/networking/iscsi/target.nix new file mode 100644 index 00000000000..8a10e7d346a --- /dev/null +++ b/nixos/modules/services/networking/iscsi/target.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.target; +in +{ + ###### interface + options = { + services.target = with types; { + enable = mkEnableOption "the kernel's LIO iscsi target"; + + config = mkOption { + type = attrs; + default = {}; + description = '' + Content of /etc/target/saveconfig.json + This file is normally read and written by targetcli + ''; + }; + }; + }; + + ###### implementation + config = mkIf cfg.enable { + environment.etc."target/saveconfig.json" = { + text = builtins.toJSON cfg.config; + mode = "0600"; + }; + + environment.systemPackages = with pkgs; [ targetcli ]; + + boot.kernelModules = [ "configfs" "target_core_mod" "iscsi_target_mod" ]; + + systemd.services.iscsi-target = { + enable = true; + after = [ "network.target" "local-fs.target" ]; + requires = [ "sys-kernel-config.mount" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.python3.pkgs.rtslib}/bin/targetctl restore"; + ExecStop = "${pkgs.python3.pkgs.rtslib}/bin/targetctl clear"; + RemainAfterExit = "yes"; + }; + }; + + systemd.tmpfiles.rules = [ + "d /etc/target 0700 root root - -" + ]; + }; +} diff --git a/nixos/modules/services/web-apps/mastodon.nix b/nixos/modules/services/web-apps/mastodon.nix index 16e8ae2ec0b..661320b5d00 100644 --- a/nixos/modules/services/web-apps/mastodon.nix +++ b/nixos/modules/services/web-apps/mastodon.nix @@ -31,6 +31,8 @@ let // (if cfg.smtp.authenticate then { SMTP_LOGIN = cfg.smtp.user; } else {}) // cfg.extraConfig; + systemCallsList = [ "@clock" "@cpu-emulation" "@debug" "@keyring" "@module" "@mount" "@obsolete" "@raw-io" "@reboot" "@resources" "@setuid" "@swap" ]; + cfgService = { # User and group User = cfg.user; @@ -68,7 +70,6 @@ let PrivateMounts = true; # System Call Filtering SystemCallArchitectures = "native"; - SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap"; }; envFile = pkgs.writeText "mastodon.env" (lib.concatMapStrings (s: s + "\n") ( @@ -432,6 +433,8 @@ in { serviceConfig = { Type = "oneshot"; WorkingDirectory = cfg.package; + # System Call Filtering + SystemCallFilter = "~" + lib.concatStringsSep " " systemCallsList; } // cfgService; after = [ "network.target" ]; @@ -457,6 +460,8 @@ in { Type = "oneshot"; EnvironmentFile = "/var/lib/mastodon/.secrets_env"; WorkingDirectory = cfg.package; + # System Call Filtering + SystemCallFilter = "~" + lib.concatStringsSep " " systemCallsList; } // cfgService; after = [ "mastodon-init-dirs.service" "network.target" ] ++ (if databaseActuallyCreateLocally then [ "postgresql.service" ] else []); wantedBy = [ "multi-user.target" ]; @@ -481,6 +486,8 @@ in { # Runtime directory and mode RuntimeDirectory = "mastodon-streaming"; RuntimeDirectoryMode = "0750"; + # System Call Filtering + SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]); } // cfgService; }; @@ -503,6 +510,8 @@ in { # Runtime directory and mode RuntimeDirectory = "mastodon-web"; RuntimeDirectoryMode = "0750"; + # System Call Filtering + SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]); } // cfgService; path = with pkgs; [ file imagemagick ffmpeg ]; }; @@ -522,6 +531,8 @@ in { RestartSec = 20; EnvironmentFile = "/var/lib/mastodon/.secrets_env"; WorkingDirectory = cfg.package; + # System Call Filtering + SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]); } // cfgService; path = with pkgs; [ file imagemagick ffmpeg ]; }; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 51c2f3febdc..18e1263fef5 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -887,6 +887,7 @@ in users.users = optionalAttrs (cfg.user == "nginx") { nginx = { group = cfg.group; + isSystemUser = true; uid = config.ids.uids.nginx; }; }; diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index 2ea191426ce..63e01dd054a 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -236,9 +236,12 @@ def main() -> None: gens += get_generations(profile) remove_old_entries(gens) for gen in gens: - write_entry(*gen, machine_id) - if os.readlink(system_dir(*gen)) == args.default_config: - write_loader_conf(*gen) + try: + write_entry(*gen, machine_id) + if os.readlink(system_dir(*gen)) == args.default_config: + write_loader_conf(*gen) + except OSError as e: + print("ignoring profile '{}' in the list of boot entries because of the following error:\n{}".format(profile, e), file=sys.stderr) memtest_entry_file = "@efiSysMountPoint@/loader/entries/memtest86.conf" if os.path.exists(memtest_entry_file): diff --git a/nixos/modules/virtualisation/azure-image.nix b/nixos/modules/virtualisation/azure-image.nix index 60fed3222ef..03dd3c05130 100644 --- a/nixos/modules/virtualisation/azure-image.nix +++ b/nixos/modules/virtualisation/azure-image.nix @@ -9,8 +9,9 @@ in options = { virtualisation.azureImage.diskSize = mkOption { - type = with types; int; - default = 2048; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 2048; description = '' Size of disk image. Unit is MB. ''; diff --git a/nixos/modules/virtualisation/digital-ocean-image.nix b/nixos/modules/virtualisation/digital-ocean-image.nix index b582e235d43..0ff2ee591f2 100644 --- a/nixos/modules/virtualisation/digital-ocean-image.nix +++ b/nixos/modules/virtualisation/digital-ocean-image.nix @@ -10,8 +10,9 @@ in options = { virtualisation.digitalOceanImage.diskSize = mkOption { - type = with types; int; - default = 4096; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 4096; description = '' Size of disk image. Unit is MB. ''; diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index e2332df611a..79c3921669e 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -18,8 +18,9 @@ in options = { virtualisation.googleComputeImage.diskSize = mkOption { - type = with types; int; - default = 1536; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 1536; description = '' Size of disk image. Unit is MB. ''; diff --git a/nixos/modules/virtualisation/hyperv-image.nix b/nixos/modules/virtualisation/hyperv-image.nix index fabc9113dfc..6845d675009 100644 --- a/nixos/modules/virtualisation/hyperv-image.nix +++ b/nixos/modules/virtualisation/hyperv-image.nix @@ -9,8 +9,9 @@ in { options = { hyperv = { baseImageSize = mkOption { - type = types.int; - default = 2048; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 2048; description = '' The size of the hyper-v base image in MiB. ''; diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index f15d5875841..7a1f11ce40d 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -439,21 +439,16 @@ in default = false; description = '' Whether this NixOS machine is a lightweight container running - in another NixOS system. If set to true, support for nested - containers is disabled by default, but can be reenabled by - setting <option>boot.enableContainers</option> to true. + in another NixOS system. ''; }; boot.enableContainers = mkOption { type = types.bool; - default = !config.boot.isContainer; + default = true; description = '' Whether to enable support for NixOS containers. Defaults to true - (at no cost if containers are not actually used), but only if the - system is not itself a lightweight container of a host. - To enable support for nested containers, this option has to be - explicitly set to true (in the outer container). + (at no cost if containers are not actually used). ''; }; diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index fa580e8b42d..071edda8269 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -11,8 +11,9 @@ in { options = { virtualbox = { baseImageSize = mkOption { - type = types.int; - default = 50 * 1024; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 50 * 1024; description = '' The size of the VirtualBox base image in MiB. ''; diff --git a/nixos/modules/virtualisation/vmware-image.nix b/nixos/modules/virtualisation/vmware-image.nix index 9da9e145f7a..f6cd12e2bb7 100644 --- a/nixos/modules/virtualisation/vmware-image.nix +++ b/nixos/modules/virtualisation/vmware-image.nix @@ -18,8 +18,9 @@ in { options = { vmware = { baseImageSize = mkOption { - type = types.int; - default = 2048; + type = with types; either (enum [ "auto" ]) int; + default = "auto"; + example = 2048; description = '' The size of the VMWare base image in MiB. ''; diff --git a/nixos/modules/virtualisation/xen-dom0.nix b/nixos/modules/virtualisation/xen-dom0.nix index 24df1b6ad7c..fea43727f2f 100644 --- a/nixos/modules/virtualisation/xen-dom0.nix +++ b/nixos/modules/virtualisation/xen-dom0.nix @@ -161,9 +161,6 @@ in environment.systemPackages = [ cfg.package ]; - # Make sure Domain 0 gets the required configuration - #boot.kernelPackages = pkgs.boot.kernelPackages.override { features={xen_dom0=true;}; }; - boot.kernelModules = [ "xen-evtchn" "xen-gntdev" "xen-gntalloc" "xen-blkback" "xen-netback" "xen-pciback" "evtchn" "gntdev" "netbk" "blkbk" "xen-scsibk" |