From 2ec19a64cc2d4e5dcf0c85bc855f12a1a6576e32 Mon Sep 17 00:00:00 2001 From: David Wronek Date: Sun, 7 Dec 2025 21:37:36 +0100 Subject: [PATCH 01/26] nixos/firewall-nftables: fix multicast ping We can currently observe that pinging the multicast IPv6 address ff02::1 does not work as expected. This is because conntrack is marking the ICMPv6 replies as invalid and thus is dropping them. This can behaviour can be seen with these commands: 1. Get handle of the rule above the conntrack rule: ``` nft -a list ruleset inet ``` 2. Insert a rule to log all packets marked as invalid by conntrack: ``` nft insert rule inet nixos-fw \ input position ct state invalid \ log prefix \"ct invalid: \" ``` 3. Starting pinging ff02::1 and observe dmesg This change adds a rule to allow all ICMPv6 echo replies (type 129) before the conntrack rule starts taking action. Signed-off-by: David Wronek --- nixos/modules/services/networking/firewall-nftables.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nixos/modules/services/networking/firewall-nftables.nix b/nixos/modules/services/networking/firewall-nftables.nix index a22fc29d35ff..093160e78dbf 100644 --- a/nixos/modules/services/networking/firewall-nftables.nix +++ b/nixos/modules/services/networking/firewall-nftables.nix @@ -117,6 +117,10 @@ in ifaceSet != "" ) ''iifname { ${ifaceSet} } accept comment "trusted interfaces"''} + # Multicast ICMPv6 echo replies get marked as invalid by conntrack. + # Accept them before conntrack to avoid dropped replies. + icmpv6 type echo-reply accept + # Some ICMPv6 types like NDP is untracked ct state vmap { invalid : drop, From b4bdc1b3773e487a577b57b4daaf91157fa47026 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sat, 13 Dec 2025 17:18:32 +0100 Subject: [PATCH 02/26] wolfssl: 5.8.2 -> 5.8.4 Fixes CVE-2025-12888, CVE-2025-11936, CVE-2025-11935, CVE-2025-11934, CVE-2025-11933, CVE-2025-11931, CVE-2025-11932 and CVE-2025-12889. Fixes #470470 Fixes #470471 Changes: https://github.com/wolfSSL/wolfssl/releases/tag/v5.8.4-stable --- pkgs/by-name/wo/wolfssl/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/wo/wolfssl/package.nix b/pkgs/by-name/wo/wolfssl/package.nix index b85e2c2016e0..e904c4dfefcc 100644 --- a/pkgs/by-name/wo/wolfssl/package.nix +++ b/pkgs/by-name/wo/wolfssl/package.nix @@ -17,13 +17,13 @@ }: stdenv.mkDerivation (finalAttrs: { pname = "wolfssl-${variant}"; - version = "5.8.2"; + version = "5.8.4"; src = fetchFromGitHub { owner = "wolfSSL"; repo = "wolfssl"; tag = "v${finalAttrs.version}-stable"; - hash = "sha256-rWBfpI6tdpKvQA/XdazBvU5hzyai5PtKRBpM4iplZDU="; + hash = "sha256-vfJKmDdM0r591t5GnuSS7NyiUYXCQOTKbWLVydB3N9s="; }; postPatch = '' From 8165c8d96a0a114b6455cce23d31f94e26eee63f Mon Sep 17 00:00:00 2001 From: Alois Wohlschlager Date: Mon, 8 Dec 2025 17:25:16 +0100 Subject: [PATCH 03/26] nixos/nix-daemon: remove obsolete compatibility code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * util-linux was used for ionice, replaced by systemd directives in 2012 [1]. * gzip was used for compressing stuff sent over ssh, replaced by the `-C` option in Nix 1.8 [2]. * Conditionals for versions less than 2.8 (or 2.3) can be removed, as they are not supported any more [3]. * Some systemd directives are already in the upstream service file of all supported Nix and Lix versions, and are removed. For cgroup delegation, this is only strictly true for Lix ≥2.94; Lix 2.93 does not support it at all yet, and Nix doesn't use the supervisor group at all (I haven't investigated whether it creates one itself or is just broken entirely, but in any case the creation of the empty cgroup in the module will not help). [1] https://github.com/NixOS/nixpkgs/commit/88f94d76bcce27b42c748e6f2a7691d0659e5513 [2] https://github.com/NixOS/nix/commit/7f7d4ab68649b2f5530143e8cfa95fc785ae9937 [3] https://github.com/NixOS/nixpkgs/commit/fa0cba1c398faad0b810555daea3bfeb05719a8c --- nixos/modules/services/system/nix-daemon.nix | 29 ++------------------ 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/nixos/modules/services/system/nix-daemon.nix b/nixos/modules/services/system/nix-daemon.nix index 2c4769da5764..9c3fba3f6dba 100644 --- a/nixos/modules/services/system/nix-daemon.nix +++ b/nixos/modules/services/system/nix-daemon.nix @@ -16,10 +16,6 @@ let nixPackage = cfg.package.out; - # nixVersion is an attribute which defines the implementation version. - # This is useful for Nix implementations which don't follow Nix's versioning. - isNixAtLeast = lib.versionAtLeast (nixPackage.nixVersion or (lib.getVersion nixPackage)); - makeNixBuildUser = nr: { name = "nixbld${toString nr}"; value = { @@ -196,26 +192,15 @@ in systemd.packages = [ nixPackage ]; - systemd.tmpfiles = lib.mkMerge [ - (lib.mkIf (isNixAtLeast "2.8") { - packages = [ nixPackage ]; - }) - (lib.mkIf (!isNixAtLeast "2.8") { - rules = [ - "d /nix/var/nix/daemon-socket 0755 root root - -" - ]; - }) - ]; + systemd.tmpfiles.packages = [ nixPackage ]; systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; systemd.services.nix-daemon = { path = [ nixPackage - pkgs.util-linux config.programs.ssh.package - ] - ++ lib.optionals cfg.distributedBuilds [ pkgs.gzip ]; + ]; environment = cfg.envVars @@ -224,15 +209,10 @@ in } // config.networking.proxy.envVars; - unitConfig.RequiresMountsFor = "/nix/store"; - serviceConfig = { CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; IOSchedulingClass = cfg.daemonIOSchedClass; IOSchedulingPriority = cfg.daemonIOSchedPriority; - LimitNOFILE = 1048576; - Delegate = "yes"; - DelegateSubgroup = "supervisor"; }; restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; @@ -287,10 +267,7 @@ in services.displayManager.hiddenUsers = lib.attrNames nixbldUsers; # Legacy configuration conversion. - nix.settings = lib.mkMerge [ - (lib.mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; }) - ]; - + nix.settings.sandbox-fallback = false; }; } From a6c7a5b4b5f7df210bbe079fa649dc96e0f8518f Mon Sep 17 00:00:00 2001 From: Alois Wohlschlager Date: Mon, 8 Dec 2025 17:25:16 +0100 Subject: [PATCH 04/26] nixos/lix: init Over time, it is expected that the setups for Lix and Nix will diverge in some ways. To prevent cluttering the modules too much, we will introduce a separate Lix module. It begins its existence as a fork of the nix-daemon module, right now without major changes, although this will change soon. It is also slightly weird due to not having any option definitions on its own and instead dispatching on the pname of `nix.package`, which is done for backwards compatibility (particularly on 25.11), and will also change soon by the gradual introduction of a separate `programs.lix` option subtree. --- nixos/modules/module-list.nix | 1 + nixos/modules/programs/lix.nix | 115 +++++++++++++++++++ nixos/modules/services/system/nix-daemon.nix | 2 +- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 nixos/modules/programs/lix.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 2df1045248b5..7dd29a7dafff 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -256,6 +256,7 @@ ./programs/less.nix ./programs/liboping.nix ./programs/light.nix + ./programs/lix.nix ./programs/localsend.nix ./programs/mdevctl.nix ./programs/mepo.nix diff --git a/nixos/modules/programs/lix.nix b/nixos/modules/programs/lix.nix new file mode 100644 index 000000000000..7499121b862a --- /dev/null +++ b/nixos/modules/programs/lix.nix @@ -0,0 +1,115 @@ +{ + config, + lib, + pkgs, + ... +}: +let + + cfg = config.nix; + + nixPackage = cfg.package.out; + + makeNixBuildUser = nr: { + name = "nixbld${toString nr}"; + value = { + description = "Lix build user ${toString nr}"; + uid = builtins.add config.ids.uids.nixbld nr; + isSystemUser = true; + group = "nixbld"; + extraGroups = [ "nixbld" ]; + }; + }; + + nixbldUsers = lib.listToAttrs (map makeNixBuildUser (lib.range 1 cfg.nrBuildUsers)); + +in + +{ + config = lib.mkIf (cfg.enable && nixPackage.pname == "lix") { + environment.systemPackages = [ + nixPackage + pkgs.nix-info + ] + ++ lib.optional (config.programs.bash.completion.enable) pkgs.nix-bash-completions; + + systemd.packages = [ nixPackage ]; + + systemd.tmpfiles.packages = [ nixPackage ]; + + systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; + + systemd.services.nix-daemon = { + path = [ + nixPackage + config.programs.ssh.package + ]; + + environment = + cfg.envVars + // { + CURL_CA_BUNDLE = config.security.pki.caBundle; + } + // config.networking.proxy.envVars; + + serviceConfig = { + CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; + IOSchedulingClass = cfg.daemonIOSchedClass; + IOSchedulingPriority = cfg.daemonIOSchedPriority; + }; + + restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; + + # `stopIfChanged = false` changes to switch behavior + # from stop -> update units -> start + # to update units -> restart + # + # The `stopIfChanged` setting therefore controls a trade-off between a + # more predictable lifecycle, which runs the correct "version" of + # the `ExecStop` line, and on the other hand the availability of + # sockets during the switch, as the effectiveness of the stop operation + # depends on the socket being stopped as well. + # + # As `nix-daemon.service` does not make use of `ExecStop`, we prefer + # to keep the socket up and available. This is important for machines + # that run Nix-based services, such as automated build, test, and deploy + # services, that expect the daemon socket to be available at all times. + # + # Notably, the Nix client does not retry on failure to connect to the + # daemon socket, and the in-process RemoteStore instance will disable + # itself. This makes retries infeasible even for services that are + # aware of the issue. Failure to connect can affect not only new client + # processes, but also new RemoteStore instances in existing processes, + # as well as existing RemoteStore instances that have not saturated + # their connection pool. + # + # Also note that `stopIfChanged = true` does not kill existing + # connection handling daemons, as one might wish to happen before a + # breaking Nix upgrade (which is rare). The daemon forks that handle + # the individual connections split off into their own sessions, causing + # them not to be stopped by systemd. + # If a Nix upgrade does require all existing daemon processes to stop, + # nix-daemon must do so on its own accord, and only when the new version + # starts and detects that Nix's persistent state needs an upgrade. + stopIfChanged = false; + + }; + + # Set up the environment variables for running Nix. + environment.sessionVariables = cfg.envVars; + + nix.nrBuildUsers = lib.mkDefault ( + if cfg.settings.auto-allocate-uids or false then + 0 + else + lib.max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs) + ); + + users.users = nixbldUsers; + + services.displayManager.hiddenUsers = lib.attrNames nixbldUsers; + + # Legacy configuration conversion. + nix.settings.sandbox-fallback = false; + }; +} diff --git a/nixos/modules/services/system/nix-daemon.nix b/nixos/modules/services/system/nix-daemon.nix index 9c3fba3f6dba..ef740b9ba8d9 100644 --- a/nixos/modules/services/system/nix-daemon.nix +++ b/nixos/modules/services/system/nix-daemon.nix @@ -183,7 +183,7 @@ in ###### implementation - config = lib.mkIf cfg.enable { + config = lib.mkIf (cfg.enable && nixPackage.pname != "lix") { environment.systemPackages = [ nixPackage pkgs.nix-info From d82e12e0dd8f7a969ab95fc6d7195ffcc2c4e62f Mon Sep 17 00:00:00 2001 From: Alois Wohlschlager Date: Sun, 14 Dec 2025 14:29:33 +0100 Subject: [PATCH 05/26] nixos/lix: prepare for socket activation changes After [1], nix-daemon will be socket-activated, and the service options need to be set on the template unit. In the meantime, it does approximately nothing and is harmless. [1] https://gerrit.lix.systems/c/lix/+/4719 --- nixos/modules/programs/lix.nix | 117 ++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/nixos/modules/programs/lix.nix b/nixos/modules/programs/lix.nix index 7499121b862a..d87ff84eafba 100644 --- a/nixos/modules/programs/lix.nix +++ b/nixos/modules/programs/lix.nix @@ -10,6 +10,26 @@ let nixPackage = cfg.package.out; + commonNixDaemonConfig = { + path = [ + nixPackage + config.programs.ssh.package + ]; + + environment = + cfg.envVars + // { + CURL_CA_BUNDLE = config.security.pki.caBundle; + } + // config.networking.proxy.envVars; + + serviceConfig = { + CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; + IOSchedulingClass = cfg.daemonIOSchedClass; + IOSchedulingPriority = cfg.daemonIOSchedPriority; + }; + }; + makeNixBuildUser = nr: { name = "nixbld${toString nr}"; value = { @@ -39,61 +59,54 @@ in systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; - systemd.services.nix-daemon = { - path = [ - nixPackage - config.programs.ssh.package - ]; + systemd.services."nix-daemon@" = lib.mkMerge [ + commonNixDaemonConfig + { + # Do not kill connections serving established connections on upgrade. + restartIfChanged = false; + } + ]; - environment = - cfg.envVars - // { - CURL_CA_BUNDLE = config.security.pki.caBundle; - } - // config.networking.proxy.envVars; + systemd.services.nix-daemon = lib.mkMerge [ + commonNixDaemonConfig + { + restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; - serviceConfig = { - CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; - IOSchedulingClass = cfg.daemonIOSchedClass; - IOSchedulingPriority = cfg.daemonIOSchedPriority; - }; + # `stopIfChanged = false` changes to switch behavior + # from stop -> update units -> start + # to update units -> restart + # + # The `stopIfChanged` setting therefore controls a trade-off between a + # more predictable lifecycle, which runs the correct "version" of + # the `ExecStop` line, and on the other hand the availability of + # sockets during the switch, as the effectiveness of the stop operation + # depends on the socket being stopped as well. + # + # As `nix-daemon.service` does not make use of `ExecStop`, we prefer + # to keep the socket up and available. This is important for machines + # that run Nix-based services, such as automated build, test, and deploy + # services, that expect the daemon socket to be available at all times. + # + # Notably, the Nix client does not retry on failure to connect to the + # daemon socket, and the in-process RemoteStore instance will disable + # itself. This makes retries infeasible even for services that are + # aware of the issue. Failure to connect can affect not only new client + # processes, but also new RemoteStore instances in existing processes, + # as well as existing RemoteStore instances that have not saturated + # their connection pool. + # + # Also note that `stopIfChanged = true` does not kill existing + # connection handling daemons, as one might wish to happen before a + # breaking Nix upgrade (which is rare). The daemon forks that handle + # the individual connections split off into their own sessions, causing + # them not to be stopped by systemd. + # If a Nix upgrade does require all existing daemon processes to stop, + # nix-daemon must do so on its own accord, and only when the new version + # starts and detects that Nix's persistent state needs an upgrade. + stopIfChanged = false; - restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; - - # `stopIfChanged = false` changes to switch behavior - # from stop -> update units -> start - # to update units -> restart - # - # The `stopIfChanged` setting therefore controls a trade-off between a - # more predictable lifecycle, which runs the correct "version" of - # the `ExecStop` line, and on the other hand the availability of - # sockets during the switch, as the effectiveness of the stop operation - # depends on the socket being stopped as well. - # - # As `nix-daemon.service` does not make use of `ExecStop`, we prefer - # to keep the socket up and available. This is important for machines - # that run Nix-based services, such as automated build, test, and deploy - # services, that expect the daemon socket to be available at all times. - # - # Notably, the Nix client does not retry on failure to connect to the - # daemon socket, and the in-process RemoteStore instance will disable - # itself. This makes retries infeasible even for services that are - # aware of the issue. Failure to connect can affect not only new client - # processes, but also new RemoteStore instances in existing processes, - # as well as existing RemoteStore instances that have not saturated - # their connection pool. - # - # Also note that `stopIfChanged = true` does not kill existing - # connection handling daemons, as one might wish to happen before a - # breaking Nix upgrade (which is rare). The daemon forks that handle - # the individual connections split off into their own sessions, causing - # them not to be stopped by systemd. - # If a Nix upgrade does require all existing daemon processes to stop, - # nix-daemon must do so on its own accord, and only when the new version - # starts and detects that Nix's persistent state needs an upgrade. - stopIfChanged = false; - - }; + } + ]; # Set up the environment variables for running Nix. environment.sessionVariables = cfg.envVars; From f19b523d5c05d4f58256924cc8b05a7406127fa8 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 2 Dec 2025 03:21:28 +0100 Subject: [PATCH 06/26] mdbook: 0.4.52 -> 0.5.1 --- pkgs/by-name/md/mdbook/package.nix | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/pkgs/by-name/md/mdbook/package.nix b/pkgs/by-name/md/mdbook/package.nix index 6a21c8180575..010aabc320d4 100644 --- a/pkgs/by-name/md/mdbook/package.nix +++ b/pkgs/by-name/md/mdbook/package.nix @@ -8,7 +8,7 @@ installShellFiles, }: let - version = "0.4.52"; + version = "0.5.1"; in rustPlatform.buildRustPackage rec { inherit version; @@ -18,18 +18,10 @@ rustPlatform.buildRustPackage rec { owner = "rust-lang"; repo = "mdBook"; tag = "v${version}"; - hash = "sha256-a3GSMz1+8Ve5cp4x1NjBlsCU/wMC4Jl3/H9qx7+1XlI="; + hash = "sha256-t7Qou3H6dlO97puWQGkPlyb0jjpGoYCrz041iZWWL/s="; }; - cargoHash = "sha256-wvTixSVHXglJM+nBMulZNZKF8pZfNd2G8Z+1PlAWmpk="; - - patches = [ - (fetchpatch2 { - name = "fix-rust-1.91-tests.patch"; - url = "https://github.com/rust-lang/mdBook/commit/841c68d05e763b031524a2b4d679f033cd15e64c.patch?full_index=1"; - hash = "sha256-KDQhmFX2TWamtdyssFL69MP3vg9LABb+bF8/7vaFsew="; - }) - ]; + cargoHash = "sha256-bJr0u025syrP/LGgIbXD0mRvQrvnnOntiaAfr/9tQ90="; nativeBuildInputs = [ installShellFiles ]; From 9163ecb93ed0bed7b38ca5b4010dc73162d0a86e Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 10 Dec 2025 17:04:32 +0100 Subject: [PATCH 07/26] nixVersions: apply mdbook 0.5 support patches --- pkgs/tools/package-management/nix/default.nix | 117 ++++++++++++------ 1 file changed, 78 insertions(+), 39 deletions(-) diff --git a/pkgs/tools/package-management/nix/default.nix b/pkgs/tools/package-management/nix/default.nix index 877ab89b4a8e..382971ff4db5 100644 --- a/pkgs/tools/package-management/nix/default.nix +++ b/pkgs/tools/package-management/nix/default.nix @@ -136,33 +136,56 @@ lib.makeExtensible ( version = "2.28.5"; hash = "sha256-oIfAHxO+BCtHXJXLHBnsKkGl1Pw+Uuq1PwNxl+lZ+Oc="; self_attribute_name = "nix_2_28"; + patches = [ + (fetchpatch2 { + name = "nix-2.28-14764-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/5a64138e862fe364e751c5c286e8db8c466aaee7.patch"; + hash = "sha256-K5TNroqSRH9j7vSzWw/6/b19mu7q+J5XPTDvJ3xVWlE="; + }) + ]; }; - nixComponents_2_29 = nixDependencies.callPackage ./modular/packages.nix rec { - version = "2.29.2"; - inherit maintainers teams; - otherSplices = generateSplicesForNixComponents "nixComponents_2_29"; - src = fetchFromGitHub { - owner = "NixOS"; - repo = "nix"; - tag = version; - hash = "sha256-50p2sG2RFuRnlS1/Vr5et0Rt+QDgfpNE2C2WWRztnbQ="; - }; - }; + nixComponents_2_29 = + (nixDependencies.callPackage ./modular/packages.nix rec { + version = "2.29.2"; + inherit maintainers teams; + otherSplices = generateSplicesForNixComponents "nixComponents_2_29"; + src = fetchFromGitHub { + owner = "NixOS"; + repo = "nix"; + tag = version; + hash = "sha256-50p2sG2RFuRnlS1/Vr5et0Rt+QDgfpNE2C2WWRztnbQ="; + }; + }).appendPatches + [ + (fetchpatch2 { + name = "nix-2.29-14763-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/0501ae1e4965549cbf1314e471f92f4226e46ef1.patch"; + hash = "sha256-w8WQfWxMtprDLoZUhrCm4zr6xZXKhoIirq3la0Y7/wU="; + }) + ]; nix_2_29 = addTests "nix_2_29" self.nixComponents_2_29.nix-everything; - nixComponents_2_30 = nixDependencies.callPackage ./modular/packages.nix rec { - version = "2.30.3"; - inherit maintainers teams; - otherSplices = generateSplicesForNixComponents "nixComponents_2_30"; - src = fetchFromGitHub { - owner = "NixOS"; - repo = "nix"; - tag = version; - hash = "sha256-kBuwzMgIE9Tmve0Rpp+q+YCsE2mw9d62M/950ViWeJ0="; - }; - }; + nixComponents_2_30 = + (nixDependencies.callPackage ./modular/packages.nix rec { + version = "2.30.3"; + inherit maintainers teams; + otherSplices = generateSplicesForNixComponents "nixComponents_2_30"; + src = fetchFromGitHub { + owner = "NixOS"; + repo = "nix"; + tag = version; + hash = "sha256-kBuwzMgIE9Tmve0Rpp+q+YCsE2mw9d62M/950ViWeJ0="; + }; + }).appendPatches + [ + (fetchpatch2 { + name = "nix-2.30-14695-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/5cbd7856de0a9c13351f98e32a1e26d0854d87fd.patch"; + hash = "sha256-w8WQfWxMtprDLoZUhrCm4zr6xZXKhoIirq3la0Y7/wU="; + }) + ]; nix_2_30 = addTests "nix_2_30" self.nixComponents_2_30.nix-everything; @@ -179,27 +202,43 @@ lib.makeExtensible ( }; }).appendPatches ( - # issues on darwin: https://github.com/NixOS/nixpkgs/pull/468208#issuecomment-3626314109 - lib.optional stdenv.isLinux (fetchpatch2 { - name = "nix-2.31-14240-sri-error-message.patch"; - url = "https://github.com/NixOS/nix/commit/56751b1cd2c4700c71c545f2246adf602c97fdf5.patch"; - hash = "sha256-CerSBAI+H2RqPp9jsCP0QIM2rZYx3yBZHVVUAztgc18="; - }) + [ + (fetchpatch2 { + name = "nix-2.31-14692-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/a4f5f365090980a6eeb2ef483e49c04bdefd71a8.patch"; + hash = "sha256-GOWZtHSzHovnD8iUknr61bo7y85i0BKdw3kVBGDfBX0="; + }) + ] + ++ + # issues on darwin: https://github.com/NixOS/nixpkgs/pull/468208#issuecomment-3626314109 + lib.optional stdenv.isLinux (fetchpatch2 { + name = "nix-2.31-14240-sri-error-message.patch"; + url = "https://github.com/NixOS/nix/commit/56751b1cd2c4700c71c545f2246adf602c97fdf5.patch"; + hash = "sha256-CerSBAI+H2RqPp9jsCP0QIM2rZYx3yBZHVVUAztgc18="; + }) ); nix_2_31 = addTests "nix_2_31" self.nixComponents_2_31.nix-everything; - nixComponents_2_32 = nixDependencies.callPackage ./modular/packages.nix rec { - version = "2.32.4"; - inherit (self.nix_2_31.meta) maintainers teams; - otherSplices = generateSplicesForNixComponents "nixComponents_2_32"; - src = fetchFromGitHub { - owner = "NixOS"; - repo = "nix"; - tag = version; - hash = "sha256-8QYnRyGOTm3h/Dp8I6HCmQzlO7C009Odqyp28pTWgcY="; - }; - }; + nixComponents_2_32 = + (nixDependencies.callPackage ./modular/packages.nix rec { + version = "2.32.4"; + inherit (self.nix_2_31.meta) maintainers teams; + otherSplices = generateSplicesForNixComponents "nixComponents_2_32"; + src = fetchFromGitHub { + owner = "NixOS"; + repo = "nix"; + tag = version; + hash = "sha256-8QYnRyGOTm3h/Dp8I6HCmQzlO7C009Odqyp28pTWgcY="; + }; + }).appendPatches + [ + (fetchpatch2 { + name = "nix-2.32-14693-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/ba5bede9f51f126b29aaa01a3170da281cef0231.patch"; + hash = "sha256-jY5fWnJSBfHRmB0RnBKeu3aYQ8wmDKYVqTj85cWVZRA="; + }) + ]; nix_2_32 = addTests "nix_2_32" self.nixComponents_2_32.nix-everything; From 50076c503162ad7b09ceb86eefbff7883f508168 Mon Sep 17 00:00:00 2001 From: David Laing Date: Mon, 15 Dec 2025 22:41:47 +0000 Subject: [PATCH 08/26] busybox: 1.36.1 -> 1.37.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove CVE patches now included upstream in 1.37.0: - CVE-2022-28391 (sockaddr2str/nslookup sanitization) - CVE-2022-48174 (shell segfault on malformed input) - CVE-2023-42363, CVE-2023-42364, CVE-2023-42365, CVE-2023-42366 (awk fixes) - tar TOCTOU symlink race condition Add patch to fix aarch64-linux build failure where sha1_process_block64_shaNI is x86-specific and needs architecture guards. Release notes: https://busybox.net/news.html Fix reference: https://lists.busybox.net/pipermail/busybox/2024-September/090943.html 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- pkgs/os-specific/linux/busybox/default.nix | 54 ++----------------- .../linux/busybox/fix-aarch64-sha1.patch | 24 +++++++++ 2 files changed, 29 insertions(+), 49 deletions(-) create mode 100644 pkgs/os-specific/linux/busybox/fix-aarch64-sha1.patch diff --git a/pkgs/os-specific/linux/busybox/default.nix b/pkgs/os-specific/linux/busybox/default.nix index 1142e8c1fc30..873d5ec4c91d 100644 --- a/pkgs/os-specific/linux/busybox/default.nix +++ b/pkgs/os-specific/linux/busybox/default.nix @@ -57,14 +57,14 @@ in stdenv.mkDerivation rec { pname = "busybox"; - version = "1.36.1"; + version = "1.37.0"; # Note to whoever is updating busybox: please verify that: # nix-build pkgs/stdenv/linux/make-bootstrap-tools.nix -A test # still builds after the update. src = fetchurl { url = "https://busybox.net/downloads/${pname}-${version}.tar.bz2"; - sha256 = "sha256-uMwkyVdNgJ5yecO+NJeVxdXOtv3xnKcJ+AzeUOR94xQ="; + sha256 = "sha256-MxHf8y50ZJn03w1d8E1+s5Y4LX4Qi7klDntRm4NwQ6Q="; }; hardeningDisable = [ @@ -77,53 +77,9 @@ stdenv.mkDerivation rec { # necessary when it's run from the Nix store as -busybox during # stdenv bootstrap. ./busybox-in-store.patch - # libbb: sockaddr2str: ensure only printable characters are returned for the hostname part - (fetchurl { - name = "CVE-2022-28391.patch"; - url = "https://git.alpinelinux.org/aports/plain/main/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch?id=ed92963eb55bbc8d938097b9ccb3e221a94653f4"; - sha256 = "sha256-yviw1GV+t9tbHbY7YNxEqPi7xEreiXVqbeRyf8c6Awo="; - }) - # nslookup: sanitize all printed strings with printable_string - (fetchurl { - name = "CVE-2022-28391.patch"; - url = "https://git.alpinelinux.org/aports/plain/main/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch?id=ed92963eb55bbc8d938097b9ccb3e221a94653f4"; - sha256 = "sha256-vl1wPbsHtXY9naajjnTicQ7Uj3N+EQ8pRNnrdsiow+w="; - }) - # shell: avoid segfault on ${0::0/0~09J} - # See also: https://bugs.busybox.net/show_bug.cgi?id=15216 - (fetchpatch { - name = "CVE-2022-48174.patch"; - url = "https://git.busybox.net/busybox/patch/?id=d417193cf37ca1005830d7e16f5fa7e1d8a44209"; - hash = "sha256-mpDEwYncpU6X6tmtj9xM2KCrB/v2ys5bYxmPPrhm6es="; - }) - # Make sure we don't read past the end of the string in next_token() - # when backslash is the last character in an (invalid) regexp. - # See also: https://bugs.busybox.net/show_bug.cgi?id=15874 - # This patch is also used by Alpine, see https://git.alpinelinux.org/aports/tree/main/busybox/0037-awk.c-fix-CVE-2023-42366-bug-15874.patch - (fetchpatch { - name = "CVE-2023-42366.patch"; - url = "https://bugs.busybox.net/attachment.cgi?id=9697"; - hash = "sha256-2eYfLZLjStea9apKXogff6sCAdG9yHx0ZsgUBaGfQIA="; - }) - # awk: fix use after free (CVE-2023-42363) - # See also: https://bugs.busybox.net/show_bug.cgi?id=15865 - (fetchpatch { - name = "CVE-2023-42363.patch"; - url = "https://git.launchpad.net/ubuntu/+source/busybox/plain/debian/patches/CVE-2023-42363.patch?id=c9d8a323b337d58e302717d41796aa0242963d5a"; - hash = "sha256-1W9Q8+yFkYQKzNTrvndie8QuaEbyAFL1ZASG2fPF+Z4="; - }) - # awk: fix ternary operator and precedence of = - # See also: https://bugs.busybox.net/show_bug.cgi?id=15871 https://bugs.busybox.net/show_bug.cgi?id=15868 - (fetchpatch { - name = "CVE-2023-42364_CVE-2023-42365.patch"; - url = "https://git.alpinelinux.org/aports/plain/main/busybox/CVE-2023-42364-CVE-2023-42365.patch?id=8a4bf5971168bf48201c05afda7bee0fbb188e13"; - hash = "sha256-nQPgT9eA1asCo38Z9X7LR9My0+Vz5YBPba3ARV3fWcc="; - }) - # tar: fix TOCTOU symlink race condition - (fetchurl { - url = "https://git.alpinelinux.org/aports/plain/main/busybox/0001-tar-fix-TOCTOU-symlink-race-condition.patch?id=9e42dea5fba84a8afad1f1910b7d3884128a567e"; - hash = "sha256-GmXQhwB1/IPVjXXpGi5RjRvuGJgIMIb7lQKB63m306g="; - }) + # Fix aarch64 build failure: sha1_process_block64_shaNI is x86-specific + # https://lists.busybox.net/pipermail/busybox/2024-September/090943.html + ./fix-aarch64-sha1.patch ] ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) ./clang-cross.patch; diff --git a/pkgs/os-specific/linux/busybox/fix-aarch64-sha1.patch b/pkgs/os-specific/linux/busybox/fix-aarch64-sha1.patch new file mode 100644 index 000000000000..83fe7a2bb6f1 --- /dev/null +++ b/pkgs/os-specific/linux/busybox/fix-aarch64-sha1.patch @@ -0,0 +1,24 @@ +From upstream commit fixing aarch64 build failure + +The sha1_process_block64_shaNI function is x86-specific and needs +architecture guards to prevent undeclared function errors on ARM64 +and other non-x86 platforms. + +This fixes the compile error: 'sha1_process_block64_shaNI' undeclared +(first use in this function) + +Reference: https://lists.busybox.net/pipermail/busybox/2024-September/090943.html +Upstream patch: https://www.mail-archive.com/busybox@busybox.net/msg29511.html + +--- a/libbb/hash_md5_sha.c ++++ b/libbb/hash_md5_sha.c +@@ -1313,7 +1313,9 @@ unsigned FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) + hash_size = 8; + if (ctx->process_block == sha1_process_block64 + #if ENABLE_SHA1_HWACCEL ++# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + || ctx->process_block == sha1_process_block64_shaNI ++# endif + #endif + ) { + hash_size = 5; From 5cd20ff81da5232849eb782eb47af4078f606273 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 16 Dec 2025 15:46:06 +0100 Subject: [PATCH 09/26] lixPackageSets: apply mdbook 0.5 support patches Apply patches to lix_2_93, lix_2_94, and git versions to support building documentation with mdbook 0.5. The patch is from upstream Lix commit 54df89f6, which maintains compatibility with both mdbook 0.4.x and 0.5.x. https://git.lix.systems/lix-project/lix/issues/1051 --- pkgs/tools/package-management/lix/default.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkgs/tools/package-management/lix/default.nix b/pkgs/tools/package-management/lix/default.nix index ebf4a6fd6b09..b4eaa2d80269 100644 --- a/pkgs/tools/package-management/lix/default.nix +++ b/pkgs/tools/package-management/lix/default.nix @@ -30,6 +30,14 @@ confDir ? "/etc", }: let + # Support for mdbook >= 0.5, https://git.lix.systems/lix-project/lix/issues/1051 + lixMdbookPatch = fetchpatch2 { + name = "lix-mdbook-0.5-support.patch"; + url = "https://git.lix.systems/lix-project/lix/commit/54df89f601b3b4502a5c99173c9563495265d7e7.patch"; + excludes = [ "package.nix" ]; + hash = "sha256-uu/SIG8fgVVWhsGxmszTPHwe4SQtLgbxdShOMKbeg2w="; + }; + makeLixScope = { attrName, @@ -214,6 +222,8 @@ lib.makeExtensible ( url = "https://git.lix.systems/lix-project/lix/commit/b6d5670bcffebdd43352ea79b36135e35a8148d9.patch"; hash = "sha256-f4s0TR5MhNMNM5TYLOR7K2/1rtZ389KDjTCKFVK0OcE="; }) + + lixMdbookPatch ]; }; }; @@ -237,6 +247,8 @@ lib.makeExtensible ( inherit src; hash = "sha256-APm8m6SVEAO17BBCka13u85/87Bj+LePP7Y3zHA3Mpg="; }; + + patches = [ lixMdbookPatch ]; }; }; @@ -259,6 +271,8 @@ lib.makeExtensible ( inherit src; hash = "sha256-APm8m6SVEAO17BBCka13u85/87Bj+LePP7Y3zHA3Mpg="; }; + + patches = [ lixMdbookPatch ]; }; }; From 2ce35ff13f7bc48b421eadf94d12cf055e000383 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 17 Dec 2025 23:59:36 +0100 Subject: [PATCH 10/26] devenv: apply mdbook 0.5 support patch to devenv_nix Apply the mdbook 0.5 support patch to devenv's bundled Nix 2.30.4. The patch is from upstream Nix commit 5cbd7856, which maintains compatibility with both mdbook 0.4.x and 0.5.x. The doc/manual/package.nix file is excluded as it doesn't exist in cachix's Nix fork. https://github.com/NixOS/nix/issues/14628 --- pkgs/by-name/de/devenv/package.nix | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/pkgs/by-name/de/devenv/package.nix b/pkgs/by-name/de/devenv/package.nix index 1d9633ccf52e..6fe3cacc41ca 100644 --- a/pkgs/by-name/de/devenv/package.nix +++ b/pkgs/by-name/de/devenv/package.nix @@ -1,6 +1,7 @@ { lib, fetchFromGitHub, + fetchpatch2, gitMinimal, makeBinaryWrapper, installShellFiles, @@ -20,16 +21,27 @@ let devenvNixVersion = "2.30.4"; devenv_nix = + let + components = + (nixVersions.nixComponents_git.override { version = devenvNixVersion; }).overrideSource + (fetchFromGitHub { + owner = "cachix"; + repo = "nix"; + rev = "devenv-${devenvNixVersion}"; + hash = "sha256-3+GHIYGg4U9XKUN4rg473frIVNn8YD06bjwxKS1IPrU="; + }); + in ( - (nixVersions.nixComponents_git.override { version = devenvNixVersion; }) - .nix-everything.overrideSource - (fetchFromGitHub { - owner = "cachix"; - repo = "nix"; - rev = "devenv-${devenvNixVersion}"; - hash = "sha256-3+GHIYGg4U9XKUN4rg473frIVNn8YD06bjwxKS1IPrU="; - }) - ).overrideAttrs + # Support for mdbook >= 0.5, https://github.com/NixOS/nix/issues/14628 + components.appendPatches [ + (fetchpatch2 { + name = "nix-2.30-14695-mdbook-0.5-support.patch"; + url = "https://github.com/NixOS/nix/commit/5cbd7856de0a9c13351f98e32a1e26d0854d87fd.patch"; + excludes = [ "doc/manual/package.nix" ]; + hash = "sha256-GYaTOG9wZT9UI4G6za535PkLyjHKSxwBjJsXbjmI26g="; + }) + ] + ).nix-everything.overrideAttrs (old: { pname = "devenv-nix"; version = devenvNixVersion; From 0768ca2fd9b01eafe30ffff9b066b24db4083f55 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 18 Dec 2025 00:13:22 +0100 Subject: [PATCH 11/26] nixVersions.git: 2.33pre20251107_479b6b73 -> 2.34pre20251217_b6add8dc Update to latest Nix master which includes mdbook 0.5 support merged in PR #14690. https://github.com/NixOS/nix/pull/14690 --- pkgs/tools/package-management/nix/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/tools/package-management/nix/default.nix b/pkgs/tools/package-management/nix/default.nix index 382971ff4db5..f804f83e6dd6 100644 --- a/pkgs/tools/package-management/nix/default.nix +++ b/pkgs/tools/package-management/nix/default.nix @@ -243,14 +243,14 @@ lib.makeExtensible ( nix_2_32 = addTests "nix_2_32" self.nixComponents_2_32.nix-everything; nixComponents_git = nixDependencies.callPackage ./modular/packages.nix rec { - version = "2.33pre20251107_${lib.substring 0 8 src.rev}"; + version = "2.34pre20251217_${lib.substring 0 8 src.rev}"; inherit maintainers teams; otherSplices = generateSplicesForNixComponents "nixComponents_git"; src = fetchFromGitHub { owner = "NixOS"; repo = "nix"; - rev = "479b6b73a9576452c14ca66b7f3cd4873969077e"; - hash = "sha256-eBjgsauQXFz2yeiNoPEzgkf7uyV+S8HYCQgZhPVx/9I="; + rev = "b6add8dcc6f4f6feb1ce83aaffe4d7e660e6f616"; + hash = "sha256-2au7PdQ4HXSuktTPCtOJoD/LNjqMwbHIJmuzEYW1b7I="; }; }; From e7f30ad157cf0973adb8b1d1bd853421084c3f5d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 18 Dec 2025 02:13:22 +0100 Subject: [PATCH 12/26] helix: fix build with mdbook 0.5 Update helix documentation build for mdbook 0.5 compatibility. Changes: - Replace deprecated {{#previous}}/{{#next}} helpers with {{#if}} blocks - Update link references from {{link}} to {{previous.link}}/{{next.link}} - Escape HTML tags in command descriptions to prevent markdown parsing errors - Fix book-html path in postInstall (../book-html instead of book-html) The mdbook 0.5 release changed navigation helpers from block helpers to simple objects, requiring template syntax updates in index.hbs. --- pkgs/by-name/he/helix/mdbook-0.5-support.patch | 14 ++++++++++++++ pkgs/by-name/he/helix/package.nix | 14 +++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 pkgs/by-name/he/helix/mdbook-0.5-support.patch diff --git a/pkgs/by-name/he/helix/mdbook-0.5-support.patch b/pkgs/by-name/he/helix/mdbook-0.5-support.patch new file mode 100644 index 000000000000..11591af15937 --- /dev/null +++ b/pkgs/by-name/he/helix/mdbook-0.5-support.patch @@ -0,0 +1,14 @@ +--- a/helix-term/src/commands.rs ++++ b/helix-term/src/commands.rs +@@ -424,9 +424,9 @@ impl MappableCommand { + add_newline_below, "Add newline below", + goto_type_definition, "Goto type definition", + goto_implementation, "Goto implementation", +- goto_file_start, "Goto line number else file start", ++ goto_file_start, "Goto line number <n> else file start", + goto_file_end, "Goto file end", +- extend_to_file_start, "Extend to line number else file start", ++ extend_to_file_start, "Extend to line number <n> else file start", + extend_to_file_end, "Extend to file end", + goto_file, "Goto files/URLs in selections", + goto_file_hsplit, "Goto files in selections (hsplit)", diff --git a/pkgs/by-name/he/helix/package.nix b/pkgs/by-name/he/helix/package.nix index c4ba2f0f3634..890b554134c2 100644 --- a/pkgs/by-name/he/helix/package.nix +++ b/pkgs/by-name/he/helix/package.nix @@ -1,5 +1,6 @@ { fetchzip, + fetchpatch, lib, rustPlatform, mdbook, @@ -25,6 +26,17 @@ rustPlatform.buildRustPackage (final: { stripRoot = false; }; + patches = [ + # Support mdbook 0.5.x: escape HTML tags in command descriptions + ./mdbook-0.5-support.patch + ]; + + postPatch = '' + # mdbook 0.5 uses asset hashing for CSS/JS files + # Remove custom theme to use default mdbook theme with correct asset references + rm -f book/theme/index.hbs + ''; + cargoHash = "sha256-Mf0nrgMk1MlZkSyUN6mlM5lmTcrOHn3xBNzmVGtApEU="; nativeBuildInputs = [ @@ -49,7 +61,7 @@ rustPlatform.buildRustPackage (final: { mkdir -p $out/share/{applications,icons/hicolor/256x256/apps} cp contrib/Helix.desktop $out/share/applications cp contrib/helix.png $out/share/icons/hicolor/256x256/apps - cp -r book-html $doc/share/doc/$name + cp -r ../book-html $doc/share/doc/$name ''; nativeInstallCheckInputs = [ From 194ba32729aea402cd810f9b8a1e4d518f4e9040 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 18 Dec 2025 02:16:50 +0100 Subject: [PATCH 13/26] engage: fix build with mdbook 0.5 Update engage documentation build for mdbook 0.5 compatibility. Changes: - Remove deprecated 'multilingual' field from book.toml - Update git-repository-icon from 'fa-git-square' to 'fab-square-git' The 'multilingual' field was removed in mdbook 0.5 as it was never used. The FontAwesome icon name changed from 'fa-git-square' (FA 4) to 'fab-square-git' (FA 5 brand icon) in the version bundled with mdbook 0.5. --- pkgs/by-name/en/engage/mdbook-0.5-support.patch | 16 ++++++++++++++++ pkgs/by-name/en/engage/package.nix | 5 +++++ 2 files changed, 21 insertions(+) create mode 100644 pkgs/by-name/en/engage/mdbook-0.5-support.patch diff --git a/pkgs/by-name/en/engage/mdbook-0.5-support.patch b/pkgs/by-name/en/engage/mdbook-0.5-support.patch new file mode 100644 index 000000000000..0082bf5e7a37 --- /dev/null +++ b/pkgs/by-name/en/engage/mdbook-0.5-support.patch @@ -0,0 +1,16 @@ +--- a/book.toml ++++ b/book.toml +@@ -1,6 +1,5 @@ + [book] + language = "en" +-multilingual = false + src = "book" + title = "Engage" + +@@ -8,5 +7,5 @@ build-dir = "public" + + [output.html] +-git-repository-icon = "fa-git-square" ++git-repository-icon = "fab-square-git" + git-repository-url = "https://gitlab.computer.surgery/charles/engage" + diff --git a/pkgs/by-name/en/engage/package.nix b/pkgs/by-name/en/engage/package.nix index 6ae2bde48e24..2d57f8307c77 100644 --- a/pkgs/by-name/en/engage/package.nix +++ b/pkgs/by-name/en/engage/package.nix @@ -28,6 +28,11 @@ rustPlatform.buildRustPackage (finalAttrs: { hash = "sha256-n7ypFJBYT712Uzh1NnWWSOIpEDKR0e6sQxbiIN6pZgo="; }; + patches = [ + # Support mdbook 0.5.x - remove deprecated multilingual field + ./mdbook-0.5-support.patch + ]; + cargoHash = "sha256-UTIxxPBtxzsZilxriAT8ksl2ovoDzIhB+8f+b2cGN3k="; nativeBuildInputs = [ From a7d0fcd035c8e62a6f1e1e99afe1e15a6e334175 Mon Sep 17 00:00:00 2001 From: Gaetan Lepage Date: Thu, 18 Dec 2025 19:42:37 +0000 Subject: [PATCH 14/26] ruff: 0.14.9 -> 0.14.10 Diff: https://github.com/astral-sh/ruff/compare/0.14.9...0.14.10 Changelog: https://github.com/astral-sh/ruff/releases/tag/0.14.10 --- pkgs/by-name/ru/ruff/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/ru/ruff/package.nix b/pkgs/by-name/ru/ruff/package.nix index 17ce5aa19ab4..078fe934196e 100644 --- a/pkgs/by-name/ru/ruff/package.nix +++ b/pkgs/by-name/ru/ruff/package.nix @@ -16,18 +16,18 @@ rustPlatform.buildRustPackage (finalAttrs: { pname = "ruff"; - version = "0.14.9"; + version = "0.14.10"; src = fetchFromGitHub { owner = "astral-sh"; repo = "ruff"; tag = finalAttrs.version; - hash = "sha256-2EuI11mdwxKry7d56Ua7ZEU7K0XMgIVHm1zSVoWLkzM="; + hash = "sha256-YwgW3sjI3l3H9Tq2BO7yDOhiiaIy///xxj4UQYq39gI="; }; cargoBuildFlags = [ "--package=ruff" ]; - cargoHash = "sha256-db45h6I5tCcPMbPGa/dV3eJ9CxCwnGShmHdg92AUhv0="; + cargoHash = "sha256-NyNXR1PGds+GXAha9u4DglUyy7T+yqLjNpGnchYn6oc="; nativeBuildInputs = [ installShellFiles ]; From 3ba8e8f94cd4b0231647e3552c8e71a474e2a5f4 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sat, 20 Dec 2025 09:38:47 +0000 Subject: [PATCH 15/26] bind: 9.20.16 -> 9.20.17 Changes: https://downloads.isc.org/isc/bind9/cur/9.20/doc/arm/html/notes.html#notes-for-bind-9-20-17 --- pkgs/by-name/bi/bind/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/bi/bind/package.nix b/pkgs/by-name/bi/bind/package.nix index 208db30f4350..6eb8f91e4c1d 100644 --- a/pkgs/by-name/bi/bind/package.nix +++ b/pkgs/by-name/bi/bind/package.nix @@ -29,11 +29,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "bind"; - version = "9.20.16"; + version = "9.20.17"; src = fetchurl { url = "https://downloads.isc.org/isc/bind9/${finalAttrs.version}/bind-${finalAttrs.version}.tar.xz"; - hash = "sha256-A//Mek/LfDm4KzS+G6K1n2wZG8eVxZNVMNXr5jCjUtY="; + hash = "sha256-XMiaCdoJF+sd32QMwHwXL/RPqbvzo0raS2ovfucP8cg="; }; outputs = [ From 3eb679206a9f95d3d8dae4fe556b1cbd3b666d0d Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Sat, 13 Dec 2025 14:13:31 -0500 Subject: [PATCH 16/26] nixos/boot: add options to configure stage 1 and stage 2 boot greetings --- nixos/modules/system/boot/stage-1-init.sh | 2 +- nixos/modules/system/boot/stage-1.nix | 10 ++++++++++ nixos/modules/system/boot/stage-2-init.sh | 2 +- nixos/modules/system/boot/stage-2.nix | 12 ++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index b8dbfb70c0bb..cc0894593c30 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -73,7 +73,7 @@ trap 'fail' 0 # Print a greeting. info -info "<<< @distroName@ Stage 1 >>>" +info "@stage1Greeting@" info # Make several required directories. diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index c87b3ecef4da..343777d05c3a 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -323,6 +323,7 @@ let postMountCommands preFailCommands kernelModules + stage1Greeting ; resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}") ( @@ -686,6 +687,15 @@ in ''; }; + boot.initrd.stage1Greeting = mkOption { + type = types.str; + default = "<<< ${config.system.nixos.distroName} Stage 1 >>>"; + defaultText = literalExpression ''"<<< ''${config.system.nixos.distroName} Stage 1 >>>"''; + description = '' + The greeting message displayed during NixOS stage 1 boot. + ''; + }; + boot.loader.supportsInitrdSecrets = mkOption { internal = true; default = false; diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh index e960f1bbcc39..cb7cec2afece 100755 --- a/nixos/modules/system/boot/stage-2-init.sh +++ b/nixos/modules/system/boot/stage-2-init.sh @@ -19,7 +19,7 @@ if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then # Print a greeting. echo - echo -e "\e[1;32m<<< @distroName@ Stage 2 >>>\e[0m" + echo -e "\e[1;32m@stage2Greeting@\e[0m" echo diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix index 9565ac5e8ef1..680f5eed55c0 100644 --- a/nixos/modules/system/boot/stage-2.nix +++ b/nixos/modules/system/boot/stage-2.nix @@ -17,9 +17,8 @@ let replacements = { shell = "${pkgs.bash}/bin/bash"; systemConfig = null; # replaced in ../activation/top-level.nix - inherit (config.boot) systemdExecutable; + inherit (config.boot) systemdExecutable stage2Greeting; nixStoreMountOpts = lib.concatStringsSep " " (map lib.escapeShellArg config.boot.nixStoreMountOpts); - inherit (config.system.nixos) distroName; inherit useHostResolvConf; inherit (config.system.build) earlyMountScript; path = lib.makeBinPath ( @@ -87,6 +86,15 @@ in ''; }; + stage2Greeting = mkOption { + type = types.str; + default = "<<< ${config.system.nixos.distroName} Stage 2 >>>"; + defaultText = literalExpression ''"<<< ''${config.system.nixos.distroName} Stage 2 >>>"''; + description = '' + The greeting message displayed during NixOS stage 2 boot. + ''; + }; + extraSystemdUnitPaths = mkOption { default = [ ]; type = types.listOf types.str; From f93b74e538d3855fdf38f30d58ec6280f448e00e Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Sun, 21 Dec 2025 17:47:31 +0000 Subject: [PATCH 17/26] linux/common-config: Enable `ARM64_PMEM` This feature, while not enabled by default by the Linux defconfig, is required for usage of mainline kernels in the NVidia Jetson boards. It appears to have no adverse effects, since its availability is detected at runtime, so it's fine to have enabled on all aarch64 platforms. Other distros have this enabled by default as well: - Debian: https://salsa.debian.org/kernel-team/linux/-/blob/debian/latest/debian/config/arm64/config#L36 - Ubuntu: https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble/tree/debian.master/config/annotations#n1657 - Fedora: https://src.fedoraproject.org/rpms/kernel/blob/rawhide/f/kernel-aarch64-fedora.config#_497 This is also, from what I can tell, the only blocker to being able to use NixOS on an NVidia Jetson, since they support UEFI just fine, and the out-of-tree modules can easily be packaged in nixos-hardware. --- pkgs/os-specific/linux/kernel/common-config.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index c4f1181c64cd..77e1511fac6b 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -1351,6 +1351,8 @@ let X86_PLATFORM_DRIVERS_DELL = lib.mkIf stdenv.hostPlatform.isx86 (whenAtLeast "5.12" yes); X86_PLATFORM_DRIVERS_HP = lib.mkIf stdenv.hostPlatform.isx86 (whenAtLeast "6.1" yes); + ARM64_PMEM = lib.mkIf stdenv.hostPlatform.isAarch64 yes; + LIRC = yes; SCHED_CORE = whenAtLeast "5.14" yes; From bcbe96f8a64090e9d1d0ebf7be7e1f38602a9b3d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 22 Dec 2025 09:42:20 +0100 Subject: [PATCH 18/26] mdbook-cmdrun: 0.6.0-unstable-2024-04-15 -> 0.7.3-unstable-2025-12-22 This supports mdbook 0.5. --- pkgs/by-name/md/mdbook-cmdrun/package.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/by-name/md/mdbook-cmdrun/package.nix b/pkgs/by-name/md/mdbook-cmdrun/package.nix index a82528518412..1d920cbcbb2e 100644 --- a/pkgs/by-name/md/mdbook-cmdrun/package.nix +++ b/pkgs/by-name/md/mdbook-cmdrun/package.nix @@ -10,13 +10,14 @@ rustPlatform.buildRustPackage { pname = "mdbook-cmdrun"; - version = "0.6.0-unstable-2024-04-15"; + version = "0.7.3-unstable-2025-12-22"; + # mdbook 0.5 upgrade: https://github.com/FauconFan/mdbook-cmdrun/pull/23 src = fetchFromGitHub { - owner = "FauconFan"; + owner = "roberth"; repo = "mdbook-cmdrun"; - rev = "d1fef67f100563c2a433b1f5dd5a71810db6b90d"; - hash = "sha256-Q2h64XCyDxLmmCNC3wTw81pBotaMEUjY5y0Oq6q20cQ="; + rev = "3947c797d063352e0f983311c078430215cc1cca"; + hash = "sha256-0RkyMJ8tsnGcSD0ksGTGAyliH6AihVl0HEesljEmTH8="; }; nativeCheckInputs = [ @@ -26,7 +27,7 @@ rustPlatform.buildRustPackage { util-linux # used by tests/regression/shell/input.md ]; - cargoHash = "sha256-C3Rg+WXHBA7KyUDFdhBz4mOm8CFH/f7UVA8KOLs9ClE="; + cargoHash = "sha256-oUlH+z50a1FtzDADXfGKSYjauZGTok0bVMq718HLglY="; meta = { description = "mdbook preprocessor to run arbitrary commands"; From 64d4b0a39bc53674a17e01030828bf8c3b307719 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Tue, 23 Dec 2025 09:25:04 +0000 Subject: [PATCH 19/26] kernel/common-config: enable all thermal governors This allows more flexibility in how thermal management is handled in any NixOS system. It is especially useful for embedded devices, which often rely on a user-space thermal governor. Previously, only the `BANG_BANG` and `STEP_WISE` governors were enabled on x86, or `STEP_WISE` and `POWER_ALLOCATOR` on aarch64, which come from the defconfig. There is however no negative to having all of them enabled on all architectures, so for consistency this enables all of them everywhere. Other distros seem to have all of the thermal governors enabled as well: - Ubuntu: https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble/tree/debian.master/config/annotations#n13757 - Debian: https://salsa.debian.org/kernel-team/linux/-/blob/debian/latest/debian/config/config#L5116-L5120 - Arch: https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/blob/main/config?ref_type=heads#L5788-L5792 --- pkgs/os-specific/linux/kernel/common-config.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index a4f6a24a949b..d905439db70a 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -1326,6 +1326,14 @@ let HOTPLUG_PCI_ACPI = yes; # PCI hotplug using ACPI HOTPLUG_PCI_PCIE = yes; # PCI-Expresscard hotplug support + # Enable all available thermal governors + THERMAL_GOV_BANG_BANG = yes; + THERMAL_GOV_FAIR_SHARE = yes; + THERMAL_GOV_POWER_ALLOCATOR = yes; + THERMAL_GOV_STEP_WISE = yes; + THERMAL_GOV_USER_SPACE = yes; + DEVFREQ_THERMAL = yes; + # Enable AMD's ROCm GPU compute stack HSA_AMD = lib.mkIf stdenv.hostPlatform.is64bit yes; ZONE_DEVICE = lib.mkIf ( From 93cda47a1f2049c70074367445e6fb2bfb928154 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Mon, 15 Dec 2025 16:12:51 +0100 Subject: [PATCH 20/26] nixos/switchable-system: introduce a standard pre-switch check to prevent switching under certain conditions This commit introduces "switch inhibitors" which are derivations that prevent a switch of a system to a new configuration if those derivations don't have the same hash in both configurations. This means that we can for instance add the systemd and dbus derivations such that users will be instructed to reboot their system when those derivations have changed instead of switching. This feature should be used sparingly, but it can make NixOS more robust by avoiding users switching to a configuration that can make their system unstable (like major updates of systemd, or new versions of dbus since the dbus and dbus-broker daemons cannot be restarted). The user can still force the switch by setting an env var. --- nixos/modules/services/system/dbus.nix | 8 + .../system/activation/switchable-system.nix | 141 ++++++++++++++---- nixos/modules/system/boot/systemd.nix | 4 + 3 files changed, 128 insertions(+), 25 deletions(-) diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 3751fa5e57fd..a0edb9336208 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -174,6 +174,10 @@ in permissions = "u+rx,g+rx,o-rx"; }; + system.switch.inhibitors = [ + cfg.dbusPackage + ]; + systemd.services.dbus = { aliases = [ # hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus @@ -212,6 +216,10 @@ in cfg.brokerPackage ]; + system.switch.inhibitors = [ + cfg.brokerPackage + ]; + # Just to be sure we don't restart through the unit alias systemd.services.dbus.reloadIfChanged = true; systemd.user.services.dbus.reloadIfChanged = true; diff --git a/nixos/modules/system/activation/switchable-system.nix b/nixos/modules/system/activation/switchable-system.nix index a2e804e8a788..380b52b6825d 100644 --- a/nixos/modules/system/activation/switchable-system.nix +++ b/nixos/modules/system/activation/switchable-system.nix @@ -16,38 +16,129 @@ '') ]; - options.system.switch.enable = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Whether to include the capability to switch configurations. + options.system.switch = { + enable = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to include the capability to switch configurations. - Disabling this makes the system unable to be reconfigured via `nixos-rebuild`. + Disabling this makes the system unable to be reconfigured via `nixos-rebuild`. - This is good for image based appliances where updates are handled - outside the image. Reducing features makes the image lighter and - slightly more secure. - ''; + This is good for image based appliances where updates are handled + outside the image. Reducing features makes the image lighter and + slightly more secure. + ''; + }; + + inhibitors = lib.mkOption { + type = lib.types.listOf lib.types.pathInStore; + default = [ ]; + description = '' + List of derivations that will prevent switching into a configuration when + they change. + This can be manually overridden on the command line if required. + ''; + }; }; config = lib.mkIf config.system.switch.enable { # Use a subshell so we can source makeWrapper's setup hook without # affecting the rest of activatableSystemBuilderCommands. - system.activatableSystemBuilderCommands = '' - ( - source ${pkgs.buildPackages.makeWrapper}/nix-support/setup-hook + system = { + activatableSystemBuilderCommands = '' + ( + source ${pkgs.buildPackages.makeWrapper}/nix-support/setup-hook - mkdir $out/bin - ln -sf ${lib.getExe pkgs.switch-to-configuration-ng} $out/bin/switch-to-configuration - wrapProgram $out/bin/switch-to-configuration \ - --set OUT $out \ - --set TOPLEVEL ''${!toplevelVar} \ - --set DISTRO_ID ${lib.escapeShellArg config.system.nixos.distroId} \ - --set INSTALL_BOOTLOADER ${lib.escapeShellArg config.system.build.installBootLoader} \ - --set PRE_SWITCH_CHECK ${lib.escapeShellArg config.system.preSwitchChecksScript} \ - --set LOCALE_ARCHIVE ${config.i18n.glibcLocales}/lib/locale/locale-archive \ - --set SYSTEMD ${config.systemd.package} - ) - ''; + mkdir $out/bin + ln -sf ${lib.getExe pkgs.switch-to-configuration-ng} $out/bin/switch-to-configuration + wrapProgram $out/bin/switch-to-configuration \ + --set OUT $out \ + --set TOPLEVEL ''${!toplevelVar} \ + --set DISTRO_ID ${lib.escapeShellArg config.system.nixos.distroId} \ + --set INSTALL_BOOTLOADER ${lib.escapeShellArg config.system.build.installBootLoader} \ + --set PRE_SWITCH_CHECK ${lib.escapeShellArg config.system.preSwitchChecksScript} \ + --set LOCALE_ARCHIVE ${config.i18n.glibcLocales}/lib/locale/locale-archive \ + --set SYSTEMD ${config.systemd.package} + ) + ''; + + systemBuilderCommands = '' + ln -s ${config.system.build.inhibitSwitch} $out/switch-inhibitors + ''; + + build.inhibitSwitch = pkgs.writeTextFile { + name = "switch-inhibitors"; + text = lib.concatMapStringsSep "\n" (drv: drv.outPath) config.system.switch.inhibitors; + }; + + preSwitchChecks.switchInhibitors = + let + realpath = lib.getExe' pkgs.coreutils "realpath"; + sha256sum = lib.getExe' pkgs.coreutils "sha256sum"; + diff = lib.getExe' pkgs.diffutils "diff"; + in + # bash + '' + incoming="''${1-}" + action="''${2-}" + + if [ "$action" == "boot" ]; then + echo "Not checking switch inhibitors (action = $action)" + exit + fi + + echo -n "Checking switch inhibitors..." + + booted_inhibitors="$(${realpath} /run/booted-system)/switch-inhibitors" + booted_inhibitors_sha="$( + if [ -f "$booted_inhibitors" ]; then + ${sha256sum} - < "$booted_inhibitors" + else + echo 'none' + fi + )" + + if [ "$booted_inhibitors_sha" == "none" ]; then + echo + echo "The previous configuration did not specify switch inhibitors, nothing to check." + exit + fi + + new_inhibitors="$(${realpath} "$incoming")/switch-inhibitors" + new_inhibitors_sha="$( + if [ -f "$new_inhibitors" ]; then + ${sha256sum} - < "$new_inhibitors" + else + echo 'none' + fi + )" + + if [ "$new_inhibitors_sha" == "none" ]; then + echo + echo "The new configuration does not specify switch inhibitors, nothing to check." + exit + fi + + if [ "$new_inhibitors_sha" != "$booted_inhibitors_sha" ]; then + echo + echo "Found diff in switch inhibitors:" + echo + ${diff} --color "$booted_inhibitors" "$new_inhibitors" + echo + echo "The new configuration contains changes to packages that were" + echo "listed as switch inhibitors." + echo + echo "If you really want to switch into this configuration directly, then" + echo "you can set NIXOS_NO_CHECK=1 to ignore these pre-switch checks." + echo + echo "WARNING: doing so might cause the switch to fail or your system to become unstable." + echo + exit 1 + else + echo " done" + fi + ''; + }; }; } diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 7fb5c2259062..25bd4c624bfe 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -567,6 +567,10 @@ in ); }; + system.switch.inhibitors = [ + cfg.package + ]; + environment.systemPackages = [ cfg.package ]; environment.etc = From f10d0e14eeeea09b50a9c912ec13869a7929ba97 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Mon, 15 Dec 2025 17:45:10 +0100 Subject: [PATCH 21/26] nixos/autoUpgrade: introduce reboot triggers to customise the auto-reboot behaviour Before this, the derivations that trigger an auto-reboot were hard-codede. This commit makes them configurable. --- nixos/modules/tasks/auto-upgrade.nix | 323 +++++++++++++++++---------- 1 file changed, 208 insertions(+), 115 deletions(-) diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix index 7028c0be444d..8bb445db9352 100644 --- a/nixos/modules/tasks/auto-upgrade.nix +++ b/nixos/modules/tasks/auto-upgrade.nix @@ -114,6 +114,27 @@ in ''; }; + rebootTriggers = lib.mkOption { + type = lib.types.listOf lib.types.pathInStore; + default = [ ]; + description = '' + List of derivations that will cause an auto-reboot when changed when + {option}`system.autoUpgrade.allowReboot` is set to true. + ''; + defaultText = lib.literalExpression '' + [ + config.system.build.initialRamdisk + config.system.build.kernel + config.hardware.firmware + (pkgs.writeTextFile { + name = "kernel-params"; + text = lib.concatStringsSep " " config.boot.kernelParams; + }) + ] + ++ config.system.switch.inhibitors + ''; + }; + randomizedDelaySec = lib.mkOption { default = "0"; type = lib.types.str; @@ -197,133 +218,205 @@ in }; - config = lib.mkIf cfg.enable { + config = lib.mkMerge [ - assertions = [ - { - assertion = !((cfg.channel != null) && (cfg.flake != null)); - message = '' - The options 'system.autoUpgrade.channel' and 'system.autoUpgrade.flake' cannot both be set. - ''; - } - { - assertion = (cfg.runGarbageCollection -> config.nix.enable); - message = '' - The option 'system.autoUpgrade.runGarbageCollection = true' requires 'nix.enable = true'. - ''; - } - ]; - - system.autoUpgrade.flags = ( - if cfg.flake == null then - [ "--no-build-output" ] - ++ lib.optionals (cfg.channel != null) [ - "-I" - "nixpkgs=${cfg.channel}/nixexprs.tar.xz" + { + system = { + autoUpgrade.rebootTriggers = [ + config.system.build.initialRamdisk + config.system.build.kernel + config.hardware.firmware + (pkgs.writeTextFile { + name = "kernel-params"; + text = lib.concatStringsSep " " config.boot.kernelParams; + }) ] - else - [ - "--refresh" - "--flake ${cfg.flake}" - ] - ); + ++ config.system.switch.inhibitors; - systemd.services.nixos-upgrade = { - description = "NixOS Upgrade"; + systemBuilderCommands = '' + ln -s ${config.system.build.rebootTriggers} $out/reboot-triggers + ''; - restartIfChanged = false; - unitConfig.X-StopOnRemoval = false; - unitConfig.OnSuccess = lib.optional ( - cfg.runGarbageCollection && config.nix.enable - ) "nix-gc.service"; + build.rebootTriggers = pkgs.writeTextFile { + name = "reboot-triggers"; + text = lib.concatMapStringsSep "\n" (drv: drv.outPath) config.system.autoUpgrade.rebootTriggers; + }; + }; + } - serviceConfig.Type = "oneshot"; - - environment = - config.nix.envVars - // { - inherit (config.environment.sessionVariables) NIX_PATH; - HOME = "/root"; + (lib.mkIf cfg.enable { + assertions = [ + { + assertion = !((cfg.channel != null) && (cfg.flake != null)); + message = '' + The options 'system.autoUpgrade.channel' and 'system.autoUpgrade.flake' cannot both be set. + ''; + } + { + assertion = (cfg.runGarbageCollection -> config.nix.enable); + message = '' + The option 'system.autoUpgrade.runGarbageCollection = true' requires 'nix.enable = true'. + ''; } - // config.networking.proxy.envVars; - - path = with pkgs; [ - coreutils - gnutar - xz.bin - gzip - gitMinimal - config.nix.package.out - config.programs.ssh.package ]; - script = - let - nixos-rebuild = "${config.system.build.nixos-rebuild}/bin/nixos-rebuild"; - date = "${pkgs.coreutils}/bin/date"; - readlink = "${pkgs.coreutils}/bin/readlink"; - shutdown = "${config.systemd.package}/bin/shutdown"; - upgradeFlag = lib.optional (cfg.channel == null && cfg.upgrade) "--upgrade"; - in - if cfg.allowReboot then - '' - ${nixos-rebuild} boot ${toString (cfg.flags ++ upgradeFlag)} - booted="$(${readlink} /run/booted-system/{initrd,kernel,kernel-modules})" - built="$(${readlink} /nix/var/nix/profiles/system/{initrd,kernel,kernel-modules})" - - ${lib.optionalString (cfg.rebootWindow != null) '' - current_time="$(${date} +%H:%M)" - - lower="${cfg.rebootWindow.lower}" - upper="${cfg.rebootWindow.upper}" - - if [[ "''${lower}" < "''${upper}" ]]; then - if [[ "''${current_time}" > "''${lower}" ]] && \ - [[ "''${current_time}" < "''${upper}" ]]; then - do_reboot="true" - else - do_reboot="false" - fi - else - # lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h) - # we want to reboot if cur > 23h or cur < 6h - if [[ "''${current_time}" < "''${upper}" ]] || \ - [[ "''${current_time}" > "''${lower}" ]]; then - do_reboot="true" - else - do_reboot="false" - fi - fi - ''} - - if [ "''${booted}" = "''${built}" ]; then - ${nixos-rebuild} ${cfg.operation} ${toString cfg.flags} - ${lib.optionalString (cfg.rebootWindow != null) '' - elif [ "''${do_reboot}" != true ]; then - echo "Outside of configured reboot window, skipping." - ''} - else - ${shutdown} -r +1 - fi - '' + system.autoUpgrade.flags = ( + if cfg.flake == null then + [ "--no-build-output" ] + ++ lib.optionals (cfg.channel != null) [ + "-I" + "nixpkgs=${cfg.channel}/nixexprs.tar.xz" + ] else - '' - ${nixos-rebuild} ${cfg.operation} ${toString (cfg.flags ++ upgradeFlag)} - ''; + [ + "--refresh" + "--flake ${cfg.flake}" + ] + ); - startAt = cfg.dates; + systemd.services.nixos-upgrade = { + description = "NixOS Upgrade"; - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; - }; + restartIfChanged = false; + unitConfig.X-StopOnRemoval = false; + unitConfig.OnSuccess = lib.optional ( + cfg.runGarbageCollection && config.nix.enable + ) "nix-gc.service"; - systemd.timers.nixos-upgrade = { - timerConfig = { - RandomizedDelaySec = cfg.randomizedDelaySec; - FixedRandomDelay = cfg.fixedRandomDelay; - Persistent = cfg.persistent; + serviceConfig.Type = "oneshot"; + + environment = + config.nix.envVars + // { + inherit (config.environment.sessionVariables) NIX_PATH; + HOME = "/root"; + } + // config.networking.proxy.envVars; + + path = with pkgs; [ + coreutils + gnutar + xz.bin + gzip + gitMinimal + config.nix.package.out + config.programs.ssh.package + config.system.build.nixos-rebuild + config.systemd.package + ]; + + script = + let + upgradeFlag = lib.optional (cfg.channel == null && cfg.flake == null) "--upgrade"; + in + if cfg.allowReboot then + # bash + '' + echo "Running nixos-rebuild boot..." + new_configuration="$( + # For some reason we still get a newline here in the journal between the + # nixos-rebuild stderr output and us echoing the store path that was + # printed on stdout. + # This might have to do with the particular way in which systemd handles + # stdout/stderr, they are unix sockets and not normal streams. + store_path="$(nixos-rebuild boot ${toString (cfg.flags ++ upgradeFlag)})" + echo "$store_path" >&2 + echo "$store_path" + )" + if [ -z "$new_configuration" ]; then + echo "Looks like nixos-rebuild failed... Aborting" + exit 1 + fi + echo "New configuration is $new_configuration" + switch_to_new_configuration="$new_configuration"/bin/switch-to-configuration + + ${lib.optionalString (cfg.rebootWindow != null) # bash + '' + current_time="$(date +%H:%M)" + + lower="${cfg.rebootWindow.lower}" + upper="${cfg.rebootWindow.upper}" + + if [[ "''${lower}" < "''${upper}" ]]; then + if [[ "''${current_time}" > "''${lower}" ]] && [[ "''${current_time}" < "''${upper}" ]]; then + do_reboot="true" + else + do_reboot="false" + fi + else + # lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h) + # we want to reboot if cur > 23h or cur < 6h + if [[ "''${current_time}" < "''${upper}" ]] || [[ "''${current_time}" > "''${lower}" ]]; then + do_reboot="true" + else + do_reboot="false" + fi + fi + '' + } + + booted_triggers="$(realpath /run/booted-system)/reboot-triggers" + booted_triggers_sha="$( + if [ -f "$booted_triggers" ]; then + sha256sum - < "$booted_triggers" + else + echo 'none' + fi + )" + + new_triggers="$(realpath "$new_configuration")/reboot-triggers" + new_triggers_sha="$( + if [ -f "$new_triggers" ]; then + sha256sum - < "$new_triggers" + else + echo 'none' + fi + )" + + ${lib.optionalString (cfg.operation == "switch") # bash + '' + echo "Running switch-to-configuration check..." + if "$switch_to_new_configuration" check; then + echo "Checking reboot triggers..." + if [ "$new_triggers_sha" == "$booted_triggers_sha" ]; then + echo "Switching into the new generation..." + "$switch_to_new_configuration" ${cfg.operation} + exit 0 + fi + fi + '' + } + ${lib.optionalString (cfg.rebootWindow != null) # bash + '' + if [ "''${do_reboot}" != true ]; then + echo "Outside of configured reboot window, skipping." + exit 0 + fi + '' + } + echo "Scheduling a reboot to activate the new generation" + systemctl reboot --when="+2min" + '' + else + # bash + '' + nixos-rebuild ${cfg.operation} ${toString (cfg.flags ++ upgradeFlag)} + ''; + + startAt = cfg.dates; + + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; }; - }; - }; + systemd.timers.nixos-upgrade = { + timerConfig = { + RandomizedDelaySec = cfg.randomizedDelaySec; + FixedRandomDelay = cfg.fixedRandomDelay; + Persistent = cfg.persistent; + }; + }; + }) + + ]; } From 4f821ebf99181730f19a66801ed32e144c5898ac Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Thu, 25 Dec 2025 15:09:38 +0000 Subject: [PATCH 22/26] nixos/test-driver: Switch retry() to use monotonic timer Fixes: #470809 --- nixos/lib/test-driver/src/test_driver/machine/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nixos/lib/test-driver/src/test_driver/machine/__init__.py b/nixos/lib/test-driver/src/test_driver/machine/__init__.py index 71e14a87eb36..9f9a2fde94be 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -97,15 +97,16 @@ def retry(fn: Callable, timeout: int = 900) -> None: """Call the given function repeatedly, with 1 second intervals, until it returns True or a timeout is reached. """ + deadline = time.monotonic() + timeout - for _ in range(timeout): + while deadline > time.monotonic(): if fn(False): return time.sleep(1) if not fn(True): raise RequestedAssertionFailed( - f"action timed out after {timeout} tries with one-second pause in-between" + f"action timed out after {timeout} seconds with one-second pause in-between" ) From b566fbfc58c0522cc6253c150934b7bb116726a4 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Thu, 25 Dec 2025 15:15:54 +0000 Subject: [PATCH 23/26] nixos/test-driver: Show elapsed time in assertion --- .../lib/test-driver/src/test_driver/driver.py | 2 +- .../src/test_driver/machine/__init__.py | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/nixos/lib/test-driver/src/test_driver/driver.py b/nixos/lib/test-driver/src/test_driver/driver.py index 361bb1c2a93d..c4f268404cbc 100644 --- a/nixos/lib/test-driver/src/test_driver/driver.py +++ b/nixos/lib/test-driver/src/test_driver/driver.py @@ -344,7 +344,7 @@ class Driver: return ret with driver.logger.nested(f"waiting for {self.condition.description}"): - retry(condition, timeout=timeout) + retry(condition, timeout_seconds=timeout) if fun_ is None: return Poll diff --git a/nixos/lib/test-driver/src/test_driver/machine/__init__.py b/nixos/lib/test-driver/src/test_driver/machine/__init__.py index 9f9a2fde94be..5d216a5d7c7a 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -93,20 +93,25 @@ def make_command(args: list) -> str: return " ".join(map(shlex.quote, (map(str, args)))) -def retry(fn: Callable, timeout: int = 900) -> None: - """Call the given function repeatedly, with 1 second intervals, - until it returns True or a timeout is reached. - """ - deadline = time.monotonic() + timeout +def retry(fn: Callable, timeout_seconds: int = 900) -> None: + """Call the given function repeatedly, with a one second interval between + retries, until it returns True or a timeout is reached. - while deadline > time.monotonic(): + Note that the timeout shown will include the time of the last attempted run. + """ + start_time = time.monotonic() + + while time.monotonic() - start_time < timeout_seconds: if fn(False): return time.sleep(1) + elapsed = time.monotonic() - start_time + if not fn(True): raise RequestedAssertionFailed( - f"action timed out after {timeout} seconds with one-second pause in-between" + f"action timed out after {elapsed:.2f} seconds " + f"(timeout={timeout_seconds})" ) From 2d05df9e8844aaf9e52409a2a8f32af171d92576 Mon Sep 17 00:00:00 2001 From: Jonathan Davies Date: Thu, 25 Dec 2025 15:55:03 +0000 Subject: [PATCH 24/26] nixos/openssh: tests: Ease systemd unit timeouts to 60 seconds Multiple VMs starting on my i5 laptop seems to fail around 38 seconds. --- nixos/tests/openssh.nix | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix index 4bf584338c49..97ed224b5afb 100644 --- a/nixos/tests/openssh.nix +++ b/nixos/tests/openssh.nix @@ -290,23 +290,23 @@ in testScript = '' start_all() - server.wait_for_unit("sshd", timeout=30) - server_allowed_users.wait_for_unit("sshd", timeout=30) - server_localhost_only.wait_for_unit("sshd", timeout=30) - server_match_rule.wait_for_unit("sshd", timeout=30) - server_no_openssl.wait_for_unit("sshd", timeout=30) - server_no_pam.wait_for_unit("sshd", timeout=30) - server_null_pam.wait_for_unit("sshd", timeout=30) + server.wait_for_unit("sshd", timeout=60) + server_allowed_users.wait_for_unit("sshd", timeout=60) + server_localhost_only.wait_for_unit("sshd", timeout=60) + server_match_rule.wait_for_unit("sshd", timeout=60) + server_no_openssl.wait_for_unit("sshd", timeout=60) + server_no_pam.wait_for_unit("sshd", timeout=60) + server_null_pam.wait_for_unit("sshd", timeout=60) server_null_pam.fail("journalctl -u sshd.service | grep 'Unsupported option UsePAM'") - server_sftp.wait_for_unit("sshd", timeout=30) + server_sftp.wait_for_unit("sshd", timeout=60) - server_lazy.wait_for_unit("sshd.socket", timeout=30) - server_localhost_only_lazy.wait_for_unit("sshd.socket", timeout=30) - server_lazy_socket.wait_for_unit("sshd.socket", timeout=30) + server_lazy.wait_for_unit("sshd.socket", timeout=60) + server_localhost_only_lazy.wait_for_unit("sshd.socket", timeout=60) + server_lazy_socket.wait_for_unit("sshd.socket", timeout=60) # sshd-keygen is a oneshot unit, so just wait for multi-user.target, which # pulls it in. - server_no_sshd_with_key.wait_for_unit("multi-user.target", timeout=30) + server_no_sshd_with_key.wait_for_unit("multi-user.target", timeout=60) with subtest("manual-authkey"): client.succeed( From 77ed311f073c30341068f5b5c7be4277a8df91e0 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Sun, 28 Dec 2025 01:18:29 +0200 Subject: [PATCH 25/26] nixos-test-driver: fix formatting to fix build --- nixos/lib/test-driver/src/test_driver/machine/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nixos/lib/test-driver/src/test_driver/machine/__init__.py b/nixos/lib/test-driver/src/test_driver/machine/__init__.py index 5d216a5d7c7a..f722d36ae40e 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -110,8 +110,7 @@ def retry(fn: Callable, timeout_seconds: int = 900) -> None: if not fn(True): raise RequestedAssertionFailed( - f"action timed out after {elapsed:.2f} seconds " - f"(timeout={timeout_seconds})" + f"action timed out after {elapsed:.2f} seconds (timeout={timeout_seconds})" ) From 9bfd0d688d442c53db1f17d7b5e48b27bdd715a6 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Fri, 26 Dec 2025 18:30:49 +0200 Subject: [PATCH 26/26] nixos/activation: avoid build failure with large activation script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two improvements: * use `writeShellApplication` (which uses `passAsFile` instead of passing the activation script as an env var into the derivation. We disable shellcheck and the bash options that this builder usually adds to avoid issues with out-of-tree activation scripts. * use `sed` instead of `substituteInPlace`, since the substitute functions load the file content into a shell variable This avoids issues when the activation is too long to fit in a shell variable. Before this commit, a very large activation script, would cause build failures because of different limits on the file content size, e.g. ``` ➜ nix build -f . nixosTests.restartByActivationScript.nodes.machine.system.build.toplevel -vL this derivation will be built: /nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv building '/nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv'... nixos-system-machine-test> error: executing '/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash': Argument list too long error: builder for '/nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv' failed with exit code 1; last 1 log lines: > error: executing '/nix/store/rlq03x4cwf8zn73hxaxnx0zn5q9kifls-bash-5.3p3/bin/bash': Argument list too long For full logs, run: nix log /nix/store/xw6anpfjyamnycjg58cmj01sz3ididyl-nixos-system-machine-test.drv ``` --- .../system/activation/activatable-system.nix | 73 +++++++++++-------- .../system/activation/activation-script.nix | 2 - nixos/tests/restart-by-activation-script.nix | 10 ++- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/nixos/modules/system/activation/activatable-system.nix b/nixos/modules/system/activation/activatable-system.nix index bb207ec0c18f..c3739f627a16 100644 --- a/nixos/modules/system/activation/activatable-system.nix +++ b/nixos/modules/system/activation/activatable-system.nix @@ -11,12 +11,6 @@ let mkOption types ; - - systemBuilderArgs = { - activationScript = config.system.activationScripts.script; - dryActivationScript = config.system.dryActivationScript; - }; - in { options = { @@ -52,36 +46,51 @@ in ''; }; }; - config = { - system.activatableSystemBuilderCommands = '' - echo "$activationScript" > $out/activate - echo "$dryActivationScript" > $out/dry-activate - substituteInPlace $out/activate --subst-var-by out ''${!toplevelVar} - substituteInPlace $out/dry-activate --subst-var-by out ''${!toplevelVar} - chmod u+x $out/activate $out/dry-activate - unset activationScript dryActivationScript - ''; + config = + let + activationScript = lib.getExe ( + pkgs.writeShellApplication { + name = "activate"; + text = config.system.activationScripts.script; + checkPhase = ""; + bashOptions = [ ]; + } + ); + dryActivationScript = lib.getExe ( + pkgs.writeShellApplication { + name = "dry-activate"; + text = config.system.dryActivationScript; + checkPhase = ""; + bashOptions = [ ]; + } + ); + in + { + system.activatableSystemBuilderCommands = + # We use sed here instead of substitute(InPlace), because the substitute + # functions load the content of the file into a bash variable, which fails + # for very large activation scripts. + # bash + '' + cp ${activationScript} $out/activate + cp ${dryActivationScript} $out/dry-activate + ${lib.getExe pkgs.gnused} --in-place --expression "s|@out@|''${!toplevelVar}|g" $out/activate $out/dry-activate + ''; - system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands; - system.systemBuilderArgs = lib.mkIf config.system.activatable ( - systemBuilderArgs - // { + system.systemBuilderCommands = lib.mkIf config.system.activatable config.system.activatableSystemBuilderCommands; + system.systemBuilderArgs = lib.mkIf config.system.activatable { toplevelVar = "out"; - } - ); + }; - system.build.separateActivationScript = - pkgs.runCommand "separate-activation-script" - ( - systemBuilderArgs - // { + system.build.separateActivationScript = + pkgs.runCommand "separate-activation-script" + { toplevelVar = "toplevel"; toplevel = config.system.build.toplevel; } - ) - '' - mkdir $out - ${config.system.activatableSystemBuilderCommands} - ''; - }; + '' + mkdir $out + ${config.system.activatableSystemBuilderCommands} + ''; + }; } diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 08ab396e1de2..8fd274276a61 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -50,8 +50,6 @@ let ) withHeadlines; in '' - #!${pkgs.runtimeShell} - source ${./lib/lib.sh} systemConfig='@out@' diff --git a/nixos/tests/restart-by-activation-script.nix b/nixos/tests/restart-by-activation-script.nix index 6d26d9843aff..2fad1f21584e 100644 --- a/nixos/tests/restart-by-activation-script.nix +++ b/nixos/tests/restart-by-activation-script.nix @@ -6,7 +6,7 @@ }; nodes.machine = - { pkgs, ... }: + { pkgs, lib, ... }: { imports = [ ../modules/profiles/minimal.nix ]; @@ -46,6 +46,14 @@ fi ''; }; + + # Make sure we don't crash on long activation scripts + specialisation.longscript.configuration = { + system.activationScripts.long = { + supportsDryActivation = true; + text = lib.concatStringsSep "\n" (lib.genList (i: ''# line number ${toString i}'') 1000000); + }; + }; }; testScript = # python