diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2020-11-28 17:09:12 +0000 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2020-11-28 17:09:12 +0000 |
commit | c6617d28ef3762bbd5cb11dd3c56afb778ff42cc (patch) | |
tree | 18fbdfb4783a2e0c5625cdb51606058ca50e2ca8 /nixos/modules/services | |
parent | 29cdd8ae609d107889469610176aa53676382eb1 (diff) | |
parent | 05d95cfe79a69cf690cec5d356b37e29d7d13d18 (diff) |
Merge remote-tracking branch 'upstream/master' into aj-rust-custom-target
Diffstat (limited to 'nixos/modules/services')
39 files changed, 556 insertions, 164 deletions
diff --git a/nixos/modules/services/admin/salt/master.nix b/nixos/modules/services/admin/salt/master.nix index c6b1b0cc0bd8..cb803d323bbd 100644 --- a/nixos/modules/services/admin/salt/master.nix +++ b/nixos/modules/services/admin/salt/master.nix @@ -59,5 +59,5 @@ in }; }; - meta.maintainers = with lib.maintainers; [ aneeshusa ]; + meta.maintainers = with lib.maintainers; [ Flakebi ]; } diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix index fff119c2cf00..e72e3fa59cf9 100644 --- a/nixos/modules/services/backup/syncoid.nix +++ b/nixos/modules/services/backup/syncoid.nix @@ -4,6 +4,15 @@ with lib; let cfg = config.services.syncoid; + + # Extract pool names of local datasets (ones that don't contain "@") that + # have the specified type (either "source" or "target") + getPools = type: unique (map (d: head (builtins.match "([^/]+).*" d)) ( + # Filter local datasets + filter (d: !hasInfix "@" d) + # Get datasets of the specified type + (catAttrs type (attrValues cfg.commands)) + )); in { # Interface @@ -26,14 +35,25 @@ in { user = mkOption { type = types.str; - default = "root"; + default = "syncoid"; example = "backup"; description = '' - The user for the service. Sudo or ZFS privilege delegation must be - configured to use a user other than root. + The user for the service. ZFS privilege delegation will be + automatically configured for any local pools used by syncoid if this + option is set to a user other than root. The user will be given the + "hold" and "send" privileges on any pool that has datasets being sent + and the "create", "mount", "receive", and "rollback" privileges on + any pool that has datasets being received. ''; }; + group = mkOption { + type = types.str; + default = "syncoid"; + example = "backup"; + description = "The group for the service."; + }; + sshKey = mkOption { type = types.nullOr types.path; # Prevent key from being copied to store @@ -150,6 +170,18 @@ in { # Implementation config = mkIf cfg.enable { + users = { + users = mkIf (cfg.user == "syncoid") { + syncoid = { + group = cfg.group; + isSystemUser = true; + }; + }; + groups = mkIf (cfg.group == "syncoid") { + syncoid = {}; + }; + }; + systemd.services.syncoid = { description = "Syncoid ZFS synchronization service"; script = concatMapStringsSep "\n" (c: lib.escapeShellArgs @@ -160,10 +192,22 @@ in { ++ c.extraArgs ++ [ "--sendoptions" c.sendOptions "--recvoptions" c.recvOptions + "--no-privilege-elevation" c.source c.target ])) (attrValues cfg.commands); after = [ "zfs.target" ]; - serviceConfig.User = cfg.user; + serviceConfig = { + ExecStartPre = (map (pool: lib.escapeShellArgs [ + "+/run/booted-system/sw/bin/zfs" "allow" + cfg.user "hold,send" pool + ]) (getPools "source")) ++ + (map (pool: lib.escapeShellArgs [ + "+/run/booted-system/sw/bin/zfs" "allow" + cfg.user "create,mount,receive,rollback" pool + ]) (getPools "target")); + User = cfg.user; + Group = cfg.group; + }; startAt = cfg.interval; }; }; diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix index 502a5898a5de..252ca17006da 100644 --- a/nixos/modules/services/continuous-integration/hydra/default.nix +++ b/nixos/modules/services/continuous-integration/hydra/default.nix @@ -37,8 +37,6 @@ let haveLocalDB = cfg.dbi == localDB; - inherit (config.system) stateVersion; - hydra-package = let makeWrapperArgs = concatStringsSep " " (mapAttrsToList (key: value: "--set \"${key}\" \"${value}\"") hydraEnv); @@ -96,7 +94,8 @@ in package = mkOption { type = types.package; - defaultText = "pkgs.hydra"; + default = pkgs.hydra-unstable; + defaultText = "pkgs.hydra-unstable"; description = "The Hydra package."; }; @@ -225,34 +224,6 @@ in config = mkIf cfg.enable { - warnings = optional (cfg.package.migration or false) '' - You're currently deploying an older version of Hydra which is needed to - make some required database changes[1]. As soon as this is done, it's recommended - to run `hydra-backfill-ids` and set `services.hydra.package` to `pkgs.hydra-unstable` - after that. - - [1] https://github.com/NixOS/hydra/pull/711 - ''; - - services.hydra.package = with pkgs; - mkDefault ( - if pkgs ? hydra - then throw '' - The Hydra package doesn't exist anymore in `nixpkgs`! It probably exists - due to an overlay. To upgrade Hydra, you need to take two steps as some - bigger changes in the database schema were implemented recently[1]. You first - need to deploy `pkgs.hydra-migration`, run `hydra-backfill-ids` on the server - and then deploy `pkgs.hydra-unstable`. - - If you want to use `pkgs.hydra` from your overlay, please set `services.hydra.package` - explicitly to `pkgs.hydra` and make sure you know what you're doing. - - [1] https://github.com/NixOS/hydra/pull/711 - '' - else if versionOlder stateVersion "20.03" then hydra-migration - else hydra-unstable - ); - users.groups.hydra = { gid = config.ids.gids.hydra; }; diff --git a/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix index 1477c471f8ab..cdc3b4b5c58f 100644 --- a/nixos/modules/services/continuous-integration/jenkins/default.nix +++ b/nixos/modules/services/continuous-integration/jenkins/default.nix @@ -86,8 +86,8 @@ in { }; packages = mkOption { - default = [ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ]; - defaultText = "[ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ]"; + default = [ pkgs.stdenv pkgs.git pkgs.jdk11 config.programs.ssh.package pkgs.nix ]; + defaultText = "[ pkgs.stdenv pkgs.git pkgs.jdk11 config.programs.ssh.package pkgs.nix ]"; type = types.listOf types.package; description = '' Packages to add to PATH for the jenkins process. @@ -207,7 +207,7 @@ in { # For reference: https://wiki.jenkins.io/display/JENKINS/JenkinsLinuxStartupScript script = '' - ${pkgs.jdk}/bin/java ${concatStringsSep " " cfg.extraJavaOptions} -jar ${cfg.package}/webapps/jenkins.war --httpListenAddress=${cfg.listenAddress} \ + ${pkgs.jdk11}/bin/java ${concatStringsSep " " cfg.extraJavaOptions} -jar ${cfg.package}/webapps/jenkins.war --httpListenAddress=${cfg.listenAddress} \ --httpPort=${toString cfg.port} \ --prefix=${cfg.prefix} \ -Djava.awt.headless=true \ diff --git a/nixos/modules/services/desktops/flatpak.nix b/nixos/modules/services/desktops/flatpak.nix index 7da92cc9f264..d0f6b66328a4 100644 --- a/nixos/modules/services/desktops/flatpak.nix +++ b/nixos/modules/services/desktops/flatpak.nix @@ -15,6 +15,18 @@ in { options = { services.flatpak = { enable = mkEnableOption "flatpak"; + + guiPackages = mkOption { + internal = true; + type = types.listOf types.package; + default = []; + example = literalExample "[ pkgs.gnome3.gnome-software ]"; + description = '' + Packages that provide an interface for flatpak + (like gnome-software) that will be automatically available + to all users when flatpak is enabled. + ''; + }; }; }; @@ -28,7 +40,7 @@ in { } ]; - environment.systemPackages = [ pkgs.flatpak ]; + environment.systemPackages = [ pkgs.flatpak ] ++ cfg.guiPackages; services.dbus.packages = [ pkgs.flatpak ]; diff --git a/nixos/modules/services/desktops/pipewire.nix b/nixos/modules/services/desktops/pipewire.nix index 5aee59cfdcce..5179cbaf6bc2 100644 --- a/nixos/modules/services/desktops/pipewire.nix +++ b/nixos/modules/services/desktops/pipewire.nix @@ -5,8 +5,22 @@ with lib; let cfg = config.services.pipewire; - packages = with pkgs; [ pipewire ]; + enable32BitAlsaPlugins = cfg.alsa.support32Bit + && pkgs.stdenv.isx86_64 + && pkgs.pkgsi686Linux.pipewire != null; + # The package doesn't output to $out/lib/pipewire directly so that the + # overlays can use the outputs to replace the originals in FHS environments. + # + # This doesn't work in general because of missing development information. + jack-libs = pkgs.runCommand "jack-libs" {} '' + mkdir -p "$out/lib" + ln -s "${pkgs.pipewire.jack}/lib" "$out/lib/pipewire" + ''; + pulse-libs = pkgs.runCommand "pulse-libs" {} '' + mkdir -p "$out/lib" + ln -s "${pkgs.pipewire.pulse}/lib" "$out/lib/pipewire" + ''; in { meta = { @@ -25,17 +39,67 @@ in { Automatically run pipewire when connections are made to the pipewire socket. ''; }; + + alsa = { + enable = mkEnableOption "ALSA support"; + support32Bit = mkEnableOption "32-bit ALSA support on 64-bit systems"; + }; + + jack = { + enable = mkEnableOption "JACK audio emulation"; + }; + + pulse = { + enable = mkEnableOption "PulseAudio emulation"; + }; }; }; ###### implementation config = mkIf cfg.enable { - environment.systemPackages = packages; + assertions = [ + { + assertion = cfg.pulse.enable -> !config.hardware.pulseaudio.enable; + message = "PipeWire based PulseAudio emulation doesn't use the PulseAudio service"; + } + { + assertion = cfg.jack.enable -> !config.services.jack.jackd.enable; + message = "PIpeWire based JACK emulation doesn't use the JACK service"; + } + ]; + + environment.systemPackages = [ pkgs.pipewire ] + ++ lib.optional cfg.jack.enable jack-libs + ++ lib.optional cfg.pulse.enable pulse-libs; - systemd.packages = packages; + systemd.packages = [ pkgs.pipewire ]; + # PipeWire depends on DBUS but doesn't list it. Without this booting + # into a terminal results in the service crashing with an error. systemd.user.sockets.pipewire.wantedBy = lib.mkIf cfg.socketActivation [ "sockets.target" ]; - }; + systemd.user.services.pipewire.bindsTo = [ "dbus.service" ]; + services.udev.packages = [ pkgs.pipewire ]; + # If any paths are updated here they must also be updated in the package test. + sound.extraConfig = mkIf cfg.alsa.enable '' + pcm_type.pipewire { + libs.native = ${pkgs.pipewire.lib}/lib/alsa-lib/libasound_module_pcm_pipewire.so ; + ${optionalString enable32BitAlsaPlugins + "libs.32Bit = ${pkgs.pkgsi686Linux.pipewire.lib}/lib/alsa-lib/libasound_module_pcm_pipewire.so ;"} + } + pcm.!default { + @func getenv + vars [ PCM ] + default "plug:pipewire" + playback_mode "-1" + capture_mode "-1" + } + ''; + environment.etc."alsa/conf.d/50-pipewire.conf" = mkIf cfg.alsa.enable { + source = "${pkgs.pipewire}/share/alsa/alsa.conf.d/50-pipewire.conf"; + }; + environment.sessionVariables.LD_LIBRARY_PATH = + lib.optional (cfg.jack.enable || cfg.pulse.enable) "/run/current-system/sw/lib/pipewire"; + }; } diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix index 054ffa35050a..9c2f78a755dd 100644 --- a/nixos/modules/services/hardware/undervolt.nix +++ b/nixos/modules/services/hardware/undervolt.nix @@ -3,7 +3,12 @@ with lib; let cfg = config.services.undervolt; - cliArgs = lib.cli.toGNUCommandLineShell {} { + + mkPLimit = limit: window: + if (isNull limit && isNull window) then null + else assert asserts.assertMsg (!isNull limit && !isNull window) "Both power limit and window must be set"; + "${toString limit} ${toString window}"; + cliArgs = lib.cli.toGNUCommandLine {} { inherit (cfg) verbose temp @@ -21,6 +26,9 @@ let temp-bat = cfg.tempBat; temp-ac = cfg.tempAc; + + power-limit-long = mkPLimit cfg.p1.limit cfg.p1.window; + power-limit-short = mkPLimit cfg.p2.limit cfg.p2.window; }; in { @@ -104,6 +112,40 @@ in ''; }; + p1.limit = mkOption { + type = with types; nullOr int; + default = null; + description = '' + The P1 Power Limit in Watts. + Both limit and window must be set. + ''; + }; + p1.window = mkOption { + type = with types; nullOr (oneOf [ float int ]); + default = null; + description = '' + The P1 Time Window in seconds. + Both limit and window must be set. + ''; + }; + + p2.limit = mkOption { + type = with types; nullOr int; + default = null; + description = '' + The P2 Power Limit in Watts. + Both limit and window must be set. + ''; + }; + p2.window = mkOption { + type = with types; nullOr (oneOf [ float int ]); + default = null; + description = '' + The P2 Time Window in seconds. + Both limit and window must be set. + ''; + }; + useTimer = mkOption { type = types.bool; default = false; @@ -133,7 +175,7 @@ in serviceConfig = { Type = "oneshot"; Restart = "no"; - ExecStart = "${pkgs.undervolt}/bin/undervolt ${cliArgs}"; + ExecStart = "${pkgs.undervolt}/bin/undervolt ${toString cliArgs}"; }; }; diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index aacdbe2aeed2..86a3f52107d5 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -153,7 +153,7 @@ let ${concatStringsSep "\n" (mapAttrsToList (name: value: let includeName = if name == "rspamd_proxy" then "proxy" else name; - tryOverride = if value.extraConfig == "" then "true" else "false"; + tryOverride = boolToString (value.extraConfig == ""); in '' worker "${value.type}" { type = "${value.type}"; diff --git a/nixos/modules/services/misc/jellyfin.nix b/nixos/modules/services/misc/jellyfin.nix index 0493dadea94e..6a47dc3628f4 100644 --- a/nixos/modules/services/misc/jellyfin.nix +++ b/nixos/modules/services/misc/jellyfin.nix @@ -45,6 +45,46 @@ in CacheDirectory = "jellyfin"; ExecStart = "${cfg.package}/bin/jellyfin --datadir '/var/lib/${StateDirectory}' --cachedir '/var/cache/${CacheDirectory}'"; Restart = "on-failure"; + + # Security options: + + NoNewPrivileges = true; + + AmbientCapabilities = ""; + CapabilityBoundingSet = ""; + + # ProtectClock= adds DeviceAllow=char-rtc r + DeviceAllow = ""; + + LockPersonality = true; + + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = true; + + ProtectClock = true; + ProtectControlGroups = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + RemoveIPC = true; + + RestrictNamespaces = true; + # AF_NETLINK needed because Jellyfin monitors the network connection + RestrictAddressFamilies = [ "AF_NETLINK" "AF_INET" "AF_INET6" ]; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ + "@system-service" + + "~@chown" "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@module" + "~@obsolete" "~@privileged" "~@setuid" + ]; }; }; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 2680b1cc0d3b..ed05882a6343 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -45,7 +45,7 @@ let trusted-substituters = ${toString cfg.trustedBinaryCaches} trusted-public-keys = ${toString cfg.binaryCachePublicKeys} auto-optimise-store = ${boolToString cfg.autoOptimiseStore} - require-sigs = ${if cfg.requireSignedBinaryCaches then "true" else "false"} + require-sigs = ${boolToString cfg.requireSignedBinaryCaches} trusted-users = ${toString cfg.trustedUsers} allowed-users = ${toString cfg.allowedUsers} ${optionalString (!cfg.distributedBuilds) '' diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 1233e5cdd1a9..a4aa470f5bc4 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -43,6 +43,7 @@ let "postgres" "redis" "rspamd" + "rtl_433" "snmp" "surfboard" "tor" @@ -224,6 +225,8 @@ in services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey; })] ++ [(mkIf config.services.rspamd.enable { services.prometheus.exporters.rspamd.url = mkDefault "http://localhost:11334/stat"; + })] ++ [(mkIf config.services.prometheus.exporters.rtl_433.enable { + hardware.rtl-sdr.enable = mkDefault true; })] ++ [(mkIf config.services.nginx.enable { systemd.services.prometheus-nginx-exporter.after = [ "nginx.service" ]; systemd.services.prometheus-nginx-exporter.requires = [ "nginx.service" ]; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix b/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix new file mode 100644 index 000000000000..01e420db3897 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix @@ -0,0 +1,78 @@ +{ config, lib, pkgs, options }: + +let + cfg = config.services.prometheus.exporters.rtl_433; +in +{ + port = 9550; + + extraOpts = let + mkMatcherOptionType = field: description: with lib.types; + listOf (submodule { + options = { + name = lib.mkOption { + type = str; + description = "Name to match."; + }; + "${field}" = lib.mkOption { + type = int; + inherit description; + }; + location = lib.mkOption { + type = str; + description = "Location to match."; + }; + }; + }); + in + { + rtl433Flags = lib.mkOption { + type = lib.types.str; + default = "-C si"; + example = "-C si -R 19"; + description = '' + Flags passed verbatim to rtl_433 binary. + Having <literal>-C si</literal> (the default) is recommended since only Celsius temperatures are parsed. + ''; + }; + channels = lib.mkOption { + type = mkMatcherOptionType "channel" "Channel to match."; + default = []; + example = [ + { name = "Acurite"; channel = 6543; location = "Kitchen"; } + ]; + description = '' + List of channel matchers to export. + ''; + }; + ids = lib.mkOption { + type = mkMatcherOptionType "id" "ID to match."; + default = []; + example = [ + { name = "Nexus"; id = 1; location = "Bedroom"; } + ]; + description = '' + List of ID matchers to export. + ''; + }; + }; + + serviceOpts = { + serviceConfig = { + # rtl-sdr udev rules make supported USB devices +rw by plugdev. + SupplementaryGroups = "plugdev"; + ExecStart = let + matchers = (map (m: + "--channel_matcher '${m.name},${toString m.channel},${m.location}'" + ) cfg.channels) ++ (map (m: + "--id_matcher '${m.name},${toString m.id},${m.location}'" + ) cfg.ids); in '' + ${pkgs.prometheus-rtl_433-exporter}/bin/rtl_433_prometheus \ + -listen ${cfg.listenAddress}:${toString cfg.port} \ + -subprocess "${pkgs.rtl_433}/bin/rtl_433 -F json ${cfg.rtl433Flags}" \ + ${lib.concatStringsSep " \\\n " matchers} \ + ${lib.concatStringsSep " \\\n " cfg.extraFlags} + ''; + }; + }; +} diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix index 2900c37f990f..0b7d5575c11f 100644 --- a/nixos/modules/services/networking/avahi-daemon.nix +++ b/nixos/modules/services/networking/avahi-daemon.nix @@ -86,7 +86,8 @@ in ipv6 = mkOption { type = types.bool; - default = false; + default = config.networking.enableIPv6; + defaultText = "config.networking.enableIPv6"; description = "Whether to use IPv6."; }; diff --git a/nixos/modules/services/networking/babeld.nix b/nixos/modules/services/networking/babeld.nix index e62c74d0069d..90395dbd3c54 100644 --- a/nixos/modules/services/networking/babeld.nix +++ b/nixos/modules/services/networking/babeld.nix @@ -87,9 +87,37 @@ in description = "Babel routing daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - serviceConfig.ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile}"; + serviceConfig = { + ExecStart = "${pkgs.babeld}/bin/babeld -c ${configFile} -I /run/babeld/babeld.pid -S /var/lib/babeld/state"; + CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; + IPAddressAllow = [ "fe80::/64" "ff00::/8" "::1/128" "127.0.0.0/8" ]; + IPAddressDeny = "any"; + LockPersonality = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = true; + ProtectSystem = "strict"; + ProtectClock = true; + ProtectKernelTunables = false; # Couldn't write sysctl: Read-only file system + ProtectKernel |