diff options
author | Milo Gertjejansen <milo@milogert.com> | 2021-07-28 21:06:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-28 21:06:44 -0400 |
commit | f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f (patch) | |
tree | cfde93691a153b5bf44dd4387f0fe855e2e7c742 /nixos/modules | |
parent | 7aa2bf302ae563453b010cc27ea66affb055b26e (diff) | |
parent | d0044b0e7d531a7a28d4552582b98e8b3953c6cb (diff) | |
download | nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar.gz nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar.bz2 nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar.lz nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar.xz nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.tar.zst nixpkgs-f3b660014d83e8d5b714e7d0ef5d5ffb1d19710f.zip |
Merge branch 'master' into tt-rss-2021-06-21
Diffstat (limited to 'nixos/modules')
27 files changed, 587 insertions, 360 deletions
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 567a8b6f3b9..d5e7745c53f 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -396,7 +396,7 @@ let }; }; - idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }: + idsAreUnique = set: idAttr: !(foldr (name: args@{ dup, acc }: let id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set)); exists = builtins.hasAttr id acc; diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix index 3e88a4c20ad..524dae57010 100644 --- a/nixos/modules/hardware/all-firmware.nix +++ b/nixos/modules/hardware/all-firmware.nix @@ -35,6 +35,14 @@ in { ''; }; + hardware.wirelessRegulatoryDatabase = mkOption { + default = false; + type = types.bool; + description = '' + Load the wireless regulatory database at boot. + ''; + }; + }; @@ -58,6 +66,7 @@ in { ++ optionals (versionOlder config.boot.kernelPackages.kernel.version "4.13") [ rtl8723bs-firmware ]; + hardware.wirelessRegulatoryDatabase = true; }) (mkIf cfg.enableAllFirmware { assertions = [{ @@ -75,5 +84,8 @@ in { b43FirmwareCutter ] ++ optional (pkgs.stdenv.hostPlatform.isi686 || pkgs.stdenv.hostPlatform.isx86_64) facetimehd-firmware; }) + (mkIf cfg.wirelessRegulatoryDatabase { + hardware.firmware = [ pkgs.wireless-regdb ]; + }) ]; } diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index d94af0b5bf7..f0384513247 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -654,7 +654,11 @@ in ]; fileSystems."/" = - { fsType = "tmpfs"; + # This module is often over-layed onto an existing host config + # that defines `/`. We use mkOverride 60 to override standard + # values, but at the same time leave room for mkForce values + # targeted at the image build. + { fsType = mkOverride 60 "tmpfs"; options = [ "mode=0755" ]; }; diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix index 238ab6d0617..f7543fdf4a2 100644 --- a/nixos/modules/installer/netboot/netboot.nix +++ b/nixos/modules/installer/netboot/netboot.nix @@ -30,7 +30,11 @@ with lib; else [ pkgs.grub2 pkgs.syslinux ]); fileSystems."/" = - { fsType = "tmpfs"; + # This module is often over-layed onto an existing host config + # that defines `/`. We use mkOverride 60 to override standard + # values, but at the same time leave room for mkForce values + # targeted at the image build. + { fsType = mkOverride 60 "tmpfs"; options = [ "mode=0755" ]; }; diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix index e3576074a5b..15c76287e34 100644 --- a/nixos/modules/installer/tools/nix-fallback-paths.nix +++ b/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -1,7 +1,7 @@ { - x86_64-linux = "/nix/store/qsgz2hhn6mzlzp53a7pwf9z2pq3l5z6h-nix-2.3.14"; - i686-linux = "/nix/store/1yw40bj04lykisw2jilq06lir3k9ga4a-nix-2.3.14"; - aarch64-linux = "/nix/store/32yzwmynmjxfrkb6y6l55liaqdrgkj4a-nix-2.3.14"; - x86_64-darwin = "/nix/store/06j0vi2d13w4l0p3jsigq7lk4x6gkycj-nix-2.3.14"; - aarch64-darwin = "/nix/store/77wi7vpbrghw5rgws25w30bwb8yggnk9-nix-2.3.14"; + x86_64-linux = "/nix/store/jhbxh1jwjc3hjhzs9y2hifdn0rmnfwaj-nix-2.3.15"; + i686-linux = "/nix/store/9pspwnkdrgzma1l4xlv7arhwa56y16di-nix-2.3.15"; + aarch64-linux = "/nix/store/72aqi5g7f4fhgvgafbcqwcpqjgnczj48-nix-2.3.15"; + x86_64-darwin = "/nix/store/6p6qwp73dgfkqhynmxrzbx1lcfgfpqal-nix-2.3.15"; + aarch64-darwin = "/nix/store/dmq2vksdhssgfl822shd0ky3x5x0klh4-nix-2.3.15"; } diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix index 8160bfef4a3..a2ac5c58528 100644 --- a/nixos/modules/misc/nixpkgs.nix +++ b/nixos/modules/misc/nixpkgs.nix @@ -39,7 +39,7 @@ let if c x then true else lib.traceSeqN 1 x false; in traceXIfNot isConfig; - merge = args: fold (def: mergeConfig def.value) {}; + merge = args: foldr (def: mergeConfig def.value) {}; }; overlayType = mkOptionType { diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4d1700ed99a..0bd789b5911 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -529,6 +529,7 @@ ./services/misc/mediatomb.nix ./services/misc/metabase.nix ./services/misc/mwlib.nix + ./services/misc/mx-puppet-discord.nix ./services/misc/n8n.nix ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix diff --git a/nixos/modules/services/backup/sanoid.nix b/nixos/modules/services/backup/sanoid.nix index abc4def1c61..41d0e2e1df6 100644 --- a/nixos/modules/services/backup/sanoid.nix +++ b/nixos/modules/services/backup/sanoid.nix @@ -52,7 +52,7 @@ let use_template = mkOption { description = "Names of the templates to use for this dataset."; type = types.listOf (types.enum (attrNames cfg.templates)); - default = []; + default = [ ]; }; useTemplate = use_template; @@ -70,116 +70,127 @@ let processChildrenOnly = process_children_only; }; - # Extract pool names from configured datasets - pools = unique (map (d: head (builtins.match "([^/]+).*" d)) (attrNames cfg.datasets)); - - configFile = let - mkValueString = v: - if builtins.isList v then concatStringsSep "," v - else generators.mkValueStringDefault {} v; - - mkKeyValue = k: v: if v == null then "" - else if k == "processChildrenOnly" then "" - else if k == "useTemplate" then "" - else generators.mkKeyValueDefault { inherit mkValueString; } "=" k v; - in generators.toINI { inherit mkKeyValue; } cfg.settings; - -in { - - # Interface - - options.services.sanoid = { - enable = mkEnableOption "Sanoid ZFS snapshotting service"; - - interval = mkOption { - type = types.str; - default = "hourly"; - example = "daily"; - description = '' - Run sanoid at this interval. The default is to run hourly. - - The format is described in - <citerefentry><refentrytitle>systemd.time</refentrytitle> - <manvolnum>7</manvolnum></citerefentry>. - ''; - }; + # Extract unique dataset names + datasets = unique (attrNames cfg.datasets); + + # Function to build "zfs allow" and "zfs unallow" commands for the + # filesystems we've delegated permissions to. + buildAllowCommand = zfsAction: permissions: dataset: lib.escapeShellArgs [ + # Here we explicitly use the booted system to guarantee the stable API needed by ZFS + "-+/run/booted-system/sw/bin/zfs" + zfsAction + "sanoid" + (concatStringsSep "," permissions) + dataset + ]; + + configFile = + let + mkValueString = v: + if builtins.isList v then concatStringsSep "," v + else generators.mkValueStringDefault { } v; + + mkKeyValue = k: v: + if v == null then "" + else if k == "processChildrenOnly" then "" + else if k == "useTemplate" then "" + else generators.mkKeyValueDefault { inherit mkValueString; } "=" k v; + in + generators.toINI { inherit mkKeyValue; } cfg.settings; + +in +{ + + # Interface + + options.services.sanoid = { + enable = mkEnableOption "Sanoid ZFS snapshotting service"; + + interval = mkOption { + type = types.str; + default = "hourly"; + example = "daily"; + description = '' + Run sanoid at this interval. The default is to run hourly. + + The format is described in + <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry>. + ''; + }; - datasets = mkOption { - type = types.attrsOf (types.submodule ({config, options, ...}: { - freeformType = datasetSettingsType; - options = commonOptions // datasetOptions; - config.use_template = mkAliasDefinitions (mkDefault options.useTemplate or {}); - config.process_children_only = mkAliasDefinitions (mkDefault options.processChildrenOnly or {}); - })); - default = {}; - description = "Datasets to snapshot."; - }; + datasets = mkOption { + type = types.attrsOf (types.submodule ({ config, options, ... }: { + freeformType = datasetSettingsType; + options = commonOptions // datasetOptions; + config.use_template = mkAliasDefinitions (mkDefault options.useTemplate or { }); + config.process_children_only = mkAliasDefinitions (mkDefault options.processChildrenOnly or { }); + })); + default = { }; + description = "Datasets to snapshot."; + }; - templates = mkOption { - type = types.attrsOf (types.submodule { - freeformType = datasetSettingsType; - options = commonOptions; - }); - default = {}; - description = "Templates for datasets."; - }; + templates = mkOption { + type = types.attrsOf (types.submodule { + freeformType = datasetSettingsType; + options = commonOptions; + }); + default = { }; + description = "Templates for datasets."; + }; - settings = mkOption { - type = types.attrsOf datasetSettingsType; - description = '' - Free-form settings written directly to the config file. See - <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/> - for allowed values. - ''; - }; + settings = mkOption { + type = types.attrsOf datasetSettingsType; + description = '' + Free-form settings written directly to the config file. See + <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/> + for allowed values. + ''; + }; - extraArgs = mkOption { - type = types.listOf types.str; - default = []; - example = [ "--verbose" "--readonly" "--debug" ]; - description = '' - Extra arguments to pass to sanoid. See - <link xlink:href="https://github.com/jimsalterjrs/sanoid/#sanoid-command-line-options"/> - for allowed options. - ''; - }; + extraArgs = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--verbose" "--readonly" "--debug" ]; + description = '' + Extra arguments to pass to sanoid. See + <link xlink:href="https://github.com/jimsalterjrs/sanoid/#sanoid-command-line-options"/> + for allowed options. + ''; }; + }; - # Implementation - - config = mkIf cfg.enable { - services.sanoid.settings = mkMerge [ - (mapAttrs' (d: v: nameValuePair ("template_" + d) v) cfg.templates) - (mapAttrs (d: v: v) cfg.datasets) - ]; - - systemd.services.sanoid = { - description = "Sanoid snapshot service"; - serviceConfig = { - ExecStartPre = map (pool: lib.escapeShellArgs [ - "+/run/booted-system/sw/bin/zfs" "allow" - "sanoid" "snapshot,mount,destroy" pool - ]) pools; - ExecStart = lib.escapeShellArgs ([ - "${pkgs.sanoid}/bin/sanoid" - "--cron" - "--configdir" (pkgs.writeTextDir "sanoid.conf" configFile) - ] ++ cfg.extraArgs); - ExecStopPost = map (pool: lib.escapeShellArgs [ - "+/run/booted-system/sw/bin/zfs" "unallow" "sanoid" pool - ]) pools; - User = "sanoid"; - Group = "sanoid"; - DynamicUser = true; - RuntimeDirectory = "sanoid"; - CacheDirectory = "sanoid"; - }; - # Prevents missing snapshots during DST changes - environment.TZ = "UTC"; - after = [ "zfs.target" ]; - startAt = cfg.interval; + # Implementation + + config = mkIf cfg.enable { + services.sanoid.settings = mkMerge [ + (mapAttrs' (d: v: nameValuePair ("template_" + d) v) cfg.templates) + (mapAttrs (d: v: v) cfg.datasets) + ]; + + systemd.services.sanoid = { + description = "Sanoid snapshot service"; + serviceConfig = { + ExecStartPre = (map (buildAllowCommand "allow" [ "snapshot" "mount" "destroy" ]) datasets); + ExecStopPost = (map (buildAllowCommand "unallow" [ "snapshot" "mount" "destroy" ]) datasets); + ExecStart = lib.escapeShellArgs ([ + "${pkgs.sanoid}/bin/sanoid" + "--cron" + "--configdir" + (pkgs.writeTextDir "sanoid.conf" configFile) + ] ++ cfg.extraArgs); + User = "sanoid"; + Group = "sanoid"; + DynamicUser = true; + RuntimeDirectory = "sanoid"; + CacheDirectory = "sanoid"; }; + # Prevents missing snapshots during DST changes + environment.TZ = "UTC"; + after = [ "zfs.target" ]; + startAt = cfg.interval; }; + }; - meta.maintainers = with maintainers; [ lopsided98 ]; - } + meta.maintainers = with maintainers; [ lopsided98 ]; +} diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix index 888ef20f642..73b01d4b53f 100644 --- a/nixos/modules/services/backup/syncoid.nix +++ b/nixos/modules/services/backup/syncoid.nix @@ -5,226 +5,243 @@ with lib; let cfg = config.services.syncoid; - # Extract the pool name of a local dataset (any dataset not containing "@") - localPoolName = d: optionals (d != null) ( - let m = builtins.match "([^/@]+)[^@]*" d; in - optionals (m != null) m); + # Extract local dasaset names (so no datasets containing "@") + localDatasetName = d: optionals (d != null) ( + let m = builtins.match "([^/@]+[^@]*)" d; in + optionals (m != null) m + ); # Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html escapeUnitName = name: lib.concatMapStrings (s: if lib.isList s then "-" else s) - (builtins.split "[^a-zA-Z0-9_.\\-]+" name); -in { + (builtins.split "[^a-zA-Z0-9_.\\-]+" name); - # Interface + # Function to build "zfs allow" and "zfs unallow" commands for the + # filesystems we've delegated permissions to. + buildAllowCommand = zfsAction: permissions: dataset: lib.escapeShellArgs [ + # Here we explicitly use the booted system to guarantee the stable API needed by ZFS + "-+/run/booted-system/sw/bin/zfs" + zfsAction + cfg.user + (concatStringsSep "," permissions) + dataset + ]; +in +{ - options.services.syncoid = { - enable = mkEnableOption "Syncoid ZFS synchronization service"; + # Interface - interval = mkOption { - type = types.str; - default = "hourly"; - example = "*-*-* *:15:00"; - description = '' - Run syncoid at this interval. The default is to run hourly. + options.services.syncoid = { + enable = mkEnableOption "Syncoid ZFS synchronization service"; - The format is described in - <citerefentry><refentrytitle>systemd.time</refentrytitle> - <manvolnum>7</manvolnum></citerefentry>. - ''; - }; + interval = mkOption { + type = types.str; + default = "hourly"; + example = "*-*-* *:15:00"; + description = '' + Run syncoid at this interval. The default is to run hourly. - user = mkOption { - type = types.str; - default = "syncoid"; - example = "backup"; - description = '' - 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. - ''; - }; + The format is described in + <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry>. + ''; + }; - group = mkOption { - type = types.str; - default = "syncoid"; - example = "backup"; - description = "The group for the service."; - }; + user = mkOption { + type = types.str; + default = "syncoid"; + example = "backup"; + description = '' + 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. + ''; + }; - sshKey = mkOption { - type = types.nullOr types.path; - # Prevent key from being copied to store - apply = mapNullable toString; - default = null; - description = '' - SSH private key file to use to login to the remote system. Can be - overridden in individual commands. - ''; - }; + group = mkOption { + type = types.str; + default = "syncoid"; + example = "backup"; + description = "The group for the service."; + }; - commonArgs = mkOption { - type = types.listOf types.str; - default = []; - example = [ "--no-sync-snap" ]; - description = '' - Arguments to add to every syncoid command, unless disabled for that - command. See - <link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/> - for available options. - ''; - }; + sshKey = mkOption { + type = types.nullOr types.path; + # Prevent key from being copied to store + apply = mapNullable toString; + default = null; + description = '' + SSH private key file to use to login to the remote system. Can be + overridden in individual commands. + ''; + }; - service = mkOption { - type = types.attrs; - default = {}; - description = '' - Systemd configuration common to all syncoid services. - ''; - }; + commonArgs = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--no-sync-snap" ]; + description = '' + Arguments to add to every syncoid command, unless disabled for that + command. See + <link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/> + for available options. + ''; + }; - commands = mkOption { - type = types.attrsOf (types.submodule ({ name, ... }: { - options = { - source = mkOption { - type = types.str; - example = "pool/dataset"; - description = '' - Source ZFS dataset. Can be either local or remote. Defaults to - the attribute name. - ''; - }; + service = mkOption { + type = types.attrs; + default = { }; + description = '' + Systemd configuration common to all syncoid services. + ''; + }; - target = mkOption { - type = types.str; - example = "user@server:pool/dataset"; - description = '' - Target ZFS dataset. Can be either local - (<replaceable>pool/dataset</replaceable>) or remote - (<replaceable>user@server:pool/dataset</replaceable>). - ''; - }; + commands = mkOption { + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + source = mkOption { + type = types.str; + example = "pool/dataset"; + description = '' + Source ZFS dataset. Can be either local or remote. Defaults to + the attribute name. + ''; + }; - recursive = mkEnableOption ''the transfer of child datasets''; + target = mkOption { + type = types.str; + example = "user@server:pool/dataset"; + description = '' + Target ZFS dataset. Can be either local + (<replaceable>pool/dataset</replaceable>) or remote + (<replaceable>user@server:pool/dataset</replaceable>). + ''; + }; - sshKey = mkOption { - type = types.nullOr types.path; - # Prevent key from being copied to store - apply = mapNullable toString; - description = '' - SSH private key file to use to login to the remote system. - Defaults to <option>services.syncoid.sshKey</option> option. - ''; - }; + recursive = mkEnableOption ''the transfer of child datasets''; - sendOptions = mkOption { - type = types.separatedString " "; - default = ""; - example = "Lc e"; - description = '' - Advanced options to pass to zfs send. Options are specified - without their leading dashes and separated by spaces. - ''; - }; + sshKey = mkOption { + type = types.nullOr types.path; + # Prevent key from being copied to store + apply = mapNullable toString; + description = '' + SSH private key file to use to login to the remote system. + Defaults to <option>services.syncoid.sshKey</option> option. + ''; + }; - recvOptions = mkOption { - type = types.separatedString " "; - default = ""; - example = "ux recordsize o compression=lz4"; - description = '' - Advanced options to pass to zfs recv. Options are specified - without their leading dashes and separated by spaces. - ''; - }; + sendOptions = mkOption { + type = types.separatedString " "; + default = ""; + example = "Lc e"; + description = '' + Advanced options to pass to zfs send. Options are specified + without their leading dashes and separated by spaces. + ''; + }; - useCommonArgs = mkOption { - type = types.bool; - default = true; - description = '' - Whether to add the configured common arguments to this command. - ''; - }; + recvOptions = mkOption { + type = types.separatedString " "; + default = ""; + example = "ux recordsize o compression=lz4"; + description = '' + Advanced options to pass to zfs recv. Options are specified + without their leading dashes and separated by spaces. + ''; + }; - service = mkOption { - type = types.attrs; - default = {}; - description = '' - Systemd configuration specific to this syncoid service. - ''; - }; + useCommonArgs = mkOption { + type = types.bool; + default = true; + description = '' + Whether to add the configured common arguments to this command. + ''; + }; - extraArgs = mkOption { - type = types.listOf types.str; - default = []; - example = [ "--sshport 2222" ]; - description = "Extra syncoid arguments for this command."; - }; + service = mkOption { + type = types.attrs; + default = { }; + description = '' + Systemd configuration specific to this syncoid service. + ''; }; - config = { - source = mkDefault name; - sshKey = mkDefault cfg.sshKey; + + extraArgs = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "--sshport 2222" ]; + description = "Extra syncoid arguments for this command."; }; - })); - default = {}; - example = literalExample '' - { - "pool/test".target = "root@target:pool/test"; - } - ''; - description = "Syncoid commands to run."; - }; + }; + config = { + source = mkDefault name; + sshKey = mkDefault cfg.sshKey; + }; + })); + default = { }; + example = literalExample '' + { + "pool/test".target = "root@target:pool/test"; + } + ''; + description = "Syncoid commands to run."; }; + }; - # Implementation + # Implementation - config = mkIf cfg.enable { - users = { - users = mkIf (cfg.user == "syncoid") { - syncoid = { - group = cfg.group; - isSystemUser = true; - # For syncoid to be able to create /var/lib/syncoid/.ssh/ - # and to use custom ssh_config or known_hosts. - home = "/var/lib/syncoid"; - createHome = false; - }; - }; - groups = mkIf (cfg.group == "syncoid") { - syncoid = {}; + config = mkIf cfg.enable { + users = { + users = mkIf (cfg.user == "syncoid") { + syncoid = { + group = cfg.group; + isSystemUser = true; + # For syncoid to be able to create /var/lib/syncoid/.ssh/ + # and to use custom ssh_config or known_hosts. + home = "/var/lib/syncoid"; + createHome = false; }; }; + groups = mkIf (cfg.group == "syncoid") { + syncoid = { }; + }; + }; - systemd.services = mapAttrs' (name: c: + systemd.services = mapAttrs' + (name: c: nameValuePair "syncoid-${escapeUnitName name}" (mkMerge [ - { description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}"; + { + description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}"; after = [ "zfs.target" ]; startAt = cfg.interval; # syncoid may need zpool to get feature@extensible_dataset path = [ "/run/booted-system/sw/bin/" ]; serviceConfig = { ExecStartPre = - map (pool: lib.escapeShellArgs [ - "+/run/booted-system/sw/bin/zfs" "allow" - cfg.user "bookmark,hold,send,snapshot,destroy" pool - # Permissions snapshot and destroy are in case --no-sync-snap is not used - ]) (localPoolName c.source) ++ - map (pool: lib.escapeShellArgs [ - "+/run/booted-system/sw/bin/zfs" "allow" - cfg.user "create,mount,receive,rollback" pool - ]) (localPoolName c.target); + # Permissions snapshot and destroy are in case --no-sync-snap is not used + (map (buildAllowCommand "allow" [ "bookmark" "hold" "send" "snapshot" "destroy" ]) (localDatasetName c.source)) ++ + (map (buildAllowCommand "allow" [ "create" "mount" "receive" "rollback" ]) (localDatasetName c.target)); + ExecStopPost = + # Permissions snapshot and destroy are in case --no-sync-snap is not used + (map (buildAllowCommand "unallow" [ "bookmark" "hold" "send" "snapshot" "destroy" ]) (localDatasetName c.source)) ++ + (map (buildAllowCommand "unallow" [ "create" "mount" "receive" "rollback" ]) (localDatasetName c.target)); ExecStart = lib.escapeShellArgs ([ "${pkgs.sanoid}/bin/syncoid" ] ++ optionals c.useCommonArgs cfg.commonArgs ++ optional c.recursive "-r" ++ optionals (c.sshKey != null) [ "--sshkey" c.sshKey ] ++ c.extraArgs - ++ [ "--sendoptions" c.sendOptions - "--recvoptions" c.recvOptions - "--no-privilege-elevation" - c.source c.target - ]); + ++ [ + "--sendoptions" + c.sendOptions + "--recvoptions" + c.recvOptions + "--no-privilege-elevation" + c.source + c.target + ]); User = cfg.user; Group = cfg.group; StateDirectory = [ "syncoid" ]; @@ -240,7 +257,7 @@ in { # systemd-analyze security | grep syncoid-'*' AmbientCapabilities = ""; CapabilityBoundingSet = ""; - DeviceAllow = ["/dev/zfs"]; + DeviceAllow = [ "/dev/zfs" ]; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; @@ -266,7 +283,7 @@ in { BindPaths = [ "/dev/zfs" ]; BindReadOnlyPaths = [ builtins.storeDir "/etc" "/run" "/bin/sh" ]; # Avoid useless mounting of RootDirectory= in the own RootDirectory= of ExecStart='s mount namespace. - InaccessiblePaths = ["-+/run/syncoid/${escapeUnitName name}"]; + InaccessiblePaths = [ "-+/run/syncoid/${escapeUnitName name}" ]; MountAPIVFS = true; # Create RootDirectory= in the host's mount namespace. RuntimeDirectory = [ "syncoid/${escapeUnitName name}" ]; @@ -277,8 +294,14 @@ in { # perf stat -x, 2>perf.log -e 'syscalls:sys_enter_*' syncoid … # awk >perf.syscalls -F "," '$1 > 0 {sub("syscalls:sys_enter_","",$3); print $3}' perf.log # systemd-analyze syscall-filter | grep -v -e '#' | sed -e ':loop; /^[^ ]/N; s/\n //; t loop' | grep $(printf ' -e \\<%s\\>' $(cat perf.syscalls)) | cut -f 1 -d ' ' - "~@aio" "~@chown" "~@keyring" "~@memlock" "~@privileged" - "~@resources" "~@setuid" "~@sync" "~@timer" + "~@aio" + "~@chown" + "~@keyring" + "~@memlock" + "~@privileged" + "~@resources" + "~@setuid" + "~@timer" ]; SystemCallArchitectures = "native"; # This is for BindPaths= and BindReadOnlyPaths= @@ -288,8 +311,9 @@ in { } cfg.service c.service - ])) cfg.commands; - }; + ])) + cfg.commands; + }; - meta.maintainers = with maintainers; [ julm lopsided98 ]; - } + meta.maintainers = with maintainers; [ julm lopsided98 ]; +} diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix index 0ca71b413ce..debb2a39705 100644 --- a/nixos/modules/services/backup/znapzend.nix +++ b/nixos/modules/services/backup/znapzend.nix @@ -279,7 +279,7 @@ let src_plan = plan; tsformat = timestampFormat; zend_delay = toString sendDelay; - } // fold (a: b: a // b) {} ( + } // foldr (a: b: a // b) {} ( map mkDestAttrs (builtins.attrValues destinations) ); diff --git a/nixos/modules/services/cluster/kubernetes/pki.nix b/nixos/modules/services/cluster/kubernetes/pki.nix index d9311d3e3a0..faf951d8157 100644 --- a/nixos/modules/services/cluster/kubernetes/pki.nix +++ b/nixos/modules/services/cluster/kubernetes/pki.nix @@ -189,7 +189,7 @@ in # manually paste it in place. Just symlink. # otherwise, create the target file, ready for users to insert the token - mkdir -p $(dirname ${certmgrAPITokenPath}) + mkdir -p "$(dirname "${certmgrAPITokenPath}")" if [ -f "${cfsslAPITokenPath}" ]; then ln -fs "${cfsslAPITokenPath}" "${certmgrAPITokenPath}" else diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index 35639e1bbc8..9b0a5bba2fe 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -194,7 +194,7 @@ let # We need to handle the last column specially here, because it's # open-ended (command + args). lines = [ labels labelDefaults ] ++ (map (l: init l ++ [""]) masterCf); - in fold foldLine (genList (const 0) (length labels)) lines; + in foldr foldLine (genList (const 0) (length labels)) lines; # Pad a string with spaces from the right (opposite of fixedWidthString). pad = width: str: let @@ -203,7 +203,7 @@ let in str + optionalString (padWidth > 0) padding; # It's + 2 here, because that's the amount of spacing between columns. - fullWidth = fold (width: acc: acc + width + 2) 0 maxWidths; + fullWidth = foldr (width: acc: acc + width + 2) 0 maxWidths; formatLine = line: concatStringsSep " " (zipListsWith pad maxWidths line); diff --git a/nixos/modules/services/misc/mx-puppet-discord.nix b/nixos/modules/services/misc/mx-puppet-discord.nix new file mode 100644 index 00000000000..11116f7c348 --- /dev/null +++ b/nixos/modules/services/misc/mx-puppet-discord.nix @@ -0,0 +1,120 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + dataDir = "/var/lib/mx-puppet-discord"; + registrationFile = "${dataDir}/discord-registration.yaml"; + cfg = config.services.mx-puppet-discord; + settingsFormat = pkgs.formats.json {}; + settingsFile = settingsFormat.generate "mx-puppet-discord-config.json" cfg.settings; + +in { + options = { + services.mx-puppet-discord = { + enable = mkEnableOption '' + mx-puppet-discord is a discord puppeting bridge for matrix. + It handles bridging private and group DMs, as well as Guilds (servers) + ''; + + settings = mkOption rec { + apply = recursiveUpdate default; + inherit (settingsFormat) type; + default = { + bridge.port = 8434; + presence = { + enabled = true; + interval = 500; + }; + provisioning.whitelist = [ ]; + relay.whitelist = [ ]; + + # variables are preceded by a colon. + namePatterns = { + user = ":name"; + userOverride = ":displayname"; + room = ":name"; + group = ":name"; + }; + + #defaults to sqlite but can be configured to use postgresql with + #connstring + database.filename = "${dataDir}/mx-puppet-discord/database.db"; + logging = { + console = "info"; + lineDateFormat = "MMM-D HH:mm:ss.SSS"; + }; + }; + example = literalExample '' + { + bridge = { + bindAddress = "localhost"; + domain = "example.com"; + homeserverUrl = "https://example.com"; + }; + + provisioning.whitelist = [ "@admin:example.com" ]; + relay.whitelist = [ "@.*:example.com" ]; + } + ''; + description = '' + <filename>config.yaml</filename> configuration as a Nix attribute set. + Configuration options should match those described in + <link xlink:href="https://github.com/matrix-discord/mx-puppet-discord/blob/master/sample.config.yaml"> + sample.config.yaml</link>. + ''; + }; + serviceDependencies = mkOption { + type = with types; listOf str; + default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + description = '' + List of Systemd services to require and wait for when starting the application service. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.mx-puppet-discord = { + description = '' + mx-puppet-discord is a discord puppeting bridge for matrix. + It handles bridging private and group DMs, as well as Guilds (servers). + ''; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ] ++ cfg.serviceDependencies; + after = [ "network-online.target" ] ++ cfg.serviceDependencies; + + preStart = '' + # generate the appservice's registration file if absent + if [ ! -f '${registrationFile}' ]; then + ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -r -c ${settingsFile} \ + -f ${registrationFile} + fi + ''; + + serviceConfig = { + Type = "simple"; + Restart = "always"; + + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + + DynamicUser = true; + PrivateTmp = true; + WorkingDirectory = pkgs.mx-puppet-discord; + StateDirectory = baseNameOf dataDir; + UMask = 0027; + + ExecStart = '' + ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -c ${settingsFile} + ''; + }; + }; + }; + + meta.maintainers = with maintainers; [ govanify ]; +} diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index d648de6a414..9182c2f2ed8 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -33,6 +33,7 @@ let "domain" "dovecot" "fritzbox" + "influxdb" "json" "jitsi" "kea" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix new file mode 100644 index 00000000000..ba45173e946 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, options }: + +with lib; + +let + cfg = config.services.prometheus.exporters.influxdb; +in +{ + port = 9122; + extraOpts = { + sampleExpiry = mkOption { + type = types.str; + default = "5m"; + example = "10m"; + description = "How long a sample is valid for"; + }; + udpBindAddress = mkOption { + type = types.str; + default = ":9122"; + example = "192.0.2.1:9122"; + description = "Address on which to listen for udp packets"; + }; + }; + serviceOpts = { + serviceConfig = { + RuntimeDirectory = "prometheus-influxdb-exporter"; + ExecStart = '' + ${pkgs.prometheus-influxdb-exporter}/bin/influxdb_exporter \ + --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ + --influxdb.sample-expiry ${cfg.sampleExpiry} ${concatStringsSep " " cfg.extraFlags} + ''; + }; + }; +} diff --git a/nixos/modules/services/networking/autossh.nix b/nixos/modules/services/networking/autossh.nix index a8d9a027e9f..245f2bfc2cf 100644 --- a/nixos/modules/services/networking/autossh.nix +++ b/nixos/modules/services/networking/autossh.nix @@ -79,7 +79,7 @@ in systemd.services = - lib.fold ( s : acc : acc // + lib.foldr ( s : acc : acc // { "autossh-${s.name}" = let diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 064018057cd..790de4ace01 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -6,7 +6,6 @@ let cfg = config.networking.networkmanager; basePackages = with pkgs; [ - crda modemmanager networkmanager networkmanager-fortisslvpn @@ -404,6 +403,8 @@ in { } ]; + hardware.wirelessRegulatoryDatabase = true; + environment.etc = with pkgs; { "NetworkManager/NetworkManager.conf".source = configFile; diff --git a/nixos/modules/services/networking/nylon.nix b/nixos/modules/services/networking/nylon.nix index bfc358cb12f..a20fa615af8 100644 --- a/nixos/modules/services/networking/nylon.nix +++ b/nixos/modules/services/networking/nylon.nix @@ -160,7 +160,7 @@ in users.groups.nylon.gid = config.ids.gids.nylon; - systemd.services = fold (a: b: a // b) {} nylonUnits; + systemd.services = foldr (a: b: a // b) {} nylonUnits; }; } diff --git a/nixos/modules/services/networking/quicktun.nix b/nixos/modules/services/networking/quicktun.nix index fb783c83646..438e67d5ebb 100644 --- a/nixos/modules/services/networking/quicktun.nix +++ b/nixos/modules/services/networking/quicktun.nix @@ -87,7 +87,7 @@ with lib; }; config = mkIf (cfg != []) { - systemd.services = fold (a: b: a // b) {} ( + systemd.services = foldr (a: b: a // b) {} ( mapAttrsToList (name: qtcfg: { "quicktun-${name}" = { wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 28348c7893a..3c58cd9ddad 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -25,41 +25,43 @@ let folder.enable ) cfg.declarative.folders); - # get the api key by parsing the config.xml - getApiKey = pkgs.writers.writeDash "getAPIKey" '' - ${pkgs.libxml2}/bin/xmllint \ - --xpath 'string(configuration/gui/apikey)'\ - ${cfg.configDir}/config.xml - ''; - updateConfig = pkgs.writers.writeDash "merge-syncthing-config" '' set -efu - # wait for syncthing port to open - until ${pkgs.curl}/bin/curl -Ss ${cfg.guiAddress} -o /dev/null; do - sleep 1 - done - - API_KEY=$(${getApiKey}) - OLD_CFG=$(${pkgs.curl}/bin/curl -Ss \ - -H "X-API-Key: $API_KEY" \ - ${cfg.guiAddress}/rest/system/config) - - # generate the new config by merging with the nixos config options - NEW_CFG=$(echo "$OLD_CFG" | ${pkgs.jq}/bin/jq -s '.[] as $in | $in * { - "devices": (${builtins.toJSON devices}${optionalString (! cfg.declarative.overrideDevices) " + $in.devices"}), - "folders": (${builtins.toJSON folders}${optionalString (! cfg.declarative.overrideFolders) " + $in.folders"}) - }') - - # POST the new config to syncthing - echo "$NEW_CFG" | ${pkgs.curl}/bin/curl -Ss \ - -H "X-API-Key: $API_KEY" \ - ${cfg.guiAddress}/rest/system/config -d @- - - # restart syncthing after sending the new config - ${pkgs.curl}/bin/curl -Ss \ - -H "X-API-Key: $API_KEY" \ - -X POST \ - ${cfg.guiAddress}/rest/system/restart + + # get the api key by parsing the config.xml + while + ! api_key=$(${pkgs.libxml2}/bin/xmllint \ + --xpath 'string(configuration/gui/apikey)' \ + ${cfg.configDir}/config.xml) + do sleep 1; done + + curl() { + while + ${pkgs.curl}/bin/curl -Ss -H "X-API-Key: $api_key" \ + --retry 100 --retry-delay 1 --retry-connrefused "$@" + status=$? + [ "$status" -eq 52 ] # retry on empty reply from server + do sleep 1; done + return "$status" + } + + # query the old config + old_cfg=$(curl ${cfg.guiAddress}/rest/config) + + # generate the new config by merging with the NixOS config options + new_cfg=$(echo "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { + "devices": (${builtins.toJSON devices}${optionalString (! cfg.declarative.overrideDevices) " + .devices"}), + "folders": (${builtins.toJSON folders}${optionalString (! cfg.declarative.overrideFolders) " + .folders"}) + } * ${builtins.toJSON cfg.declarative.extraOptions}') + + # send the new config + curl -X PUT -d "$new_cfg" ${cfg.guiAddress}/rest/config + + # restart Syncthing if required + if curl ${cfg.guiAddress}/rest/config/restart-required | + ${pkgs.jq}/bin/jq -e .requiresRestart > /dev/null; then + curl -X POST ${cfg.guiAddress}/rest/system/restart + fi ''; in { ###### interface @@ -77,7 +79,7 @@ in { type = types.nullOr types.str; default = null; description = '' - Path to users cert.pem file, will be copied into the syncthing's + Path to users cert.pem file, will be copied into Syncthing's <literal>configDir</literal> ''; }; @@ -86,7 +88,7 @@ in { type = types.nullOr types.str; default = null; description = '' - Path to users key.pem file, will be copied into the syncthing's + Path to users key.pem file, will be copied into Syncthing's <literal>configDir</literal> ''; }; @@ -105,7 +107,7 @@ in { devices = mkOption { default = {}; description = '' - Peers/devices which syncthing should communicate with. + Peers/devices which Syncthing should communicate with. ''; example = { bigbox = { @@ -168,7 +170,7 @@ in { folders = mkOption { default = {}; description = '' - folders which should be shared by syncthing. + Folders which should be shared by Syncthing. ''; example = literalExample '' { @@ -227,7 +229,7 @@ in { versioning = mkOption { default = null; description = '' - How to keep changed/deleted files with syncthing. + How to keep changed/deleted files with Syncthing. There are 4 different types of versioning with different parameters. See https://docs.syncthing.net/users/versioning.html ''; @@ -335,10 +337,21 @@ in { upstream's docs</link>. ''; }; - }; })); }; + + extraOptions = mkOption { + type = types.addCheck (pkgs.formats.json {}).type isAttrs; + default = {}; + description = '' + Extra configuration options for Syncthing. + ''; + example = { + options.localAnnounceEnabled = false; + gui.theme = "black"; + }; + }; }; guiAddress = mkOption { @@ -378,7 +391,7 @@ in { default = null; example = "socks5://address.com:1234"; description = '' - Overwrites all_proxy environment variable for the syncthing process to + Overwrites all_proxy environment variable for the Syncthing process to the given value. This is normaly used to let relay client connect through SOCKS5 proxy server. ''; @@ -412,7 +425,7 @@ in { Open the default ports in the firewall: - TCP 22000 for transfers - UDP 21027 for discovery - If multiple users are running syncthing on this machine, you will need to manually open a set of ports for each instance and leave this disabled. + If multiple users are running Syncthing on this machine, you will need to manually open a set of ports for each instance and leave this disabled. Alternatively, if are running only a single instance on this machine using the default ports, enable this. ''; }; @@ -431,7 +444,7 @@ in { imports = [ (mkRemovedOptionModule ["services" "syncthing" "useInotify"] '' - This option was removed because syncthing now has the inotify functionality included under the name "fswatcher". + This option was removed because Syncthing now has the inotify functionality included under the name "fswatcher". It can be enabled on a per-folder basis through the webinterface. '') ]; @@ -516,8 +529,9 @@ in { }; }; syncthing-init = mkIf ( - cfg.declarative.devices != {} || cfg.declarative.folders != {} + cfg.declarative.devices != {} || cfg.declarative.folders != {} || cfg.declarative.extraOptions != {} ) { + description = "Syncthing configuration updater"; after = [ "syncthing.service" ]; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix index b6afd83a9ab..9e433ad1a98 100644 --- a/nixos/modules/services/networking/tinc.nix +++ b/nixos/modules/services/networking/tinc.nix @@ -351,7 +351,7 @@ in config = mkIf (cfg.networks != { }) { - environment.etc = fold (a: b: a // b) { } + environment.etc = foldr (a: b: a // b) { } (flip mapAttrsToList cfg.networks (network: data: flip mapAttrs' data.hosts (host: text: nameValuePair ("tinc/${network}/hosts/${host}") diff --git a/nixos/modules/services/networking/wakeonlan.nix b/nixos/modules/services/networking/wakeonlan.nix index 35ff67937fc..f41b6ec2740 100644 --- a/nixos/modules/services/networking/wakeonlan.nix +++ b/nixos/modules/services/networking/wakeonlan.nix @@ -19,7 +19,7 @@ let ${ethtool} -s ${interface} ${methodParameter {inherit method password;}} ''; - concatStrings = fold (x: y: x + y) ""; + concatStrings = foldr (x: y: x + y) ""; lines = concatStrings (map (l: line l) interfaces); in diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index c0a4ce40760..494d21cc867 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -241,7 +241,8 @@ in { environment.systemPackages = [ package ]; services.dbus.packages = [ package ]; - services.udev.packages = [ pkgs.crda ]; + + hardware.wirelessRegulatoryDatabase = true; # FIXME: start a separate wpa_supplicant instance per interface. systemd.services.wpa_supplicant = let diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 4e2f25cd27f..d3e4923a993 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -125,7 +125,7 @@ let else showWarnings config.warnings baseSystem; # Replace runtime dependencies - system = fold ({ oldDependency, newDependency }: drv: + system = foldr ({ oldDependency, newDependency }: drv: pkgs.replaceDependency { inherit oldDependency newDependency drv; } ) baseSystemAssertWarn config.system.replaceRuntimeDependencies; diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index c6ec9acd54c..e183bc3648c 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -75,7 +75,7 @@ let else "${convertedFont}"); }); - bootDeviceCounters = fold (device: attr: attr // { ${device} = (attr.${device} or 0) + 1; }) {} + bootDeviceCounters = foldr (device: attr: attr // { ${device} = (attr.${device} or 0) + 1; }) {} (concatMap (args: args.devices) cfg.mirroredBoots); convertedFont = (pkgs.runCommand "grub-font-converted.pf2" {} diff --git a/nixos/modules/tasks/encrypted-devices.nix b/nixos/modules/tasks/encrypted-devices.nix index dd337de9869..06117d19af4 100644 --- a/nixos/modules/tasks/encrypted-devices.nix +++ b/nixos/modules/tasks/encrypted-devices.nix @@ -8,7 +8,7 @@ let keyedEncDevs = filter (dev: dev.encrypted.keyFile != null) encDevs; keylessEncDevs = filter (dev: dev.encrypted.keyFile == null) encDevs; anyEncrypted = - fold (j: v: v || j.encrypted.enable) false encDevs; + foldr (j: v: v || j.encrypted.enable) false encDevs; encryptedFSOptions = { diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index d9f7ce5d2c3..ea13d396c46 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -333,15 +333,15 @@ in set -eu # if the pstore module is builtin it will have mounted the persistent store automatically. it may also be already mounted for other reasons. ${pkgs.util-linux}/bin/mountpoint -q /sys/fs/pstore || ${pkgs.util-linux}/bin/mount -t pstore -o nosuid,noexec,nodev pstore /sys/fs/pstore - # wait up to five seconds (arbitrary, happened within one in testing) for the backend to be registered and the files to appear. a systemd path unit cannot detect this happening; and succeeding after a restart would not start dependent units. - TRIES=50 + # wait up to 1.5 seconds for the backend to be registered and the files to appear. a systemd path unit cannot detect this happening; and succeeding after a restart would not start dependent units. + TRIES=15 while [ "$(cat /sys/module/pstore/parameters/backend)" = "(null)" ]; do if (( $TRIES )); then sleep 0.1 TRIES=$((TRIES-1)) else echo "Persistent Storage backend was not registered in time." >&2 - exit 1 + break fi done ''; |