diff options
Diffstat (limited to 'nixos/modules')
25 files changed, 514 insertions, 74 deletions
diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix index 212013b5e289..fe6cc4161630 100644 --- a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix +++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix @@ -31,11 +31,24 @@ in users.extraUsers.root.initialHashedPassword = ""; sdImage = { - populateBootCommands = '' - (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/) - cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi.bin - echo 'kernel u-boot-rpi.bin' > boot/config.txt - ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot - ''; + populateBootCommands = 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. + avoid_warnings=1 + + [pi0] + kernel=u-boot-rpi0.bin + + [pi1] + kernel=u-boot-rpi1.bin + ''; + in '' + (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/) + cp ${pkgs.ubootRaspberryPiZero}/u-boot.bin boot/u-boot-rpi0.bin + cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi1.bin + cp ${configTxt} boot/config.txt + ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot + ''; }; } diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 12d9e1adf23d..da4c21296ffd 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -514,6 +514,7 @@ ./services/networking/miniupnpd.nix ./services/networking/mosquitto.nix ./services/networking/monero.nix + ./services/networking/morty.nix ./services/networking/miredo.nix ./services/networking/mstpd.nix ./services/networking/murmur.nix @@ -787,6 +788,7 @@ ./virtualisation/lxd.nix ./virtualisation/amazon-options.nix ./virtualisation/hyperv-guest.nix + ./virtualisation/kvmgt.nix ./virtualisation/openvswitch.nix ./virtualisation/parallels-guest.nix ./virtualisation/qemu-guest-agent.nix diff --git a/nixos/modules/programs/mosh.nix b/nixos/modules/programs/mosh.nix index b3aa55e189a3..359fe23e0ecd 100644 --- a/nixos/modules/programs/mosh.nix +++ b/nixos/modules/programs/mosh.nix @@ -16,10 +16,28 @@ in default = false; type = lib.types.bool; }; + withUtempter = mkOption { + description = '' + Whether to enable libutempter for mosh. + This is required so that mosh can write to /var/run/utmp (which can be queried with `who` to display currently connected user sessions). + Note, this will add a guid wrapper for the group utmp! + ''; + default = true; + type = lib.types.bool; + }; }; config = mkIf cfg.enable { environment.systemPackages = with pkgs; [ mosh ]; networking.firewall.allowedUDPPortRanges = [ { from = 60000; to = 61000; } ]; + security.wrappers = mkIf cfg.withUtempter { + utempter = { + source = "${pkgs.libutempter}/lib/utempter/utempter"; + owner = "nobody"; + group = "utmp"; + setuid = false; + setgid = true; + }; + }; }; } diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index 5f379b392ea8..94020ed05d67 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -13,7 +13,9 @@ let mpdConf = pkgs.writeText "mpd.conf" '' music_directory "${cfg.musicDirectory}" playlist_directory "${cfg.playlistDirectory}" - db_file "${cfg.dbFile}" + ${lib.optionalString (cfg.dbFile != null) '' + db_file "${cfg.dbFile}" + ''} state_file "${cfg.dataDir}/state" sticker_file "${cfg.dataDir}/sticker.sql" log_file "syslog" @@ -126,11 +128,12 @@ in { }; dbFile = mkOption { - type = types.str; + type = types.nullOr types.str; default = "${cfg.dataDir}/tag_cache"; defaultText = ''''${dataDir}/tag_cache''; description = '' - The path to MPD's database. + The path to MPD's database. If set to <literal>null</literal> the + parameter is omitted from the configuration. ''; }; }; diff --git a/nixos/modules/services/backup/duplicati.nix b/nixos/modules/services/backup/duplicati.nix index 9772ca4d20a7..379fde1fe038 100644 --- a/nixos/modules/services/backup/duplicati.nix +++ b/nixos/modules/services/backup/duplicati.nix @@ -9,6 +9,23 @@ in options = { services.duplicati = { enable = mkEnableOption "Duplicati"; + + port = mkOption { + default = 8200; + type = types.int; + description = '' + Port serving the web interface + ''; + }; + + interface = mkOption { + default = "lo"; + type = types.str; + description = '' + Listening interface for the web UI + Set it to "any" to listen on all available interfaces + ''; + }; }; }; @@ -22,7 +39,7 @@ in serviceConfig = { User = "duplicati"; Group = "duplicati"; - ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=any --webservice-port=8200 --server-datafolder=/var/lib/duplicati"; + ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=/var/lib/duplicati"; Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix index 501925597023..e624f41601b3 100644 --- a/nixos/modules/services/cluster/kubernetes/default.nix +++ b/nixos/modules/services/cluster/kubernetes/default.nix @@ -78,7 +78,7 @@ let }; caFile = mkOption { - description = "${prefix} certificate authrority file used to connect to kube-apiserver."; + description = "${prefix} certificate authority file used to connect to kube-apiserver."; type = types.nullOr types.path; default = cfg.caFile; }; diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix index 3e513ab15717..1e1c5bc9f035 100644 --- a/nixos/modules/services/computing/slurm/slurm.nix +++ b/nixos/modules/services/computing/slurm/slurm.nix @@ -6,7 +6,7 @@ let cfg = config.services.slurm; # configuration file can be generated by http://slurm.schedmd.com/configurator.html - configFile = pkgs.writeText "slurm.conf" + configFile = pkgs.writeTextDir "slurm.conf" '' ${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''} ${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''} @@ -17,10 +17,25 @@ let ${cfg.extraConfig} ''; - plugStackConfig = pkgs.writeText "plugstack.conf" + plugStackConfig = pkgs.writeTextDir "plugstack.conf" '' ${optionalString cfg.enableSrunX11 ''optional ${pkgs.slurm-spank-x11}/lib/x11.so''} + ${cfg.extraPlugstackConfig} ''; + + + cgroupConfig = pkgs.writeTextDir "cgroup.conf" + '' + ${cfg.extraCgroupConfig} + ''; + + # slurm expects some additional config files to be + # in the same directory as slurm.conf + etcSlurm = pkgs.symlinkJoin { + name = "etc-slurm"; + paths = [ configFile cgroupConfig plugStackConfig ]; + }; + in { @@ -46,7 +61,17 @@ in client = { enable = mkEnableOption "slurm client daemon"; + }; + enableStools = mkOption { + type = types.bool; + default = false; + description = '' + Wether to provide a slurm.conf file. + Enable this option if you do not run a slurm daemon on this host + (i.e. <literal>server.enable</literal> and <literal>client.enable</literal> are <literal>false</literal>) + but you still want to run slurm commands from this host. + ''; }; package = mkOption { @@ -97,7 +122,7 @@ in example = "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP"; description = '' Name by which the partition may be referenced. Note that now you have - to write patrition's parameters after the name. + to write the partition's parameters after the name. ''; }; @@ -107,8 +132,10 @@ in description = '' If enabled srun will accept the option "--x11" to allow for X11 forwarding from within an interactive session or a batch job. This activates the - slurm-spank-x11 module. Note that this requires 'services.openssh.forwardX11' - to be enabled on the compute nodes. + slurm-spank-x11 module. Note that this option also enables + 'services.openssh.forwardX11' on the client. + + This option requires slurm to be compiled without native X11 support. ''; }; @@ -130,6 +157,23 @@ in the end of the slurm configuration file. ''; }; + + extraPlugstackConfig = mkOption { + default = ""; + type = types.lines; + description = '' + Extra configuration that will be added to the end of <literal>plugstack.conf</literal>. + ''; + }; + + extraCgroupConfig = mkOption { + default = ""; + type = types.lines; + description = '' + Extra configuration for <literal>cgroup.conf</literal>. This file is + used when <literal>procTrackType=proctrack/cgroup</literal>. + ''; + }; }; }; @@ -142,8 +186,6 @@ in wrappedSlurm = pkgs.stdenv.mkDerivation { name = "wrappedSlurm"; - propagatedBuildInputs = [ cfg.package configFile ]; - builder = pkgs.writeText "builder.sh" '' source $stdenv/setup mkdir -p $out/bin @@ -155,17 +197,20 @@ in #!/bin/sh if [ -z "$SLURM_CONF" ] then - SLURM_CONF="${configFile}" "$EXE" "\$@" + SLURM_CONF="${etcSlurm}/slurm.conf" "$EXE" "\$@" else "$EXE" "\$0" fi EOT chmod +x "$wrappername" done + + mkdir -p $out/share + ln -s ${getBin cfg.package}/share/man $out/share/man ''; }; - in mkIf (cfg.client.enable || cfg.server.enable) { + in mkIf (cfg.enableStools || cfg.client.enable || cfg.server.enable) { environment.systemPackages = [ wrappedSlurm ]; @@ -190,6 +235,8 @@ in ''; }; + services.openssh.forwardX11 = mkIf cfg.client.enable (mkDefault true); + systemd.services.slurmctld = mkIf (cfg.server.enable) { path = with pkgs; [ wrappedSlurm munge coreutils ] ++ lib.optional cfg.enableSrunX11 slurm-spank-x11; diff --git a/nixos/modules/services/mail/exim.nix b/nixos/modules/services/mail/exim.nix index 440eae281f40..f9ee3f909660 100644 --- a/nixos/modules/services/mail/exim.nix +++ b/nixos/modules/services/mail/exim.nix @@ -94,6 +94,7 @@ in systemd.services.exim = { description = "Exim Mail Daemon"; wantedBy = [ "multi-user.target" ]; + restartTriggers = [ config.environment.etc."exim.conf".source ]; serviceConfig = { ExecStart = "${exim}/bin/exim -bdf -q30m"; ExecReload = "${coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index 45dfdc71eb36..46efc1df12eb 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -356,7 +356,7 @@ in text = cfg.database.password; }))); - systemd.services.gitea-dump = { + systemd.services.gitea-dump = mkIf cfg.dump.enable { description = "gitea dump"; after = [ "gitea.service" ]; wantedBy = [ "default.target" ]; @@ -376,7 +376,7 @@ in }; }; - systemd.timers.gitea-dump = { + systemd.timers.gitea-dump = mkIf cfg.dump.enable { description = "Update timer for gitea-dump"; partOf = [ "gitea-dump.service" ]; wantedBy = [ "timers.target" ]; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 429ce09ea68f..0ee105e4c6f1 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -130,11 +130,13 @@ in default = false; description = " If set, Nix will perform builds in a sandboxed environment that it - will set up automatically for each build. This prevents - impurities in builds by disallowing access to dependencies - outside of the Nix store. This isn't enabled by default for - performance. It doesn't affect derivation hashes, so changing - this option will not trigger a rebuild of packages. + will set up automatically for each build. This prevents impurities + in builds by disallowing access to dependencies outside of the Nix + store by using network and mount namespaces in a chroot environment. + This isn't enabled by default for possible performance impacts due to + the initial setup time of a sandbox for each build. It doesn't affect + derivation hashes, so changing this option will not trigger a rebuild + of packages. "; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 780448d8bad8..8d2c303a69e8 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -20,6 +20,7 @@ let exporterOpts = { blackbox = import ./exporters/blackbox.nix { inherit config lib pkgs; }; collectd = import ./exporters/collectd.nix { inherit config lib pkgs; }; + dnsmasq = import ./exporters/dnsmasq.nix { inherit config lib pkgs; }; dovecot = import ./exporters/dovecot.nix { inherit config lib pkgs; }; fritzbox = import ./exporters/fritzbox.nix { inherit config lib pkgs; }; json = import ./exporters/json.nix { inherit config lib pkgs; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix new file mode 100644 index 000000000000..b1fab85109af --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs }: + +with lib; + +let + cfg = config.services.prometheus.exporters.dnsmasq; +in +{ + port = 9153; + extraOpts = { + dnsmasqListenAddress = mkOption { + type = types.str; + default = "localhost:53"; + description = '' + Address on which dnsmasq listens. + ''; + }; + leasesPath = mkOption { + type = types.path; + default = "/var/lib/misc/dnsmasq.leases"; + example = "/var/lib/dnsmasq/dnsmasq.leases"; + description = '' + Path to the <literal>dnsmasq.leases</literal> file. + ''; + }; + }; + serviceOpts = { + serviceConfig = { + DynamicUser = true; + ExecStart = '' + ${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \ + --listen ${cfg.listenAddress}:${toString cfg.port} \ + --dnsmasq ${cfg.dnsmasqListenAddress} \ + --leases_path ${cfg.leasesPath} \ + ${concatStringsSep " \\\n " cfg.extraFlags} + ''; + }; + }; +} diff --git a/nixos/modules/services/networking/morty.nix b/nixos/modules/services/networking/morty.nix new file mode 100644 index 000000000000..b31bec9a8627 --- /dev/null +++ b/nixos/modules/services/networking/morty.nix @@ -0,0 +1,98 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.morty; + + configFile = cfg.configFile; + +in + +{ + + ###### interface + + options = { + + services.morty = { + + enable = mkEnableOption + "Morty proxy server. See https://github.com/asciimoo/morty"; + + ipv6 = mkOption { + type = types.bool; + default = true; + description = "Allow IPv6 HTTP requests?"; + defaultText = "Allow IPv6 HTTP requests."; + }; + + key = mkOption { + type = types.string; + default = ""; + description = "HMAC url validation key (hexadecimal encoded). + Leave blank to disable. Without validation key, anyone can + submit proxy requests. Leave blank to disable."; + defaultText = "No HMAC url validation. Generate with echo -n somevalue | openssl dgst -sha1 -hmac somekey"; + }; + + timeout = mkOption { + type = types.int; + default = 2; + description = "Request timeout in seconds."; + defaultText = "A resource now gets 2 seconds to respond."; + }; + + package = mkOption { + type = types.package; + default = pkgs.morty; + defaultText = "pkgs.morty"; + description = "morty package to use."; + }; + + port = mkOption { + type = types.int; + default = 3000; + description = "Listing port"; + }; + + listenAddress = mkOption { + type = types.string; + default = "127.0.0.1"; + description = "The address on which the service listens"; + defaultText = "127.0.0.1 (localhost)"; + }; + + }; + + }; + + ###### Service definition + + config = mkIf config.services.morty.enable { + + users.extraUsers.morty = + { description = "Morty user"; + createHome = true; + home = "/var/lib/morty"; + }; + + systemd.services.morty = + { + description = "Morty sanitizing proxy server."; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "morty"; + ExecStart = ''${cfg.package}/bin/morty \ + -listen ${cfg.listenAddress}:${toString cfg.port} \ + ${optionalString cfg.ipv6 "-ipv6"} \ + ${optionalString (cfg.key != "") "-key " + cfg.key} \ + ''; + }; + }; + environment.systemPackages = [ cfg.package ]; + + }; +} diff --git a/nixos/modules/services/networking/openntpd.nix b/nixos/modules/services/networking/openntpd.nix index 4bb9da54fe09..241038ca12ed 100644 --- a/nixos/modules/services/networking/openntpd.nix +++ b/nixos/modules/services/networking/openntpd.nix @@ -7,7 +7,7 @@ let package = pkgs.openntpd_nixos; - cfgFile = pkgs.writeText "openntpd.conf" '' + configFile = '' ${concatStringsSep "\n" (map (s: "server ${s}") cfg.servers)} ${cfg.extraConfig} ''; @@ -31,8 +31,8 @@ in type = with types; lines; default = ""; example = '' - listen on 127.0.0.1 - listen on ::1 + listen on 127.0.0.1 + listen on ::1 ''; description = '' Additional text appended to <filename>openntpd.conf</filename>. @@ -57,6 +57,8 @@ in # Add ntpctl to the environment for status checking environment.systemPackages = [ package ]; + environment.etc."ntpd.conf".text = configFile; + users.extraUsers = singleton { name = "ntp"; uid = config.ids.uids.ntp; @@ -71,7 +73,7 @@ in before = [ "time-sync.target" ]; after = [ "dnsmasq.service" "bind.service" "network-online.target" ]; serviceConfig = { - ExecStart = "${package}/sbin/ntpd -f ${cfgFile} -p ${pidFile} ${cfg.extraOptions}"; + ExecStart = "${package}/sbin/ntpd -p ${pidFile} ${cfg.extraOptions}"; Type = "forking"; PIDFile = pidFile; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index aab1203086ce..902e759f3a3a 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -272,6 +272,31 @@ in ''; }; + logLevel = mkOption { + type = types.enum [ "QUIET" "FATAL" "ERROR" "INFO" "VERBOSE" "DEBUG" "DEBUG1" "DEBUG2" "DEBUG3" ]; + default = "VERBOSE"; + description = '' + Gives the verbosity level that is used when logging messages from sshd(8). The possible values are: + QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is VERBOSE. DEBUG and DEBUG1 + are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level + violates the privacy of users and is not recommended. + + LogLevel VERBOSE logs user's key fingerprint on login. + Needed to have a clear audit track of which key was used to log in. + ''; + }; + + useDns = mkOption { + type = types.bool; + default = false; + description = '' + Specifies whether sshd(8) should look up the remote host name, and to check that the resolved host name for + the remote IP address maps back to the very same IP address. + If this option is set to no (the default) then only addresses and not host names may be used in + ~/.ssh/authorized_keys from and sshd_config Match Host directives. + ''; + }; + extraConfig = mkOption { type = types.lines; default = ""; @@ -426,9 +451,14 @@ in Ciphers ${concatStringsSep "," cfg.ciphers} MACs ${concatStringsSep "," cfg.macs} - # LogLevel VERBOSE logs user's key fingerprint on login. - # Needed to have a clear audit track of which key was used to log in. - LogLevel VERBOSE + LogLevel ${cfg.logLevel} + + ${if cfg.useDns then '' + UseDNS yes + '' else '' + UseDNS no + ''} + ''; assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true; diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix index e3d65c49fbf2..0222e8ce8b58 100644 --- a/nixos/modules/services/networking/sslh.nix +++ b/nixos/modules/services/networking/sslh.nix @@ -4,15 +4,14 @@ with lib; let cfg = config.services.sslh; + user = "sslh"; configFile = pkgs.writeText "sslh.conf" '' verbose: ${boolToString cfg.verbose}; foreground: true; inetd: false; numeric: false; - transparent: false; + transparent: ${boolToString cfg.transparent}; timeout: "${toString cfg.timeout}"; - user: "nobody"; - pidfile: "${cfg.pidfile}"; listen: ( @@ -50,16 +49,16 @@ in description = "Timeout in seconds."; }; - pidfile = mkOption { - type = types.path; - default = "/run/sslh.pid"; - description = "PID file path for sslh daemon."; + transparent = mkOption { + type = types.bool; + default = false; + description = "Will the services behind sslh (Apache, sshd and so on) see the external IP and ports as if the external world connected directly to them"; }; listenAddress = mkOption { type = types.str; - default = config.networking.hostName; - description = "Listening hostname."; + default = "0.0.0.0"; + description = "Listening address or hostname."; }; port = mkOption { @@ -76,14 +75,91 @@ in }; }; - config = mkIf cfg.enable { - systemd.services.sslh = { - description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F${configFile}"; - serviceConfig.KillMode = "process"; - serviceConfig.PIDFile = "${cfg.pidfile}"; - }; - }; + config = mkMerge [ + (mkIf cfg.enable { + users.users.${user} = { + description = "sslh daemon user"; + isSystemUser = true; + }; + + systemd.services.sslh = { + description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + User = user; + Group = "nogroup"; + PermissionsStartOnly = true; + Restart = "always"; + RestartSec = "1s"; + ExecStart = "${pkgs.sslh}/bin/sslh -F${configFile}"; + KillMode = "process"; + AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_NET_ADMIN CAP_SETGID CAP_SETUID"; + PrivateTmp = true; + PrivateDevices = true; + ProtectSystem = "full"; + ProtectHome = true; + }; + }; + }) + + # code from https://github.com/yrutschle/sslh#transparent-proxy-support + # the only difference is using iptables mark 0x2 instead of 0x1 to avoid conflicts with nixos/nat module + (mkIf (cfg.enable && cfg.transparent) { + # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + boot.kernel.sysctl."net.ipv4.conf.default.route_localnet" = 1; + boot.kernel.sysctl."net.ipv4.conf.all.route_localnet" = 1; + + systemd.services.sslh = let + iptablesCommands = [ + # DROP martian packets as they would have been if route_localnet was zero + # Note: packets not leaving the server aren't affected by this, thus sslh will still work + { table = "raw"; command = "PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP"; } + { table = "mangle"; command = "POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP"; } + # Mark all connections made by ssl for special treatment (here sslh is run as user ${user}) + { table = "nat"; command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f"; } + # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) + { table = "mangle"; command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f"; } + ]; + ip6tablesCommands = [ + { table = "raw"; command = "PREROUTING ! -i lo -d ::1/128 -j DROP"; } + { table = "mangle"; command = "POSTROUTING ! -o lo -s ::1/128 -j DROP"; } + { table = "nat"; command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f"; } + { table = "mangle"; command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f"; } + ]; + in { + path = [ pkgs.iptables pkgs.iproute pkgs.procps ]; + + preStart = '' + # Cleanup old iptables entries which might be still there + ${concatMapStringsSep "\n" ({table, command}: "while iptables -w -t ${table} -D ${command} 2>/dev/null; do echo; done") iptablesCommands} + ${concatMapStringsSep "\n" ({table, command}: "iptables -w -t ${table} -A ${command}" ) iptablesCommands} + + # Configure routing for those marked packets + ip rule add fwmark 0x2 lookup 100 + ip route add local 0.0.0.0/0 dev lo table 100 + + '' + optionalString config.networking.enableIPv6 '' + ${concatMapStringsSep "\n" ({table, command}: "while ip6tables -w -t ${table} -D ${command} 2>/dev/null; do echo; done") ip6tablesCommands} + ${concatMapStringsSep "\n" ({table, command}: "ip6tables -w -t ${table} -A ${command}" ) ip6tablesCommands} + + ip -6 rule add fwmark 0x2 lookup 100 + ip -6 route add local ::/0 dev lo table 100 + ''; + + postStop = '' + ${concatMapStringsSep "\n" ({table, command}: "iptables -w -t ${table} -D ${command}") iptablesCommands} + + ip rule del fwmark 0x2 lookup 100 + ip route del local 0.0.0.0/0 dev lo table 100 + '' + optionalString config.networking.enableIPv6 '' + ${concatMapStringsSep "\n" ({table, command}: "ip6tables -w -t ${table} -D ${command}") ip6tablesCommands} + + ip -6 rule del fwmark 0x2 lookup 100 + ip -6 route del local ::/0 dev lo table 100 + ''; + }; + }) + ]; } diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix index e3b6b638f5a7..0ea41f3c3985 100644 --- a/nixos/modules/services/scheduling/fcron.nix +++ b/nixos/modules/services/scheduling/fcron.nix @@ -128,6 +128,7 @@ in owner = "fcron"; group = "fcron"; setgid = true; + setuid = true; }; fcrondyn = { source = "${pkgs.fcron}/bin/fcrondyn"; diff --git a/nixos/modules/services/security/munge.nix b/nixos/modules/services/security/munge.nix index 919c2c2b0e15..5bca15833544 100644 --- a/nixos/modules/services/security/munge.nix +++ b/nixos/modules/services/security/munge.nix @@ -35,7 +35,15 @@ in environment.systemPackages = [ pkgs.munge ]; - systemd.services.munged = { + users.users.munge = { + description = "Munge daemon user"; + isSystemUser = true; + group = "munge"; + }; + + users.groups.munge = {}; + + systemd.services.munged = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; @@ -44,14 +52,20 @@ in preStart = '' chmod 0700 ${cfg.password} mkdir -p /var/lib/munge -m 0711 + chown -R munge:munge /var/lib/munge mkdir -p /var/log/munge -m 0700 + chown -R munge:munge /var/log/munge mkdir -p /run/munge -m 0755 + chown -R munge:munge /run/munge ''; serviceConfig = { ExecStart = "${pkgs.munge}/bin/munged --syslog --key-file ${cfg.password}"; PIDFile = "/run/munge/munged.pid"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + PermissionsStartOnly = "true"; + User = "munge"; + Group = "munge"; }; }; diff --git a/nixos/modules/services/web-servers/minio.nix b/nixos/modules/services/web-servers/minio.nix index 843f0d986877..7ead33483ea4 100644 --- a/nixos/modules/services/web-servers/minio.nix +++ b/nixos/modules/services/web-servers/minio.nix @@ -85,7 +85,7 @@ in ''; serviceConfig = { PermissionsStartOnly = true; - ExecStart = "${cfg.package}/bin/minio server --address ${cfg.listenAddress} --config-dir=${cfg.configDir} ${cfg.dataDir}"; + ExecStart = "${cfg.package}/bin/minio server --json --address ${cfg.listenAddress} --config-dir=${cfg.configDir} ${cfg.dataDir}"; Type = "simple"; User = "minio"; Group = "minio"; diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 67daaa333e5e..2e497ff9f2c4 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -64,9 +64,10 @@ let )) + ":" + (makeSearchPathOutput "bin" "sbin" [ pkgs.mdadm pkgs.utillinux ]); - font = if lib.last (lib.splitString "." cfg.font) == "pf2" + font = if cfg.font == null then "" + else (if lib.last (lib.splitString "." cfg.font) == "pf2" then cfg.font - else "${convertedFont}"; + else "${convertedFont}"); }); bootDeviceCounters = fold (device: attr: attr // { "${device}" = (attr."${device}" or 0) + 1; }) {} diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 1aa14729a75c..872261d0edfa 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -281,22 +281,24 @@ else { else insmod vbe fi - insmod font - if loadfont " . $grubBoot->path . "/converted-font.pf2; then - insmod gfxterm - if [ \"\${grub_platform}\" = \"efi\" ]; then - set gfxmode=$gfxmodeEfi - set gfxpayload=keep - else - set gfxmode=$gfxmodeBios - set gfxpayload=text - fi - terminal_output gfxterm - fi "; if ($font) { copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath\n"; + $conf .= " + insmod font + if loadfont " . $grubBoot->path . "/converted-font.pf2; then + insmod gfxterm + if [ \"\${grub_platform}\" = \"efi\" ]; then + set gfxmode=$gfxmodeEfi + set gfxpayload=keep + else + set gfxmode=$gfxmodeBios + set gfxpayload=text + fi + terminal_output gfxterm + fi + "; } if ($splashImage) { # Keeps the image's extension. diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix index ae9ee8811f77..8b37bf8d35d8 100644 --- a/nixos/modules/system/boot/systemd-lib.nix +++ b/nixos/modules/system/boot/systemd-lib.nix @@ -78,10 +78,16 @@ in rec { optional (badFields != [ ]) "Systemd ${group} has extra fields [${concatStringsSep " " badFields}]."; - checkUnitConfig = group: checks: v: - let errors = concatMap (c: c group v) checks; in - if errors == [] then true - else builtins.trace (concatStringsSep "\n" errors) false; + checkUnitConfig = group: checks: attrs: let + # We're applied at the top-level type (attrsOf unitOption), so the actual + # unit options might contain attributes from mkOverride that we need to + # convert into single values before checking them. + defs = mapAttrs (const (v: + if v._type or "" == "override" then v.content else v + )) attrs; + errors = concatMap (c: c group defs) checks; + in if errors == [] then true + else builtins.trace (concatStringsSep "\n" errors) false; toOption = x: if x == true then "true" diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index c3bf897d51fd..de735e9ba11b 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -403,6 +403,9 @@ in nameValuePair "zfs-sync-${pool}" { description = "Sync ZFS pool \"${pool}\""; wantedBy = [ "shutdown.target" ]; + unitConfig = { + DefaultDependencies = false; + }; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index 374a84332357..de2c43b8a40a 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -257,7 +257,7 @@ in echo "Setup of ssh host keys from http://metadata.google.internal/computeMetadata/v1/instance/attributes/ failed." false fi - rm -f $SSH_HOST_KEYS_DIR + rm -rf $SSH_HOST_KEYS_DIR ''; serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; diff --git a/nixos/modules/virtualisation/kvmgt.nix b/nixos/modules/virtualisation/kvmgt.nix new file mode 100644 index 000000000000..fc0bedb68bd0 --- /dev/null +++ b/nixos/modules/virtualisation/kvmgt.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.virtualisation.kvmgt; + kernelPackages = config.boot.kernelPackages; + vgpuOptions = { + uuid = mkOption { + type = types.string; + description = "UUID of VGPU device. You can generate one with <package>libossp_uuid</package>."; + }; + }; +in { + options = { + virtualisation.kvmgt = { + enable = mkEnableOption '' + KVMGT (iGVT-g) VGPU support. Allows Qemu/KVM guests to share host's Intel integrated graphics card. + Currently only one graphical device can be shared + ''; + # multi GPU support is under the question + device = mkOption { + type = types.string; + default = "0000:00:02.0"; + description = "PCI ID of graphics card. You can figure it with <command>ls /sys/class/mdev_bus</command>."; + }; + vgpus = mkOption { + default = {}; + type = with types; attrsOf (submodule [ { options = vgpuOptions; } ]); + description = '' + Virtual GPUs to be used in Qemu. You can find devices via <command>ls /sys/bus/pci/devices/*/mdev_supported_types</command> + and find info about device via <command>cat /sys/bus/pci/devices/*/mdev_supported_types/i915-GVTg_V5_4/description</command> + ''; + example = { + "i915-GVTg_V5_8" = { + uuid = "a297db4a-f4c2-11e6-90f6-d3b88d6c9525"; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = singleton { + assertion = versionAtLeast kernelPackages.kernel.version "4.16"; + message = "KVMGT is not properly supported for kernels older than 4.16"; + }; + boot.kernelParams = [ "i915.enable_gvt=1" ]; + systemd.services = mapAttrs' (name: value: + nameValuePair "kvmgt-${name}" { + description = "KVMGT VGPU ${name}"; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.runtimeShell} -c 'echo ${value.uuid} > /sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create'"; + ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/bus/pci/devices/${cfg.device}/${value.uuid}/remove'"; + }; + wantedBy = [ "multi-user.target" ]; + } + ) cfg.vgpus; + }; + + meta.maintainers = with maintainers; [ gnidorah ]; +} |