diff options
Diffstat (limited to 'nixpkgs/nixos/modules')
32 files changed, 997 insertions, 183 deletions
diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix index 4320edf60da5..c36775dd24bb 100644 --- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix +++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix @@ -269,9 +269,9 @@ in { services.udev.extraRules = '' # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. - KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'" - KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \ -f 4); do mknod -m 666 /dev/nvidia$${i} c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) $${i}; done'" - KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'" + KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c 195 255'" + KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \ -f 4); do mknod -m 666 /dev/nvidia$${i} c 195 $${i}; done'" + KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c 195 254'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" ''; diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl index 7d0c5898e23d..85180bf2d1b4 100644 --- a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl @@ -102,22 +102,6 @@ sub cpuManufacturer { return $cpuinfo =~ /^vendor_id\s*:.* $id$/m; } - -# Determine CPU governor to use -if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") { - my $governors = read_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"); - # ondemand governor is not available on sandy bridge or later Intel CPUs - my @desired_governors = ("ondemand", "powersave"); - my $e; - - foreach $e (@desired_governors) { - if (index($governors, $e) != -1) { - last if (push @attrs, "powerManagement.cpuFreqGovernor = lib.mkDefault \"$e\";"); - } - } -} - - # Virtualization support? push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; diff --git a/nixpkgs/nixos/modules/misc/nixpkgs.nix b/nixpkgs/nixos/modules/misc/nixpkgs.nix index bfcae9c7a935..da321a923449 100644 --- a/nixpkgs/nixos/modules/misc/nixpkgs.nix +++ b/nixpkgs/nixos/modules/misc/nixpkgs.nix @@ -187,7 +187,7 @@ in hostPlatform = mkOption { type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform - example = { system = "aarch64-linux"; config = "aarch64-unknown-linux-gnu"; }; + example = { system = "aarch64-linux"; }; # Make sure that the final value has all fields for sake of other modules # referring to this. TODO make `lib.systems` itself use the module system. apply = lib.systems.elaborate; @@ -205,7 +205,7 @@ in buildPlatform = mkOption { type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform default = cfg.hostPlatform; - example = { system = "x86_64-linux"; config = "x86_64-unknown-linux-gnu"; }; + example = { system = "x86_64-linux"; }; # Make sure that the final value has all fields for sake of other modules # referring to this. apply = lib.systems.elaborate; @@ -228,7 +228,7 @@ in localSystem = mkOption { type = types.attrs; # TODO utilize lib.systems.parsedPlatform default = { inherit (cfg) system; }; - example = { system = "aarch64-linux"; config = "aarch64-unknown-linux-gnu"; }; + example = { system = "aarch64-linux"; }; # Make sure that the final value has all fields for sake of other modules # referring to this. TODO make `lib.systems` itself use the module system. apply = lib.systems.elaborate; @@ -262,7 +262,7 @@ in crossSystem = mkOption { type = types.nullOr types.attrs; # TODO utilize lib.systems.parsedPlatform default = null; - example = { system = "aarch64-linux"; config = "aarch64-unknown-linux-gnu"; }; + example = { system = "aarch64-linux"; }; description = lib.mdDoc '' Systems with a recently generated `hardware-configuration.nix` may instead specify *only* {option}`nixpkgs.buildPlatform`, diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix index 16541be4e120..c5c3c0d4719a 100644 --- a/nixpkgs/nixos/modules/module-list.nix +++ b/nixpkgs/nixos/modules/module-list.nix @@ -268,6 +268,7 @@ ./programs/usbtop.nix ./programs/vim.nix ./programs/wavemon.nix + ./programs/wayland/cardboard.nix ./programs/wayland/river.nix ./programs/wayland/sway.nix ./programs/wayland/waybar.nix @@ -626,6 +627,7 @@ ./services/matrix/matrix-sliding-sync.nix ./services/matrix/synapse.nix ./services/misc/airsonic.nix + ./services/misc/amazon-ssm-agent.nix ./services/misc/ananicy.nix ./services/misc/ankisyncd.nix ./services/misc/apache-kafka.nix @@ -742,7 +744,6 @@ ./services/misc/spice-autorandr.nix ./services/misc/spice-vdagentd.nix ./services/misc/spice-webdavd.nix - ./services/misc/ssm-agent.nix ./services/misc/sssd.nix ./services/misc/subsonic.nix ./services/misc/sundtek.nix @@ -908,6 +909,7 @@ ./services/networking/eternal-terminal.nix ./services/networking/expressvpn.nix ./services/networking/fakeroute.nix + ./services/networking/fastnetmon-advanced.nix ./services/networking/ferm.nix ./services/networking/firefox-syncserver.nix ./services/networking/fireqos.nix @@ -1048,6 +1050,7 @@ ./services/networking/redsocks.nix ./services/networking/resilio.nix ./services/networking/robustirc-bridge.nix + ./services/networking/rosenpass.nix ./services/networking/routedns.nix ./services/networking/rpcbind.nix ./services/networking/rxe.nix @@ -1269,6 +1272,7 @@ ./services/web-apps/kavita.nix ./services/web-apps/keycloak.nix ./services/web-apps/komga.nix + ./services/web-apps/lanraragi.nix ./services/web-apps/lemmy.nix ./services/web-apps/limesurvey.nix ./services/web-apps/mainsail.nix diff --git a/nixpkgs/nixos/modules/programs/browserpass.nix b/nixpkgs/nixos/modules/programs/browserpass.nix index abd99056ff3b..a9670a37e618 100644 --- a/nixpkgs/nixos/modules/programs/browserpass.nix +++ b/nixpkgs/nixos/modules/programs/browserpass.nix @@ -27,6 +27,6 @@ with lib; "opt/brave/native-messaging-hosts/${appId}".source = source "hosts/chromium"; "opt/brave/policies/managed/${appId}".source = source "policies/chromium"; }; - programs.firefox.wrapperConfig.enableBrowserpass = true; + programs.firefox.nativeMessagingHosts.packages = [ pkgs.browserpass ]; }; } diff --git a/nixpkgs/nixos/modules/programs/firefox.nix b/nixpkgs/nixos/modules/programs/firefox.nix index 813e0e0105f6..85f47530cf5a 100644 --- a/nixpkgs/nixos/modules/programs/firefox.nix +++ b/nixpkgs/nixos/modules/programs/firefox.nix @@ -5,8 +5,6 @@ with lib; let cfg = config.programs.firefox; - nmh = cfg.nativeMessagingHosts; - policyFormat = pkgs.formats.json { }; organisationInfo = '' @@ -17,6 +15,50 @@ let given control of your browser, unless of course they also control your NixOS configuration. ''; + + # deprecated per-native-messaging-host options + nmhOptions = { + browserpass = { + name = "Browserpass"; + package = pkgs.browserpass; + }; + bukubrow = { + name = "Bukubrow"; + package = pkgs.bukubrow; + }; + euwebid = { + name = "Web eID"; + package = pkgs.web-eid-app; + }; + ff2mpv = { + name = "ff2mpv"; + package = pkgs.ff2mpv; + }; + fxCast = { + name = "fx_cast"; + package = pkgs.fx-cast-bridge; + }; + gsconnect = { + name = "GSConnect"; + package = pkgs.gnomeExtensions.gsconnect; + }; + jabref = { + name = "JabRef"; + package = pkgs.jabref; + }; + passff = { + name = "PassFF"; + package = pkgs.passff-host; + }; + tridactyl = { + name = "Tridactyl"; + package = pkgs.tridactyl-native; + }; + ugetIntegrator = { + name = "Uget Integrator"; + package = pkgs.uget-integrator; + }; + }; in { options.programs.firefox = { @@ -204,46 +246,31 @@ in ''; }; - nativeMessagingHosts = mapAttrs (_: v: mkEnableOption (mdDoc v)) { - browserpass = "Browserpass support"; - bukubrow = "Bukubrow support"; - euwebid = "Web eID support"; - ff2mpv = "ff2mpv support"; - fxCast = "fx_cast support"; - gsconnect = "GSConnect support"; - jabref = "JabRef support"; - passff = "PassFF support"; - tridactyl = "Tridactyl support"; - ugetIntegrator = "Uget Integrator support"; - }; + nativeMessagingHosts = ({ + packages = mkOption { + type = types.listOf types.package; + default = []; + description = mdDoc '' + Additional packages containing native messaging hosts that should be made available to Firefox extensions. + ''; + }; + }) // (mapAttrs (k: v: mkEnableOption (mdDoc "${v.name} support")) nmhOptions); }; - config = mkIf cfg.enable { + config = let + forEachEnabledNmh = fn: flatten (mapAttrsToList (k: v: lib.optional cfg.nativeMessagingHosts.${k} (fn k v)) nmhOptions); + in mkIf cfg.enable { + warnings = forEachEnabledNmh (k: v: + "The `programs.firefox.nativeMessagingHosts.${k}` option is deprecated, " + + "please add `${v.package.pname}` to `programs.firefox.nativeMessagingHosts.packages` instead." + ); + programs.firefox.nativeMessagingHosts.packages = forEachEnabledNmh (_: v: v.package); + environment.systemPackages = [ (cfg.package.override (old: { - extraPrefs = cfg.autoConfig; - extraNativeMessagingHosts = - old.extraNativeMessagingHosts or [] - ++ optional nmh.ff2mpv pkgs.ff2mpv - ++ optional nmh.euwebid pkgs.web-eid-app - ++ optional nmh.gsconnect pkgs.gnomeExtensions.gsconnect - ++ optional nmh.jabref pkgs.jabref - ++ optional nmh.passff pkgs.passff-host; - cfg = let - # copy-pasted from the wrapper; TODO: figure out fix - applicationName = cfg.package.binaryName or (lib.getName cfg.package); - - oldCfg = old.cfg or {}; - nixpkgsConfig = pkgs.config.${applicationName} or {}; - optionConfig = cfg.wrapperConfig; - nmhConfig = { - enableBrowserpass = nmh.browserpass; - enableBukubrow = nmh.bukubrow; - enableTridactylNative = nmh.tridactyl; - enableUgetIntegrator = nmh.ugetIntegrator; - enableFXCastBridge = nmh.fxCast; - }; - in oldCfg // nixpkgsConfig // optionConfig // nmhConfig; + extraPrefsFiles = old.extraPrefsFiles or [] ++ [(pkgs.writeText "firefox-autoconfig.js" cfg.autoConfig)]; + nativeMessagingHosts = old.nativeMessagingHosts or [] ++ cfg.nativeMessagingHosts.packages; + cfg = (old.cfg or {}) // cfg.wrapperConfig; })) ]; diff --git a/nixpkgs/nixos/modules/programs/wayland/cardboard.nix b/nixpkgs/nixos/modules/programs/wayland/cardboard.nix new file mode 100644 index 000000000000..262c698c74ba --- /dev/null +++ b/nixpkgs/nixos/modules/programs/wayland/cardboard.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.cardboard; +in +{ + meta.maintainers = with lib.maintainers; [ AndersonTorres ]; + + options.programs.cardboard = { + enable = lib.mkEnableOption (lib.mdDoc "cardboard"); + + package = lib.mkPackageOptionMD pkgs "cardboard" { }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + environment.systemPackages = [ cfg.package ]; + + # To make a cardboard session available for certain DMs like SDDM + services.xserver.displayManager.sessionPackages = [ cfg.package ]; + } + (import ./wayland-session.nix { inherit lib pkgs; }) + ]); +} diff --git a/nixpkgs/nixos/modules/security/acme/default.nix b/nixpkgs/nixos/modules/security/acme/default.nix index f8e17bc71ee1..932bf3e79115 100644 --- a/nixpkgs/nixos/modules/security/acme/default.nix +++ b/nixpkgs/nixos/modules/security/acme/default.nix @@ -184,6 +184,7 @@ let certToConfig = cert: data: let acmeServer = data.server; useDns = data.dnsProvider != null; + useDnsOrS3 = useDns || data.s3Bucket != null; destPath = "/var/lib/acme/${cert}"; selfsignedDeps = optionals (cfg.preliminarySelfsigned) [ "acme-selfsigned-${cert}.service" ]; @@ -219,7 +220,8 @@ let [ "--dns" data.dnsProvider ] ++ optionals (!data.dnsPropagationCheck) [ "--dns.disable-cp" ] ++ optionals (data.dnsResolver != null) [ "--dns.resolvers" data.dnsResolver ] - ) else if data.listenHTTP != null then [ "--http" "--http.port" data.listenHTTP ] + ) else if data.s3Bucket != null then [ "--http" "--http.s3-bucket" data.s3Bucket ] + else if data.listenHTTP != null then [ "--http" "--http.port" data.listenHTTP ] else [ "--http" "--http.webroot" data.webroot ]; commonOpts = [ @@ -362,13 +364,12 @@ let "/var/lib/acme/.lego/${cert}/${certDir}:/tmp/certificates" ]; - # Only try loading the environmentFile if the dns challenge is enabled - EnvironmentFile = mkIf useDns data.environmentFile; + EnvironmentFile = mkIf useDnsOrS3 data.environmentFile; - Environment = mkIf useDns + Environment = mkIf useDnsOrS3 (mapAttrsToList (k: v: ''"${k}=%d/${k}"'') data.credentialFiles); - LoadCredential = mkIf useDns + LoadCredential = mkIf useDnsOrS3 (mapAttrsToList (k: v: "${k}:${v}") data.credentialFiles); # Run as root (Prefixed with +) @@ -755,6 +756,15 @@ let ''; }; + s3Bucket = mkOption { + type = types.nullOr types.str; + default = null; + example = "acme"; + description = lib.mdDoc '' + S3 bucket name to use for HTTP-01 based challenges. Challenges will be written to the S3 bucket. + ''; + }; + inheritDefaults = mkOption { default = true; example = true; @@ -928,35 +938,20 @@ in { and remove the wildcard from the path. ''; } - { - assertion = data.dnsProvider == null || data.webroot == null; - message = '' - Options `security.acme.certs.${cert}.dnsProvider` and - `security.acme.certs.${cert}.webroot` are mutually exclusive. - ''; - } - { - assertion = data.webroot == null || data.listenHTTP == null; - message = '' - Options `security.acme.certs.${cert}.webroot` and - `security.acme.certs.${cert}.listenHTTP` are mutually exclusive. - ''; - } - { - assertion = data.listenHTTP == null || data.dnsProvider == null; + (let exclusiveAttrs = { + inherit (data) dnsProvider webroot listenHTTP s3Bucket; + }; in { + assertion = lib.length (lib.filter (x: x != null) (builtins.attrValues exclusiveAttrs)) == 1; message = '' - Options `security.acme.certs.${cert}.listenHTTP` and - `security.acme.certs.${cert}.dnsProvider` are mutually exclusive. + Exactly one of the options + `security.acme.certs.${cert}.dnsProvider`, + `security.acme.certs.${cert}.webroot`, + `security.acme.certs.${cert}.listenHTTP` and + `security.acme.certs.${cert}.s3Bucket` + is required. + Current values: ${(lib.generators.toPretty {} exclusiveAttrs)}. ''; - } - { - assertion = data.dnsProvider != null || data.webroot != null || data.listenHTTP != null; - message = '' - One of `security.acme.certs.${cert}.dnsProvider`, - `security.acme.certs.${cert}.webroot`, or - `security.acme.certs.${cert}.listenHTTP` must be provided. - ''; - } + }) { assertion = all (hasSuffix "_FILE") (attrNames data.credentialFiles); message = '' diff --git a/nixpkgs/nixos/modules/services/backup/bacula.nix b/nixpkgs/nixos/modules/services/backup/bacula.nix index 0acbf1b3eabb..5a75a46e5259 100644 --- a/nixpkgs/nixos/modules/services/backup/bacula.nix +++ b/nixpkgs/nixos/modules/services/backup/bacula.nix @@ -15,16 +15,16 @@ let Client { Name = "${fd_cfg.name}"; FDPort = ${toString fd_cfg.port}; - WorkingDirectory = "${libDir}"; - Pid Directory = "/run"; + WorkingDirectory = ${libDir}; + Pid Directory = /run; ${fd_cfg.extraClientConfig} } ${concatStringsSep "\n" (mapAttrsToList (name: value: '' Director { Name = "${name}"; - Password = "${value.password}"; - Monitor = "${value.monitor}"; + Password = ${value.password}; + Monitor = ${value.monitor}; } '') fd_cfg.director)} @@ -41,8 +41,8 @@ let Storage { Name = "${sd_cfg.name}"; SDPort = ${toString sd_cfg.port}; - WorkingDirectory = "${libDir}"; - Pid Directory = "/run"; + WorkingDirectory = ${libDir}; + Pid Directory = /run; ${sd_cfg.extraStorageConfig} } @@ -50,8 +50,8 @@ let Autochanger { Name = "${name}"; Device = ${concatStringsSep ", " (map (a: "\"${a}\"") value.devices)}; - Changer Device = "${value.changerDevice}"; - Changer Command = "${value.changerCommand}"; + Changer Device = ${value.changerDevice}; + Changer Command = ${value.changerCommand}; ${value.extraAutochangerConfig} } '') sd_cfg.autochanger)} @@ -59,8 +59,8 @@ let ${concatStringsSep "\n" (mapAttrsToList (name: value: '' Device { Name = "${name}"; - Archive Device = "${value.archiveDevice}"; - Media Type = "${value.mediaType}"; + Archive Device = ${value.archiveDevice}; + Media Type = ${value.mediaType}; ${value.extraDeviceConfig} } '') sd_cfg.device)} @@ -68,8 +68,8 @@ let ${concatStringsSep "\n" (mapAttrsToList (name: value: '' Director { Name = "${name}"; - Password = "${value.password}"; - Monitor = "${value.monitor}"; + Password = ${value.password}; + Monitor = ${value.monitor}; } '') sd_cfg.director)} @@ -85,18 +85,18 @@ let '' Director { Name = "${dir_cfg.name}"; - Password = "${dir_cfg.password}"; + Password = ${dir_cfg.password}; DirPort = ${toString dir_cfg.port}; - Working Directory = "${libDir}"; - Pid Directory = "/run/"; - QueryFile = "${pkgs.bacula}/etc/query.sql"; + Working Directory = ${libDir}; + Pid Directory = /run/; + QueryFile = ${pkgs.bacula}/etc/query.sql; ${dir_cfg.extraDirectorConfig} } Catalog { - Name = "PostgreSQL"; - dbname = "bacula"; - user = "bacula"; + Name = PostgreSQL; + dbname = bacula; + user = bacula; } Messages { @@ -533,7 +533,7 @@ in { }; }; - services.postgresql.enable = dir_cfg.enable == true; + services.postgresql.enable = lib.mkIf dir_cfg.enable true; systemd.services.bacula-dir = mkIf dir_cfg.enable { after = [ "network.target" "postgresql.service" ]; diff --git a/nixpkgs/nixos/modules/services/databases/ferretdb.nix b/nixpkgs/nixos/modules/services/databases/ferretdb.nix index 45f822d64691..ab55e22bf214 100644 --- a/nixpkgs/nixos/modules/services/databases/ferretdb.nix +++ b/nixpkgs/nixos/modules/services/databases/ferretdb.nix @@ -30,7 +30,7 @@ in }; description = '' Additional configuration for FerretDB, see - <https://docs.ferretdb.io/flags/> + <https://docs.ferretdb.io/configuration/flags/> for supported values. ''; }; diff --git a/nixpkgs/nixos/modules/services/desktops/gnome/gnome-browser-connector.nix b/nixpkgs/nixos/modules/services/desktops/gnome/gnome-browser-connector.nix index d18e303891e4..4f680eabbe15 100644 --- a/nixpkgs/nixos/modules/services/desktops/gnome/gnome-browser-connector.nix +++ b/nixpkgs/nixos/modules/services/desktops/gnome/gnome-browser-connector.nix @@ -42,6 +42,6 @@ in services.dbus.packages = [ pkgs.gnome-browser-connector ]; - programs.firefox.wrapperConfig.enableGnomeExtensions = true; + programs.firefox.nativeMessagingHosts.packages = [ pkgs.gnome-browser-connector ]; }; } diff --git a/nixpkgs/nixos/modules/services/home-automation/esphome.nix b/nixpkgs/nixos/modules/services/home-automation/esphome.nix index d7dbb6f0b90e..080c8876382f 100644 --- a/nixpkgs/nixos/modules/services/home-automation/esphome.nix +++ b/nixpkgs/nixos/modules/services/home-automation/esphome.nix @@ -112,7 +112,7 @@ in ProtectKernelModules = true; ProtectKernelTunables = true; ProtectProc = "invisible"; - ProcSubset = "pid"; + ProcSubset = "all"; # Using "pid" breaks bwrap ProtectSystem = "strict"; #RemoveIPC = true; # Implied by DynamicUser RestrictAddressFamilies = [ diff --git a/nixpkgs/nixos/modules/services/home-automation/home-assistant.nix b/nixpkgs/nixos/modules/services/home-automation/home-assistant.nix index 99bac86a8e9a..0e6fa65667af 100644 --- a/nixpkgs/nixos/modules/services/home-automation/home-assistant.nix +++ b/nixpkgs/nixos/modules/services/home-automation/home-assistant.nix @@ -12,7 +12,7 @@ let # We post-process the result to add support for YAML functions, like secrets or includes, see e.g. # https://www.home-assistant.io/docs/configuration/secrets/ filteredConfig = lib.converge (lib.filterAttrsRecursive (_: v: ! elem v [ null ])) cfg.config or {}; - configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } '' + configFile = pkgs.runCommandLocal "configuration.yaml" { } '' cp ${format.generate "configuration.yaml" filteredConfig} $out sed -i -e "s/'\!\([a-z_]\+\) \(.*\)'/\!\1 \2/;s/^\!\!/\!/;" $out ''; diff --git a/nixpkgs/nixos/modules/services/matrix/synapse.nix b/nixpkgs/nixos/modules/services/matrix/synapse.nix index b38b35361cf0..12e27ef26ff3 100644 --- a/nixpkgs/nixos/modules/services/matrix/synapse.nix +++ b/nixpkgs/nixos/modules/services/matrix/synapse.nix @@ -60,7 +60,6 @@ let ++ lib.optional (cfg.settings ? oidc_providers) "oidc" ++ lib.optional (cfg.settings ? jwt_config) "jwt" ++ lib.optional (cfg.settings ? saml2_config) "saml2" - ++ lib.optional (cfg.settings ? opentracing) "opentracing" ++ lib.optional (cfg.settings ? redis) "redis" ++ lib.optional (cfg.settings ? sentry) "sentry" ++ lib.optional (cfg.settings ? user_directory) "user-search" @@ -334,7 +333,6 @@ in { [ "cache-memory" # Provide statistics about caching memory consumption "jwt" # JSON Web Token authentication - "opentracing" # End-to-end tracing support using Jaeger "oidc" # OpenID Connect authentication "postgres" # PostgreSQL database backend "redis" # Redis support for the replication stream between worker processes diff --git a/nixpkgs/nixos/modules/services/misc/ssm-agent.nix b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix index d1f371c2bd61..0be79e759c31 100644 --- a/nixpkgs/nixos/modules/services/misc/ssm-agent.nix +++ b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix @@ -2,7 +2,7 @@ with lib; let - cfg = config.services.ssm-agent; + cfg = config.services.amazon-ssm-agent; # The SSM agent doesn't pay attention to our /etc/os-release yet, and the lsb-release tool # in nixpkgs doesn't seem to work properly on NixOS, so let's just fake the two fields SSM @@ -16,19 +16,24 @@ let esac ''; in { - options.services.ssm-agent = { - enable = mkEnableOption (lib.mdDoc "AWS SSM agent"); + imports = [ + (mkRenamedOptionModule [ "services" "ssm-agent" "enable" ] [ "services" "amazon-ssm-agent" "enable" ]) + (mkRenamedOptionModule [ "services" "ssm-agent" "package" ] [ "services" "amazon-ssm-agent" "package" ]) + ]; + + options.services.amazon-ssm-agent = { + enable = mkEnableOption (lib.mdDoc "Amazon SSM agent"); package = mkOption { type = types.path; - description = lib.mdDoc "The SSM agent package to use"; - default = pkgs.ssm-agent.override { overrideEtc = false; }; - defaultText = literalExpression "pkgs.ssm-agent.override { overrideEtc = false; }"; + description = lib.mdDoc "The Amazon SSM agent package to use"; + default = pkgs.amazon-ssm-agent.override { overrideEtc = false; }; + defaultText = literalExpression "pkgs.amazon-ssm-agent.override { overrideEtc = false; }"; }; }; config = mkIf cfg.enable { - systemd.services.ssm-agent = { + systemd.services.amazon-ssm-agent = { inherit (cfg.package.meta) description; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.nix b/nixpkgs/nixos/modules/services/misc/forgejo.nix index b2920981efbd..90b5f16f4189 100644 --- a/nixpkgs/nixos/modules/services/misc/forgejo.nix +++ b/nixpkgs/nixos/modules/services/misc/forgejo.nix @@ -632,6 +632,8 @@ in }; }; + services.openssh.settings.AcceptEnv = mkIf (!cfg.settings.START_SSH_SERVER or false) "GIT_PROTOCOL"; + users.users = mkIf (cfg.user == "forgejo") { forgejo = { home = cfg.stateDir; diff --git a/nixpkgs/nixos/modules/services/monitoring/munin.nix b/nixpkgs/nixos/modules/services/monitoring/munin.nix index f37f2689927e..90a51181ac30 100644 --- a/nixpkgs/nixos/modules/services/monitoring/munin.nix +++ b/nixpkgs/nixos/modules/services/monitoring/munin.nix @@ -83,42 +83,47 @@ let # Copy one Munin plugin into the Nix store with a specific name. # This is suitable for use with plugins going directly into /etc/munin/plugins, # i.e. munin.extraPlugins. - internOnePlugin = name: path: + internOnePlugin = { name, path }: "cp -a '${path}' '${name}'"; # Copy an entire tree of Munin plugins into a single directory in the Nix - # store, with no renaming. - # This is suitable for use with munin-node-configure --suggest, i.e. - # munin.extraAutoPlugins. - internManyPlugins = name: path: + # store, with no renaming. The output is suitable for use with + # munin-node-configure --suggest, i.e. munin.extraAutoPlugins. + # Note that this flattens the input; this is intentional, as + # munin-node-configure won't recurse into subdirectories. + internManyPlugins = path: "find '${path}' -type f -perm /a+x -exec cp -a -t . '{}' '+'"; # Use the appropriate intern-fn to copy the plugins into the store and patch # them afterwards in an attempt to get them to run on NixOS. + # This is a bit hairy because we can't just fix shebangs; lots of munin plugins + # hardcode paths like /sbin/mount rather than trusting $PATH, so we have to + # look for and update those throughout the script. At the same time, if the + # plugin comes from a package that is already nixified, we don't want to + # rewrite paths like /nix/store/foo/sbin/mount. + # For now we make the simplifying assumption that no file will contain lines + # which mix store paths and FHS paths, and thus run our substitution only on + # lines which do not contain store paths. internAndFixPlugins = name: intern-fn: paths: pkgs.runCommand name {} '' mkdir -p "$out" cd "$out" - ${lib.concatStringsSep "\n" - (lib.attrsets.mapAttrsToList intern-fn paths)} + ${lib.concatStringsSep "\n" (map intern-fn paths)} chmod -R u+w . - find . -type f -exec sed -E -i ' - s,(/usr)?/s?bin/,/run/current-system/sw/bin/,g - ' '{}' '+' + ${pkgs.findutils}/bin/find . -type f -exec ${pkgs.gnused}/bin/sed -E -i " + \%''${NIX_STORE}/%! s,(/usr)?/s?bin/,/run/current-system/sw/bin/,g + " '{}' '+' ''; # TODO: write a derivation for munin-contrib, so that for contrib plugins # you can just refer to them by name rather than needing to include a copy # of munin-contrib in your nixos configuration. extraPluginDir = internAndFixPlugins "munin-extra-plugins.d" - internOnePlugin nodeCfg.extraPlugins; + internOnePlugin + (lib.attrsets.mapAttrsToList (k: v: { name = k; path = v; }) nodeCfg.extraPlugins); extraAutoPluginDir = internAndFixPlugins "munin-extra-auto-plugins.d" - internManyPlugins - (builtins.listToAttrs - (map - (path: { name = baseNameOf path; value = path; }) - nodeCfg.extraAutoPlugins)); + internManyPlugins nodeCfg.extraAutoPlugins; customStaticDir = pkgs.runCommand "munin-custom-static-data" {} '' cp -a "${pkgs.munin}/etc/opt/munin/static" "$out" diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/kea.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/kea.nix index ed33c72f644f..8b1cd47d0a40 100644 --- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/kea.nix +++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/kea.nix @@ -15,8 +15,8 @@ in { type = types.listOf types.str; example = literalExpression '' [ - "/run/kea/kea-dhcp4.socket" - "/run/kea/kea-dhcp6.socket" + "/run/kea-dhcp4/kea-dhcp4.socket" + "/run/kea-dhcp6/kea-dhcp6.socket" ] ''; description = lib.mdDoc '' diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/knot.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/knot.nix index a73425b37da7..775848750803 100644 --- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/knot.nix +++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/knot.nix @@ -8,9 +8,9 @@ in { port = 9433; extraOpts = { knotLibraryPath = mkOption { - type = types.str; - default = "${pkgs.knot-dns.out}/lib/libknot.so"; - defaultText = literalExpression ''"''${pkgs.knot-dns.out}/lib/libknot.so"''; + type = types.nullOr types.str; + default = null; + example = literalExpression ''"''${pkgs.knot-dns.out}/lib/libknot.so"''; description = lib.mdDoc '' Path to the library of `knot-dns`. ''; @@ -25,7 +25,7 @@ in { }; knotSocketTimeout = mkOption { - type = types.int; + type = types.ints.positive; default = 2000; description = lib.mdDoc '' Timeout in seconds. @@ -33,17 +33,22 @@ in { }; }; serviceOpts = { + path = with pkgs; [ + procps + ]; serviceConfig = { ExecStart = '' - ${pkgs.prometheus-knot-exporter}/bin/knot_exporter \ + ${pkgs.prometheus-knot-exporter}/bin/knot-exporter \ --web-listen-addr ${cfg.listenAddress} \ --web-listen-port ${toString cfg.port} \ - --knot-library-path ${cfg.knotLibraryPath} \ --knot-socket-path ${cfg.knotSocketPath} \ --knot-socket-timeout ${toString cfg.knotSocketTimeout} \ + ${lib.optionalString (cfg.knotLibraryPath != null) "--knot-library-path ${cfg.knotLibraryPath}"} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; - SupplementaryGroups = [ "knot" ]; + SupplementaryGroups = [ + "knot" + ]; RestrictAddressFamilies = [ # Need AF_UNIX to collect data "AF_UNIX" diff --git a/nixpkgs/nixos/modules/services/networking/fastnetmon-advanced.nix b/nixpkgs/nixos/modules/services/networking/fastnetmon-advanced.nix new file mode 100644 index 000000000000..26e8ad8b76d9 --- /dev/null +++ b/nixpkgs/nixos/modules/services/networking/fastnetmon-advanced.nix @@ -0,0 +1,222 @@ +{ config, lib, pkgs, ... }: + +let + # Background information: FastNetMon requires a MongoDB to start. This is because + # it uses MongoDB to store its configuration. That is, in a normal setup there is + # one collection with one document. + # To provide declarative configuration in our NixOS module, this database is + # completely emptied and replaced on each boot by the fastnetmon-setup service + # using the configuration backup functionality. + + cfg = config.services.fastnetmon-advanced; + settingsFormat = pkgs.formats.yaml { }; + + # obtain the default configs by starting up ferretdb and fcli in a derivation + default_configs = pkgs.runCommand "default-configs" { + nativeBuildInputs = [ + pkgs.ferretdb + pkgs.fastnetmon-advanced # for fcli + pkgs.proot + ]; + } '' + mkdir ferretdb fastnetmon $out + FERRETDB_TELEMETRY="disable" FERRETDB_HANDLER="sqlite" FERRETDB_STATE_DIR="$PWD/ferretdb" FERRETDB_SQLITE_URL="file:$PWD/ferretdb/" ferretdb & + + cat << EOF > fastnetmon/fastnetmon.conf + ${builtins.toJSON { + mongodb_username = ""; + }} + EOF + proot -b fastnetmon:/etc/fastnetmon -0 fcli create_configuration + proot -b fastnetmon:/etc/fastnetmon -0 fcli set bgp default + proot -b fastnetmon:/etc/fastnetmon -0 fcli export_configuration backup.tar + tar -C $out --no-same-owner -xvf backup.tar + ''; + + # merge the user configs into the default configs + config_tar = pkgs.runCommand "fastnetmon-config.tar" { + nativeBuildInputs = with pkgs; [ jq ]; + } '' + jq -s add ${default_configs}/main.json ${pkgs.writeText "main-add.json" (builtins.toJSON cfg.settings)} > main.json + mkdir hostgroup + ${lib.concatImapStringsSep "\n" (pos: hostgroup: '' + jq -s add ${default_configs}/hostgroup/0.json ${pkgs.writeText "hostgroup-${toString (pos - 1)}-add.json" (builtins.toJSON hostgroup)} > hostgroup/${toString (pos - 1)}.json + '') hostgroups} + mkdir bgp + ${lib.concatImapStringsSep "\n" (pos: bgp: '' + jq -s add ${default_configs}/bgp/0.json ${pkgs.writeText "bgp-${toString (pos - 1)}-add.json" (builtins.toJSON bgp)} > bgp/${toString (pos - 1)}.json + '') bgpPeers} + tar -cf $out main.json ${lib.concatImapStringsSep " " (pos: _: "hostgroup/${toString (pos - 1)}.json") hostgroups} ${lib.concatImapStringsSep " " (pos: _: "bgp/${toString (pos - 1)}.json") bgpPeers} + ''; + + hostgroups = lib.mapAttrsToList (name: hostgroup: { inherit name; } // hostgroup) cfg.hostgroups; + bgpPeers = lib.mapAttrsToList (name: bgpPeer: { inherit name; } // bgpPeer) cfg.bgpPeers; + +in { + options.services.fastnetmon-advanced = with lib; { + enable = mkEnableOption "the fastnetmon-advanced DDoS Protection daemon"; + + settings = mkOption { + description = '' + Extra configuration options to declaratively load into FastNetMon Advanced. + + See the [FastNetMon Advanced Configuration options reference](https://fastnetmon.com/docs-fnm-advanced/fastnetmon-advanced-configuration-options/) for more details. + ''; + type = settingsFormat.type; + default = {}; + example = literalExpression '' + { + networks_list = [ "192.0.2.0/24" ]; + gobgp = true; + gobgp_flow_spec_announces = true; + } + ''; + }; + hostgroups = mkOption { + description = "Hostgroups to declaratively load into FastNetMon Advanced"; + type = types.attrsOf settingsFormat.type; + default = {}; + }; + bgpPeers = mkOption { + description = "BGP Peers to declaratively load into FastNetMon Advanced"; + type = types.attrsOf settingsFormat.type; + default = {}; + }; + + enableAdvancedTrafficPersistence = mkOption { + description = "Store historical flow data in clickhouse"; + type = types.bool; + default = false; + }; + + traffic_db.settings = mkOption { + type = settingsFormat.type; + description = "Additional settings for /etc/fastnetmon/traffic_db.conf"; + }; + }; + + config = lib.mkMerge [ (lib.mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + fastnetmon-advanced # for fcli + ]; + + environment.etc."fastnetmon/license.lic".source = "/var/lib/fastnetmon/license.lic"; + environment.etc."fastnetmon/gobgpd.conf".source = "/run/fastnetmon/gobgpd.conf"; + environment.etc."fastnetmon/fastnetmon.conf".source = pkgs.writeText "fastnetmon.conf" (builtins.toJSON { + mongodb_username = ""; + }); + + services.ferretdb.enable = true; + + systemd.services.fastnetmon-setup = { + wantedBy = [ "multi-user.target" ]; + after = [ "ferretdb.service" ]; + path = with pkgs; [ fastnetmon-advanced config.systemd.package ]; + script = '' + fcli create_configuration + fcli delete hostgroup global + fcli import_configuration ${config_tar} + systemctl --no-block try-restart fastnetmon + ''; + serviceConfig.Type = "oneshot"; + }; + + systemd.services.fastnetmon = { + wantedBy = [ "multi-user.target" ]; + after = [ "ferretdb.service" "fastnetmon-setup.service" "polkit.service" ]; + path = with pkgs; [ iproute2 ]; + unitConfig = { + # Disable logic which shuts service when we do too many restarts + # We do restarts from sudo fcli commit and it's expected that we may have many restarts + # Details: https://github.com/systemd/systemd/issues/2416 + StartLimitInterval = 0; + }; + serviceConfig = { + ExecStart = "${pkgs.fastnetmon-advanced}/bin/fastnetmon --log_to_console"; + + LimitNOFILE = 65535; + # Restart service when it fails due to any reasons, we need to keep processing traffic no matter what happened + Restart= "on-failure"; + RestartSec= "5s"; + + DynamicUser = true; + CacheDirectory = "fastnetmon"; + RuntimeDirectory = "fastnetmon"; # for gobgpd config + StateDirectory = "fastnetmon"; # for license file + }; + }; + + security.polkit.enable = true; + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.systemd1.manage-units" && + subject.isInGroup("fastnetmon")) { + if (action.lookup("unit") == "gobgp.service") { + var verb = action.lookup("verb"); + if (verb == "start" || verb == "stop" || verb == "restart") { + return polkit.Result.YES; + } + } + } + }); + ''; + + # We don't use the existing gobgp NixOS module and package, because the gobgp + # version might not be compatible with fastnetmon. Also, the service name + # _must_ be 'gobgp' and not 'gobgpd', so that fastnetmon can reload the config. + systemd.services.gobgp = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "GoBGP Routing Daemon"; + unitConfig = { + ConditionPathExists = "/run/fastnetmon/gobgpd.conf"; + }; + serviceConfig = { + Type = "notify"; + ExecStartPre = "${pkgs.fastnetmon-advanced}/bin/fnm-gobgpd -f /run/fastnetmon/gobgpd.conf -d"; + SupplementaryGroups = [ "fastnetmon" ]; + ExecStart = "${pkgs.fastnetmon-advanced}/bin/fnm-gobgpd -f /run/fastnetmon/gobgpd.conf --sdnotify"; + ExecReload = "${pkgs.fastnetmon-advanced}/bin/fnm-gobgpd -r"; + DynamicUser = true; + AmbientCapabilities = "cap_net_bind_service"; + }; + }; + }) + + (lib.mkIf (cfg.enable && cfg.enableAdvancedTrafficPersistence) { + ## Advanced Traffic persistence + ## https://fastnetmon.com/docs-fnm-advanced/fastnetmon-advanced-traffic-persistency/ + + services.clickhouse.enable = true; + + services.fastnetmon-advanced.settings.traffic_db = true; + + services.fastnetmon-advanced.traffic_db.settings = { + clickhouse_batch_size = lib.mkDefault 1000; + clickhouse_batch_delay = lib.mkDefault 1; + traffic_db_host = lib.mkDefault "127.0.0.1"; + traffic_db_port = lib.mkDefault 8100; + clickhouse_host = lib.mkDefault "127.0.0.1"; + clickhouse_port = lib.mkDefault 9000; + clickhouse_user = lib.mkDefault "default"; + clickhouse_password = lib.mkDefault ""; + }; + environment.etc."fastnetmon/traffic_db.conf".text = builtins.toJSON cfg.traffic_db.settings; + + systemd.services.traffic_db = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${pkgs.fastnetmon-advanced}/bin/traffic_db"; + # Restart service when it fails due to any reasons, we need to keep processing traffic no matter what happened + Restart= "on-failure"; + RestartSec= "5s"; + + DynamicUser = true; + }; + }; + + }) ]; + + meta.maintainers = lib.teams.wdz.members; +} diff --git a/nixpkgs/nixos/modules/services/networking/kea.nix b/nixpkgs/nixos/modules/services/networking/kea.nix index 945f4113bd47..2f922a026a3a 100644 --- a/nixpkgs/nixos/modules/services/networking/kea.nix +++ b/nixpkgs/nixos/modules/services/networking/kea.nix @@ -254,7 +254,6 @@ in DynamicUser = true; User = "kea"; ConfigurationDirectory = "kea"; - RuntimeDirectory = "kea"; StateDirectory = "kea"; UMask = "0077"; }; @@ -289,8 +288,8 @@ in ]; environment = { - KEA_PIDFILE_DIR = "/run/kea"; - KEA_LOCKFILE_DIR = "/run/kea"; + KEA_PIDFILE_DIR = "/run/kea-ctrl-agent"; + KEA_LOCKFILE_DIR = "/run/kea-ctrl-agent"; }; restartTriggers = [ @@ -301,6 +300,7 @@ in ExecStart = "${package}/bin/kea-ctrl-agent -c /etc/kea/ctrl-agent.conf ${lib.escapeShellArgs cfg.ctrl-agent.extraArgs}"; KillMode = "process"; Restart = "on-failure"; + RuntimeDirectory = "kea-ctrl-agent"; } // commonServiceConfig; }; }) @@ -329,8 +329,8 @@ in ]; environment = { - KEA_PIDFILE_DIR = "/run/kea"; - KEA_LOCKFILE_DIR = "/run/kea"; + KEA_PIDFILE_DIR = "/run/kea-dhcp4"; + KEA_LOCKFILE_DIR = "/run/kea-dhcp4"; }; restartTriggers = [ @@ -348,6 +348,7 @@ in "CAP_NET_BIND_SERVICE" "CAP_NET_RAW" ]; + RuntimeDirectory = "kea-dhcp4"; } // commonServiceConfig; }; }) @@ -376,8 +377,8 @@ in ]; environment = { - KEA_PIDFILE_DIR = "/run/kea"; - KEA_LOCKFILE_DIR = "/run/kea"; + KEA_PIDFILE_DIR = "/run/kea-dhcp6"; + KEA_LOCKFILE_DIR = "/run/kea-dhcp6"; }; restartTriggers = [ @@ -393,6 +394,7 @@ in CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + RuntimeDirectory = "kea-dhcp6"; } // commonServiceConfig; }; }) @@ -421,8 +423,8 @@ in ]; environment = { - KEA_PIDFILE_DIR = "/run/kea"; - KEA_LOCKFILE_DIR = "/run/kea"; + KEA_PIDFILE_DIR = "/run/kea-dhcp-ddns"; + KEA_LOCKFILE_DIR = "/run/kea-dhcp-ddns"; }; restartTriggers = [ @@ -437,6 +439,7 @@ in CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + RuntimeDirectory = "kea-dhcp-ddns"; } // commonServiceConfig; }; }) diff --git a/nixpkgs/nixos/modules/services/networking/rosenpass.nix b/nixpkgs/nixos/modules/services/networking/rosenpass.nix new file mode 100644 index 000000000000..d2a264b83d67 --- /dev/null +++ b/nixpkgs/nixos/modules/services/networking/rosenpass.nix @@ -0,0 +1,233 @@ +{ config +, lib +, options +, pkgs +, ... +}: +let + inherit (lib) + attrValues + concatLines + concatMap + filter + filterAttrsRecursive + flatten + getExe + mdDoc + mkIf + optional + ; + + cfg = config.services.rosenpass; + opt = options.services.rosenpass; + settingsFormat = pkgs.formats.toml { }; +in +{ + options.services.rosenpass = + let + inherit (lib) + literalExpression + mdDoc + mkOption + ; + inherit (lib.types) + enum + listOf + nullOr + path + str + submodule + ; + in + { + enable = lib.mkEnableOption (mdDoc "Rosenpass"); + + package = lib.mkPackageOption pkgs "rosenpass" { }; + + defaultDevice = mkOption { + type = nullOr str; + description = mdDoc "Name of the network interface to use for all peers by default."; + example = "wg0"; + }; + + settings = mkOption { + type = submodule { + freeformType = settingsFormat.type; + + options = { + public_key = mkOption { + type = path; + description = mdDoc "Path to a file containing the public key of the local Rosenpass peer. Generate this by running {command}`rosenpass gen-keys`."; + }; + + secret_key = mkOption { + type = path; + description = mdDoc "Path to a file containing the secret key of the local Rosenpass peer. Generate this by running {command}`rosenpass gen-keys`."; + }; + + listen = mkOption { + type = listOf str; + description = mdDoc "List of local endpoints to listen for connections."; + default = [ ]; + example = literalExpression "[ \"0.0.0.0:10000\" ]"; + }; + + verbosity = mkOption { + type = enum [ "Verbose" "Quiet" ]; + default = "Quiet"; + description = mdDoc "Verbosity of output produced by the service."; + }; + + peers = + let + peer = submodule { + freeformType = settingsFormat.type; + + options = { + public_key = mkOption { + type = path; + description = mdDoc "Path to a file containing the public key of the remote Rosenpass peer."; + }; + + endpoint = mkOption { + type = nullOr str; + default = null; + description = mdDoc "Endpoint of the remote Rosenpass peer."; + }; + + device = mkOption { + type = str; + default = cfg.defaultDevice; + defaultText = literalExpression "config.${opt.defaultDevice}"; + description = mdDoc "Name of the local WireGuard interface to use for this peer."; + }; + + peer = mkOption { + type = str; + description = mdDoc "WireGuard public key corresponding to the remote Rosenpass peer."; + }; + }; + }; + in + mkOption { + type = listOf peer; + description = mdDoc "List of peers to exchange keys with."; + default = [ ]; + }; + }; + }; + default = { }; + description = mdDoc "Configuration for Rosenpass, see <https://rosenpass.eu/> for further information."; + }; + }; + + config = mkIf cfg.enable { + warnings = + let + # NOTE: In the descriptions below, we tried to refer to e.g. + # options.systemd.network.netdevs."<name>".wireguardPeers.*.PublicKey + # directly, but don't know how to traverse "<name>" and * in this path. + extractions = [ + { + relevant = config.systemd.network.enable; + root = config.systemd.network.netdevs; + peer = (x: x.wireguardPeers); + key = (x: if x.wireguardPeerConfig ? PublicKey then x.wireguardPeerConfig.PublicKey else null); + description = mdDoc "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.wireguardPeerConfig.PublicKey"; + } + { + relevant = config.networking.wireguard.enable; + root = config.networking.wireguard.interfaces; + peer = (x: x.peers); + key = (x: x.publicKey); + description = mdDoc "${options.networking.wireguard.interfaces}.\"<name>\".peers.*.publicKey"; + } + rec { + relevant = root != { }; + root = config.networking.wg-quick.interfaces; + peer = (x: x.peers); + key = (x: x.publicKey); + description = mdDoc "${options.networking.wg-quick.interfaces}.\"<name>\".peers.*.publicKey"; + } + ]; + relevantExtractions = filter (x: x.relevant) extractions; + extract = { root, peer, key, ... }: + filter (x: x != null) (flatten (concatMap (x: (map key (peer x))) (attrValues root))); + configuredKeys = flatten (map extract relevantExtractions); + itemize = xs: concatLines (map (x: " - ${x}") xs); + descriptions = map (x: "`${x.description}`"); + missingKeys = filter (key: !builtins.elem key configuredKeys) (map (x: x.peer) cfg.settings.peers); + unusual = '' + While this may work as expected, e.g. you want to manually configure WireGuard, + such a scenario is unusual. Please double-check your configuration. + ''; + in + (optional (relevantExtractions != [ ] && missingKeys != [ ]) '' + You have configured Rosenpass peers with the WireGuard public keys: + ${itemize missingKeys} + But there is no corresponding active Wireguard peer configuration in any of: + ${itemize (descriptions relevantExtractions)} + ${unusual} + '') + ++ + optional (relevantExtractions == [ ]) '' + You have configured Rosenpass, but you have not configured Wireguard via any of: + ${itemize (descriptions extractions)} + ${unusual} + ''; + + environment.systemPackages = [ cfg.package pkgs.wireguard-tools ]; + + systemd.services.rosenpass = + let + filterNonNull = filterAttrsRecursive (_: v: v != null); + config = settingsFormat.generate "config.toml" ( + filterNonNull (cfg.settings + // + ( + let + credentialPath = id: "$CREDENTIALS_DIRECTORY/${id}"; + # NOTE: We would like to remove all `null` values inside `cfg.settings` + # recursively, since `settingsFormat.generate` cannot handle `null`. + # This would require to traverse both attribute sets and lists recursively. + # `filterAttrsRecursive` only recurses into attribute sets, but not + # into values that might contain other attribute sets (such as lists, + # e.g. `cfg.settings.peers`). Here, we just specialize on `cfg.settings.peers`, + # and this may break unexpectedly whenever a `null` value is contained + # in a list in `cfg.settings`, other than `cfg.settings.peers`. + peersWithoutNulls = map filterNonNull cfg.settings.peers; + in + { + secret_key = credentialPath "pqsk"; + public_key = credentialPath "pqpk"; + peers = peersWithoutNulls; + } + ) + ) + ); + in + rec { + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + path = [ cfg.package pkgs.wireguard-tools ]; + + serviceConfig = { + User = "rosenpass"; + Group = "rosenpass"; + RuntimeDirectory = "rosenpass"; + DynamicUser = true; + AmbientCapabilities = [ "CAP_NET_ADMIN" ]; + LoadCredential = [ + "pqsk:${cfg.settings.secret_key}" + "pqpk:${cfg.settings.public_key}" + ]; + }; + + # See <https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers> + environment.CONFIG = "%t/${serviceConfig.RuntimeDirectory}/config.toml"; + + preStart = "${getExe pkgs.envsubst} -i ${config} -o \"$CONFIG\""; + script = "rosenpass exchange-config \"$CONFIG\""; + }; + }; +} diff --git a/nixpkgs/nixos/modules/services/networking/syncthing.nix b/nixpkgs/nixos/modules/services/networking/syncthing.nix index c4b2d0e80f9b..bdcdaf056d03 100644 --- a/nixpkgs/nixos/modules/services/networking/syncthing.nix +++ b/nixpkgs/nixos/modules/services/networking/syncthing.nix @@ -10,6 +10,21 @@ let settingsFormat = pkgs.formats.json { }; cleanedConfig = converge (filterAttrsRecursive (_: v: v != null && v != {})) cfg.settings; + isUnixGui = (builtins.substring 0 1 cfg.guiAddress) == "/"; + + # Syncthing supports serving the GUI over Unix sockets. If that happens, the + # API is served over the Unix socket as well. This function returns the correct + # curl arguments for the address portion of the curl command for both network + # and Unix socket addresses. + curlAddressArgs = path: if isUnixGui + # if cfg.guiAddress is a unix socket, tell curl explicitly about it + # note that the dot in front of `${path}` is the hostname, which is + # required. + then "--unix-socket ${cfg.guiAddress} http://.${path}" + # no adjustements are needed if cfg.guiAddress is a network address + else "${cfg.guiAddress}${path}" + ; + devices = mapAttrsToList (_: device: device // { deviceID = device.id; }) cfg.settings.devices; @@ -62,14 +77,14 @@ let GET_IdAttrName = "deviceID"; override = cfg.overrideDevices; conf = devices; - baseAddress = "${cfg.guiAddress}/rest/config/devices"; + baseAddress = curlAddressArgs "/rest/config/devices"; }; dirs = { new_conf_IDs = map (v: v.id) folders; GET_IdAttrName = "id"; override = cfg.overrideFolders; conf = folders; - baseAddress = "${cfg.guiAddress}/rest/config/folders"; + baseAddress = curlAddressArgs "/rest/config/folders"; }; } [ # Now for each of these attributes, write the curl commands that are @@ -117,15 +132,14 @@ let builtins.attrNames (lib.subtractLists ["folders" "devices"]) (map (subOption: '' - curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} \ - ${cfg.guiAddress}/rest/config/${subOption} + curl -X PUT -d ${lib.escapeShellArg (builtins.toJSON cleanedConfig.${subOption})} ${curlAddressArgs "/rest/config/${subOption}"} '')) (lib.concatStringsSep "\n") ]) + '' # restart Syncthing if required - if curl ${cfg.guiAddress}/rest/config/restart-required | + if curl ${curlAddressArgs "/rest/config/restart-required"} | ${jq} -e .requiresRestart > /dev/null; then - curl -X POST ${cfg.guiAddress}/rest/system/restart + curl -X POST ${curlAddressArgs "/rest/system/restart"} fi ''); in { @@ -651,7 +665,7 @@ in { ExecStart = '' ${cfg.package}/bin/syncthing \ -no-browser \ - -gui-address=${cfg.guiAddress} \ + -gui-address=${if isUnixGui then "unix://" else ""}${cfg.guiAddress} \ -home=${cfg.configDir} ${escapeShellArgs cfg.extraFlags} ''; MemoryDenyWriteExecute = true; diff --git a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix index 0595e9e6df23..90d9c68433cf 100644 --- a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix @@ -530,5 +530,5 @@ in { ''; }; - meta.maintainers = with lib.maintainers; [ globin rnhmjoj ]; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; } diff --git a/nixpkgs/nixos/modules/services/web-apps/akkoma.nix b/nixpkgs/nixos/modules/services/web-apps/akkoma.nix index 8d1775258612..eaee70c712bb 100644 --- a/nixpkgs/nixos/modules/services/web-apps/akkoma.nix +++ b/nixpkgs/nixos/modules/services/web-apps/akkoma.nix @@ -282,11 +282,11 @@ let AKKOMA_CONFIG_PATH="$RUNTIME_DIRECTORY/config.exs" \ ERL_EPMD_ADDRESS="${cfg.dist.address}" \ ERL_EPMD_PORT="${toString cfg.dist.epmdPort}" \ - ERL_FLAGS="${concatStringsSep " " [ - "-kernel inet_dist_use_interface '${erlAddr cfg.dist.address}'" - "-kernel inet_dist_listen_min ${toString cfg.dist.portMin}" - "-kernel inet_dist_listen_max ${toString cfg.dist.portMax}" - ]}" \ + ERL_FLAGS=${lib.escapeShellArg (lib.escapeShellArgs ([ + "-kernel" "inet_dist_use_interface" (erlAddr cfg.dist.address) + "-kernel" "inet_dist_listen_min" (toString cfg.dist.portMin) + "-kernel" "inet_dist_listen_max" (toString cfg.dist.portMax) + ] ++ cfg.dist.extraFlags))} \ RELEASE_COOKIE="$(<"$RUNTIME_DIRECTORY/cookie")" \ RELEASE_NAME="akkoma" \ exec "${cfg.package}/bin/$(basename "$0")" "$@" @@ -553,6 +553,13 @@ in { description = mdDoc "TCP port to bind Erlang Port Mapper Daemon to."; }; + extraFlags = mkOption { + type = with types; listOf str; + default = [ ]; + description = mdDoc "Extra flags to pass to Erlang"; + example = [ "+sbwt" "none" "+sbwtdcpu" "none" "+sbwtdio" "none" ]; + }; + portMin = mkOption { type = types.port; default = 49152; diff --git a/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix b/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix new file mode 100644 index 000000000000..f1ab8b8b4eb4 --- /dev/null +++ b/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix @@ -0,0 +1,100 @@ +{ pkgs, lib, config, ... }: + +let + cfg = config.services.lanraragi; +in +{ + meta.maintainers = with lib.maintainers; [ tomasajt ]; + + options.services = { + lanraragi = { + enable = lib.mkEnableOption (lib.mdDoc "LANraragi"); + package = lib.mkPackageOptionMD pkgs "lanraragi" { }; + + port = lib.mkOption { + type = lib.types.port; + default = 3000; + description = lib.mdDoc "Port for LANraragi's web interface."; + }; + + passwordFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + example = "/run/keys/lanraragi-password"; + description = lib.mdDoc '' + A file containing the password for LANraragi's admin interface. + ''; + }; + + redis = { + port = lib.mkOption { + type = lib.types.port; + default = 6379; + description = lib.mdDoc "Port for LANraragi's Redis server."; + }; + passwordFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + example = "/run/keys/redis-lanraragi-password"; + description = lib.mdDoc '' + A file containing the password for LANraragi's Redis server. + ''; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + services.redis.servers.lanraragi = { + enable = true; + port = cfg.redis.port; + requirePassFile = cfg.redis.passwordFile; + }; + + systemd.services.lanraragi = { + description = "LANraragi main service"; + after = [ "network.target" "redis-lanraragi.service" ]; + requires = [ "redis-lanraragi.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = lib.getExe cfg.package; + DynamicUser = true; + StateDirectory = "lanraragi"; + RuntimeDirectory = "lanraragi"; + LogsDirectory = "lanraragi"; + Restart = "on-failure"; + WorkingDirectory = "/var/lib/lanraragi"; + }; + environment = { + "LRR_TEMP_DIRECTORY" = "/run/lanraragi"; + "LRR_LOG_DIRECTORY" = "/var/log/lanraragi"; + "LRR_NETWORK" = "http://*:${toString cfg.port}"; + "HOME" = "/var/lib/lanraragi"; + }; + preStart = '' + REDIS_PASS=${lib.optionalString (cfg.redis.passwordFile != null) "$(head -n1 ${cfg.redis.passwordFile})"} + cat > lrr.conf <<EOF + { + redis_address => "127.0.0.1:${toString cfg.redis.port}", + redis_password => "$REDIS_PASS", + redis_database => "0", + redis_database_minion => "1", + redis_database_config => "2", + redis_database_search => "3", + } + EOF + '' + lib.optionalString (cfg.passwordFile != null) '' + PASS_HASH=$( + PASS=$(head -n1 ${cfg.passwordFile}) ${cfg.package.perlEnv}/bin/perl -I${cfg.package}/share/lanraragi/lib -e \ + 'use LANraragi::Controller::Config; print LANraragi::Controller::Config::make_password_hash($ENV{PASS})' \ + 2>/dev/null + ) + + ${lib.getExe pkgs.redis} -h 127.0.0.1 -p ${toString cfg.redis.port} -a "$REDIS_PASS" <<EOF + SELECT 2 + HSET LRR_CONFIG password $PASS_HASH + EOF + ''; + }; + }; +} diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix index c82f02ecefec..9db4c8e23025 100644 --- a/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -35,7 +35,10 @@ with lib; }; port = mkOption { type = types.nullOr port; - description = lib.mdDoc "Port number."; + description = lib.mdDoc '' + Port number to listen on. + If unset and the listen address is not a socket then nginx defaults to 80. + ''; default = null; }; ssl = mkOption { diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix index 285d0a181931..fc3287045710 100644 --- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -379,7 +379,7 @@ in # Update the start menu for each user that is currently logged in system.userActivationScripts.plasmaSetup = activationScript; - programs.firefox.wrapperConfig.enablePlasmaBrowserIntegration = true; + programs.firefox.nativeMessagingHosts.packages = [ pkgs.plasma5Packages.plasma-browser-integration ]; }) (mkIf (cfg.kwinrc != {}) { diff --git a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix index 64c8ab74bba6..6f0a62d0ea89 100644 --- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix +++ b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix @@ -49,7 +49,7 @@ let ''; }; - checkedSystemdBootBuilder = pkgs.runCommandLocal "systemd-boot" { + checkedSystemdBootBuilder = pkgs.runCommand "systemd-boot" { nativeBuildInputs = [ pkgs.mypy ]; } '' install -m755 ${systemdBootBuilder} $out diff --git a/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix b/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix index 3065392b1d20..f7ef45aab3c9 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix @@ -20,6 +20,102 @@ in ''; }; + systemd.tmpfiles.settings = mkOption { + description = lib.mdDoc '' + Declare systemd-tmpfiles rules to create, delete, and clean up volatile + and temporary files and directories. + + Even though the service is called `*tmp*files` you can also create + persistent files. + ''; + example = { + "10-mypackage" = { + "/var/lib/my-service/statefolder".d = { + mode = "0755"; + user = "root"; + group = "root"; + }; + }; + }; + default = {}; + type = types.attrsOf (types.attrsOf (types.attrsOf (types.submodule ({ name, config, ... }: { + options.type = mkOption { + type = types.str; + default = name; + example = "d"; + description = lib.mdDoc '' + The type of operation to perform on the file. + + The type consists of a single letter and optionally one or more + modifier characters. + + Please see the upstream documentation for the available types and + more details: + <https://www.freedesktop.org/software/systemd/man/tmpfiles.d> + ''; + }; + options.mode = mkOption { + type = types.str; + default = "-"; + example = "0755"; + description = lib.mdDoc '' + The file access mode to use when creating this file or directory. + ''; + }; + options.user = mkOption { + type = types.str; + default = "-"; + example = "root"; + description = lib.mdDoc '' + The user of the file. + + This may either be a numeric ID or a user/group name. + + If omitted or when set to `"-"`, the user and group of the user who + invokes systemd-tmpfiles is used. + ''; + }; + options.group = mkOption { + type = types.str; + default = "-"; + example = "root"; + description = lib.mdDoc '' + The group of the file. + + This may either be a numeric ID or a user/group name. + + If omitted or when set to `"-"`, the user and group of the user who + invokes systemd-tmpfiles is used. + ''; + }; + options.age = mkOption { + type = types.str; + default = "-"; + example = "10d"; + description = lib.mdDoc '' + Delete a file when it reaches a certain age. + + If a file or directory is older than the current time minus the age + field, it is deleted. + + If set to `"-"` no automatic clean-up is done. + ''; + }; + options.argument = mkOption { + type = types.str; + default = ""; + example = ""; + description = lib.mdDoc '' + An argument whose meaning depends on the type of operation. + + Please see the upstream documentation for the meaning of this + parameter in different situations: + <https://www.freedesktop.org/software/systemd/man/tmpfiles.d> + ''; + }; + })))); + }; + systemd.tmpfiles.packages = mkOption { type = types.listOf types.package; default = []; @@ -102,7 +198,13 @@ in ${concatStringsSep "\n" cfg.rules} ''; }) - ]; + ] ++ (mapAttrsToList (name: paths: + pkgs.writeTextDir "lib/tmpfiles.d/${name}.conf" (concatStrings (mapAttrsToList (path: types: + concatStrings (mapAttrsToList (_type: entry: '' + '${entry.type}' '${path}' '${entry.mode}' '${entry.user}' '${entry.group}' '${entry.age}' ${entry.argument} + '') types) + ) paths )) + ) cfg.settings); systemd.tmpfiles.rules = [ "d /nix/var 0755 root root - -" diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix index 1034c699629d..61d7c4cb73fe 100644 --- a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix +++ b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix @@ -37,7 +37,6 @@ in { ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system ''; - # TODO: build rootfs as squashfs for faster unpack system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix { extraArgs = "--owner=0"; @@ -64,6 +63,23 @@ in { extraCommands = "mkdir -p proc sys dev"; }; + system.build.squashfs = pkgs.callPackage ../../lib/make-squashfs.nix { + fileName = "nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}"; + + noStrip = true; # keep directory structure + comp = "zstd -Xcompression-level 6"; + + storeContents = [config.system.build.toplevel]; + + pseudoFiles = [ + "/sbin d 0755 0 0" + "/sbin/init s 0555 0 0 ${config.system.build.toplevel}/init" + "/dev d 0755 0 0" + "/proc d 0555 0 0" + "/sys d 0555 0 0" + ]; + }; + system.build.installBootLoader = pkgs.writeScript "install-lxd-sbin-init.sh" '' #!${pkgs.runtimeShell} ${pkgs.coreutils}/bin/ln -fs "$1/init" /sbin/init diff --git a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix index 737a935711ae..e625c6322d9c 100644 --- a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix @@ -198,6 +198,39 @@ let fi ''} + ${lib.optionalString cfg.tpm.enable '' + NIX_SWTPM_DIR=$(readlink -f "''${NIX_SWTPM_DIR:-${config.system.name}-swtpm}") + mkdir -p "$NIX_SWTPM_DIR" + ${lib.getExe cfg.tpm.package} \ + socket \ + --tpmstate dir="$NIX_SWTPM_DIR" \ + --ctrl type=unixio,path="$NIX_SWTPM_DIR"/socket,terminate \ + --pid file="$NIX_SWTPM_DIR"/pid --daemon \ + --tpm2 \ + --log file="$NIX_SWTPM_DIR"/stdout,level=6 + + # Enable `fdflags` builtin in Bash + # We will need it to perform surgical modification of the file descriptor + # passed in the coprocess to remove `FD_CLOEXEC`, i.e. close the file descriptor + # on exec. + # If let alone, it will trigger the coprocess to read EOF when QEMU is `exec` + # at the end of this script. To work around that, we will just clear + # the `FD_CLOEXEC` bits as a first step. + enable -f ${hostPkgs.bash}/lib/bash/fdflags fdflags + # leave a dangling subprocess because the swtpm ctrl socket has + # "terminate" when the last connection disconnects, it stops swtpm. + # When qemu stops, or if the main shell process ends, the coproc will + # get signaled by virtue of the pipe between main and coproc ending. + # Which in turns triggers a socat connect-disconnect to swtpm which + # will stop it. + coproc waitingswtpm { + read || : + echo "" | ${lib.getExe hostPkgs.socat} STDIO UNIX-CONNECT:"$NIX_SWTPM_DIR"/socket + } + # Clear `FD_CLOEXEC` on the coprocess' file descriptor stdin. + fdflags -s-cloexec ''${waitingswtpm[1]} + ''} + cd "$TMPDIR" ${lib.optionalString (cfg.emptyDiskImages != []) "idx=0"} @@ -657,8 +690,8 @@ in package = mkOption { type = types.package; - default = hostPkgs.qemu_kvm; - defaultText = literalExpression "config.virtualisation.host.pkgs.qemu_kvm"; + default = if hostPkgs.stdenv.hostPlatform.qemuArch == pkgs.stdenv.hostPlatform.qemuArch then hostPkgs.qemu_kvm else hostPkgs.qemu; + defaultText = literalExpression "if hostPkgs.stdenv.hostPlatform.qemuArch == pkgs.stdenv.hostPlatform.qemuArch then config.virtualisation.host.pkgs.qemu_kvm else config.virtualisation.host.pkgs.qemu"; example = literalExpression "pkgs.qemu_test"; description = lib.mdDoc "QEMU package to use."; }; @@ -863,6 +896,32 @@ in }; }; + virtualisation.tpm = { + enable = mkEnableOption "a TPM device in the virtual machine with a driver, using swtpm."; + + package = mkPackageOptionMD cfg.host.pkgs "swtpm" { }; + + deviceModel = mkOption { + type = types.str; + default = ({ + "i686-linux" = "tpm-tis"; + "x86_64-linux" = "tpm-tis"; + "ppc64-linux" = "tpm-spapr"; + "armv7-linux" = "tpm-tis-device"; + "aarch64-linux" = "tpm-tis-device"; + }.${pkgs.hostPlatform.system} or (throw "Unsupported system for TPM2 emulation in QEMU")); + defaultText = '' + Based on the guest platform Linux system: + + - `tpm-tis` for (i686, x86_64) + - `tpm-spapr` for ppc64 + - `tpm-tis-device` for (armv7, aarch64) + ''; + example = "tpm-tis-device"; + description = lib.mdDoc "QEMU device model for the TPM, uses the appropriate default based on th guest platform system and the package passed."; + }; + }; + virtualisation.useDefaultFilesystems = mkOption { type = types.bool; @@ -1028,7 +1087,8 @@ in boot.initrd.availableKernelModules = optional cfg.writableStore "overlay" - ++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx"; + ++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx" + ++ optional (cfg.tpm.enable) "tpm_tis"; virtualisation.additionalPaths = [ config.system.build.toplevel ]; @@ -1099,6 +1159,11 @@ in (mkIf (!cfg.graphics) [ "-nographic" ]) + (mkIf (cfg.tpm.enable) [ + "-chardev socket,id=chrtpm,path=\"$NIX_SWTPM_DIR\"/socket" + "-tpmdev emulator,id=tpm_dev_0,chardev=chrtpm" + "-device ${cfg.tpm.deviceModel},tpmdev=tpm_dev_0" + ]) ]; virtualisation.qemu.drives = mkMerge [ |