From 7894aae821d6b9da7e0d651b79cd5e52197afa5b Mon Sep 17 00:00:00 2001 From: fred21O4 <67189813+fred21O4@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:54:49 +1200 Subject: [PATCH 1/7] busybox: don't use hardcoded /sbin/resolvconf --- pkgs/os-specific/linux/busybox/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/os-specific/linux/busybox/default.nix b/pkgs/os-specific/linux/busybox/default.nix index 677b884d1c6d..4155f345bc7e 100644 --- a/pkgs/os-specific/linux/busybox/default.nix +++ b/pkgs/os-specific/linux/busybox/default.nix @@ -167,6 +167,7 @@ stdenv.mkDerivation rec { 1 a busybox() { '$out'/bin/busybox "$@"; }\ logger() { '$out'/bin/logger "$@"; }\ ' ${debianDispatcherScript} > ${outDispatchPath} + sed -i 's|/sbin/resolvconf|"$(busybox which resolvconf)"|g' ${outDispatchPath} chmod 555 ${outDispatchPath} HOST_PATH=$out/bin patchShebangs --host ${outDispatchPath} ''; From 4971c9331a72deeda85ba8d8018a5b07ee6f1635 Mon Sep 17 00:00:00 2001 From: edef Date: Wed, 15 Apr 2026 17:53:12 +0000 Subject: [PATCH 2/7] nixos: maximise mmap ASLR entropy on x86_64 and AArch64 The Linux default of 28 bits on x86_64 and 18 bits (!) on AArch64 is a legacy holdover; Ubuntu 22.04 LTS and newer use a much more defensible 32 bits here on x86_64, and 33 bits on AArch64. On AArch64, the maximum depends on page size: 33 bits for 4K pages, 31 bits for 16K pages, and 29 bits for 64K pages (e.g. Asahi Linux). We query the kernel config to select the right value. In 32-bit compatibility mode on x86_64 and AArch64, we set 16 bits, the maximum permitted by the size of the address space. Other architectures are left at kernel defaults, since the maximums vary widely (e.g. 24 for riscv64, 18 for loongarch/mips/parisc). --- nixos/modules/config/sysctl.nix | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/nixos/modules/config/sysctl.nix b/nixos/modules/config/sysctl.nix index a45fe8d88d56..6b6e8e879012 100644 --- a/nixos/modules/config/sysctl.nix +++ b/nixos/modules/config/sysctl.nix @@ -1,4 +1,9 @@ -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: let sysctlOption = lib.mkOptionType { @@ -87,6 +92,28 @@ in # the value below is used by default on several other distros. "fs.inotify.max_user_instances" = lib.mkDefault 524288; "fs.inotify.max_user_watches" = lib.mkDefault 524288; + + # Maximise address space randomisation. + "vm.mmap_rnd_bits" = lib.mkMerge [ + (lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 ( + let + kernel = config.boot.kernelPackages.kernel; + isYes = kernel.config.isYes or (_: false); + in + lib.mkDefault ( + if isYes "ARM64_64K_PAGES" then + 29 + else if isYes "ARM64_16K_PAGES" then + 31 + else + 33 + ) + )) + (lib.mkIf pkgs.stdenv.hostPlatform.isx86_64 (lib.mkDefault 32)) + ]; + "vm.mmap_rnd_compat_bits" = lib.mkIf ( + pkgs.stdenv.hostPlatform.isx86_64 || pkgs.stdenv.hostPlatform.isAarch64 + ) (lib.mkDefault 16); }; }; } From a2ff6e406ea1c970e67c700c6d7b5ecc45ab3f8d Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Sun, 19 Apr 2026 18:02:46 +0100 Subject: [PATCH 3/7] nixos-test-driver: use info/error/debug log feature more --- .../lib/test-driver/src/test_driver/driver.py | 2 +- .../lib/test-driver/src/test_driver/logger.py | 4 +-- .../src/test_driver/machine/__init__.py | 32 +++++++++++++------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/nixos/lib/test-driver/src/test_driver/driver.py b/nixos/lib/test-driver/src/test_driver/driver.py index 8b6a5dfef5a0..414b637feb2f 100644 --- a/nixos/lib/test-driver/src/test_driver/driver.py +++ b/nixos/lib/test-driver/src/test_driver/driver.py @@ -346,7 +346,7 @@ class Driver: vlan_symbols = { f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans) } - print( + self.logger.debug( "additionally exposed symbols:\n " + ", ".join(map(lambda m: m.name, self.machines)) + ",\n " diff --git a/nixos/lib/test-driver/src/test_driver/logger.py b/nixos/lib/test-driver/src/test_driver/logger.py index a5bf7c61c1a4..fe295a14e621 100644 --- a/nixos/lib/test-driver/src/test_driver/logger.py +++ b/nixos/lib/test-driver/src/test_driver/logger.py @@ -248,7 +248,7 @@ class TerminalLogger(AbstractLogger): tic = time.time() yield toc = time.time() - self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)", attributes) + self.info(f"(finished: {message}, in {toc - tic:.2f} seconds)", attributes) def debug(self, *args, **kwargs) -> None: if self._log_level <= LogLevel.DEBUG: @@ -379,6 +379,6 @@ class XMLLogger(AbstractLogger): yield self.drain_log_queue() toc = time.time() - self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)") + self.info(f"(finished: {message}, in {toc - tic:.2f} seconds)") self.xml.endElement("nest") 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 909a906a9a0d..3ec746a7c09b 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -271,6 +271,18 @@ class BaseMachine(ABC): """ self.logger.log(msg, {"machine": self.name}) + def debug(self, msg: str) -> None: + """ + Log a message to console with log level for debug. + """ + self.logger.debug(msg, {"machine": self.name}) + + def error(self, msg: str) -> None: + """ + Log a message to console with log level for error. + """ + self.logger.error(msg, {"machine": self.name}) + def log_serial(self, msg: str) -> None: self.logger.log_serial(msg, self.name) @@ -855,7 +867,7 @@ class QemuMachine(BaseMachine): def tty_matches(last_try: bool) -> bool: text = self.get_tty_text(tty) if last_try: - self.log( + self.debug( f"Last chance to match /{regexp}/ on TTY{tty}, " f"which currently contains: {text}" ) @@ -1061,8 +1073,8 @@ class QemuMachine(BaseMachine): toc = time.time() - self.log("connected to guest root shell") - self.log(f"(connecting took {toc - tic:.2f} seconds)") + self.debug("connected to guest root shell") + self.debug(f"(connecting took {toc - tic:.2f} seconds)") self.connected = True @contextmanager @@ -1225,7 +1237,7 @@ class QemuMachine(BaseMachine): if self.booted: return - self.log("starting vm") + self.debug("starting vm") def clear(path: Path) -> Path: if path.exists(): @@ -1299,7 +1311,7 @@ class QemuMachine(BaseMachine): self.pid = self.process.pid self.booted = True - self.log(f"QEMU running (pid {self.pid})") + self.debug(f"QEMU running (pid {self.pid})") def shutdown(self) -> None: """ @@ -1402,7 +1414,7 @@ class QemuMachine(BaseMachine): def release(self) -> None: if self.pid is None: return - self.logger.info(f"kill QemuMachine (pid {self.pid})") + self.logger.debug(f"kill QemuMachine (pid {self.pid})") assert self.process assert self.shell assert self.monitor @@ -1492,7 +1504,7 @@ class NspawnMachine(BaseMachine): if self.machine_sock: self.machine_sock.close() - self.logger.info(f"kill NspawnMachine (pid {self.pid})") + self.logger.debug(f"kill NspawnMachine (pid {self.pid})") assert self.process is not None self.process.terminate() self.process = None @@ -1610,7 +1622,7 @@ class NspawnMachine(BaseMachine): proc = self.process # 1. Wait for the directory to actually be created by the container - self.log(f"Waiting for journal at {journal_path}...") + self.debug(f"Waiting for journal at {journal_path}...") max_attempts = 10 attempts = 0 while not journal_path.exists() and attempts < max_attempts: @@ -1647,7 +1659,7 @@ class NspawnMachine(BaseMachine): if proc.poll() is not None: break except Exception as e: - self.log(f"Error while reading journalctl output: {e}") + self.error(f"Error while reading journalctl output: {e}") finally: log_proc.terminate() log_proc.wait() @@ -1685,7 +1697,7 @@ class NspawnMachine(BaseMachine): self.pid = self.process.pid - self.log(f"systemd-nspawn running (pid {self.pid})") + self.debug(f"systemd-nspawn running (pid {self.pid})") journal_thread = threading.Thread(target=self._stream_journal, daemon=True) journal_thread.start() From 1ecef5cad6ddc666b558a0655f647c80d7060483 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Sun, 19 Apr 2026 14:58:26 +0100 Subject: [PATCH 4/7] nixos-test-driver: require "/dev/net" in tests that need containers --- nixos/doc/manual/redirects.json | 18 ++++++++++ nixos/lib/testing/run.nix | 62 +++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index 2cad40493dc5..88cb8f37f146 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -1466,6 +1466,24 @@ "module-services-mailman-other-mtas": [ "index.html#module-services-mailman-other-mtas" ], + "test-opt-requiredFeatures": [ + "index.html#test-opt-requiredFeatures" + ], + "test-opt-requiredFeatures.apple-virt": [ + "index.html#test-opt-requiredFeatures.apple-virt" + ], + "test-opt-requiredFeatures.devnet": [ + "index.html#test-opt-requiredFeatures.devnet" + ], + "test-opt-requiredFeatures.kvm": [ + "index.html#test-opt-requiredFeatures.kvm" + ], + "test-opt-requiredFeatures.nixos-test": [ + "index.html#test-opt-requiredFeatures.nixos-test" + ], + "test-opt-requiredFeatures.uid-range": [ + "index.html#test-opt-requiredFeatures.uid-range" + ], "trezor": [ "index.html#trezor" ], diff --git a/nixos/lib/testing/run.nix b/nixos/lib/testing/run.nix index fcdd81412123..71d4e46f6d4f 100644 --- a/nixos/lib/testing/run.nix +++ b/nixos/lib/testing/run.nix @@ -3,6 +3,7 @@ hostPkgs, lib, containers, + nodes, options, ... }: @@ -28,9 +29,62 @@ let */ f: lib.mkOverride (opt.highestPrio - 1) (f opt.value); + + requiredFeaturesModuleType = { + freeformType = types.attrsOf types.bool; + options = { + devnet = mkOption { + type = types.bool; + default = + builtins.length (lib.attrNames containers) > 0 && builtins.length (lib.attrNames nodes) > 0; + defaultText = lib.literalMD "`true` if both VMs and containers are present."; + description = '' + This heuristic setting that assumes that the majority of tests requires VMs and containers + to communicate over network. To support such tests, adding "/dev/net" to `nix.settings.extra-sandbox-paths` is necessary. + + Override this to `false` if the heuristic is wrong in some cases. + ''; + }; + nixos-test = mkOption { + type = types.bool; + default = true; + description = "Standard requirement for NixOS integration tests"; + }; + uid-range = mkOption { + type = types.bool; + default = builtins.length (lib.attrNames containers) > 0; + defaultText = lib.literalMD "`true` if containers are present."; + description = "Containers use systemd-nspawn, which requires pid 0 inside of the sandbox. `uid-range` enables that."; + }; + kvm = mkOption { + type = types.bool; + default = isLinux; + defaultText = lib.literalMD "`true` if built to run on Linux."; + description = "Whether Linux KVM virtualization is required when running this test. Can be disabled to allow emulated execution."; + }; + apple-virt = mkOption { + type = types.bool; + default = isDarwin; + defaultText = lib.literalMD "`true` if built to run on Darwin."; + description = "Whether Apple virtualization functionality is required for running this test."; + }; + }; + }; in { options = { + requiredFeatures = mkOption { + description = "Builder features that are required for running this test."; + example = lib.literalExpression '' + { + cuda = true; + devnet = mkForce false; + } + ''; + type = types.submodule requiredFeaturesModuleType; + default = { }; # this is necessary due to a bug in the module system. + }; + passthru = mkOption { type = types.lazyAttrsOf types.raw; description = '' @@ -98,13 +152,7 @@ in { name = "vm-test-run-${config.name}"; - requiredSystemFeatures = [ - "nixos-test" - ] - # Containers use systemd-nspawn, which requires pid 0 inside of the sandbox. - ++ lib.optional (builtins.length (lib.attrNames containers) > 0) "uid-range" - ++ lib.optional isLinux "kvm" - ++ lib.optional isDarwin "apple-virt"; + requiredSystemFeatures = lib.attrNames (lib.filterAttrs (_: v: v) config.requiredFeatures); nativeBuildInputs = lib.optionals config.enableDebugHook [ hostPkgs.openssh From 4c907dbb68ff92ec570bedfc53ad58d67862e48b Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Mon, 20 Apr 2026 22:11:01 +0200 Subject: [PATCH 5/7] Revert "nixos-test-driver: use info/error/debug log feature more" This reverts commit a2ff6e406ea1c970e67c700c6d7b5ecc45ab3f8d. Pushed by accident to staging-nixos: https://matrix.to/#/%21UNVBThoJtlIiVwiDjU%3Anixos.org/%24UUtlLXPAwZaoeDXDT0wHC1PRZIWVhRNNgyvkKTVRG24?via=nixos.org&via=matrix.org&via=tchncs.de --- .../lib/test-driver/src/test_driver/driver.py | 2 +- .../lib/test-driver/src/test_driver/logger.py | 4 +-- .../src/test_driver/machine/__init__.py | 32 ++++++------------- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/nixos/lib/test-driver/src/test_driver/driver.py b/nixos/lib/test-driver/src/test_driver/driver.py index 414b637feb2f..8b6a5dfef5a0 100644 --- a/nixos/lib/test-driver/src/test_driver/driver.py +++ b/nixos/lib/test-driver/src/test_driver/driver.py @@ -346,7 +346,7 @@ class Driver: vlan_symbols = { f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans) } - self.logger.debug( + print( "additionally exposed symbols:\n " + ", ".join(map(lambda m: m.name, self.machines)) + ",\n " diff --git a/nixos/lib/test-driver/src/test_driver/logger.py b/nixos/lib/test-driver/src/test_driver/logger.py index fe295a14e621..a5bf7c61c1a4 100644 --- a/nixos/lib/test-driver/src/test_driver/logger.py +++ b/nixos/lib/test-driver/src/test_driver/logger.py @@ -248,7 +248,7 @@ class TerminalLogger(AbstractLogger): tic = time.time() yield toc = time.time() - self.info(f"(finished: {message}, in {toc - tic:.2f} seconds)", attributes) + self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)", attributes) def debug(self, *args, **kwargs) -> None: if self._log_level <= LogLevel.DEBUG: @@ -379,6 +379,6 @@ class XMLLogger(AbstractLogger): yield self.drain_log_queue() toc = time.time() - self.info(f"(finished: {message}, in {toc - tic:.2f} seconds)") + self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)") self.xml.endElement("nest") 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 3ec746a7c09b..909a906a9a0d 100644 --- a/nixos/lib/test-driver/src/test_driver/machine/__init__.py +++ b/nixos/lib/test-driver/src/test_driver/machine/__init__.py @@ -271,18 +271,6 @@ class BaseMachine(ABC): """ self.logger.log(msg, {"machine": self.name}) - def debug(self, msg: str) -> None: - """ - Log a message to console with log level for debug. - """ - self.logger.debug(msg, {"machine": self.name}) - - def error(self, msg: str) -> None: - """ - Log a message to console with log level for error. - """ - self.logger.error(msg, {"machine": self.name}) - def log_serial(self, msg: str) -> None: self.logger.log_serial(msg, self.name) @@ -867,7 +855,7 @@ class QemuMachine(BaseMachine): def tty_matches(last_try: bool) -> bool: text = self.get_tty_text(tty) if last_try: - self.debug( + self.log( f"Last chance to match /{regexp}/ on TTY{tty}, " f"which currently contains: {text}" ) @@ -1073,8 +1061,8 @@ class QemuMachine(BaseMachine): toc = time.time() - self.debug("connected to guest root shell") - self.debug(f"(connecting took {toc - tic:.2f} seconds)") + self.log("connected to guest root shell") + self.log(f"(connecting took {toc - tic:.2f} seconds)") self.connected = True @contextmanager @@ -1237,7 +1225,7 @@ class QemuMachine(BaseMachine): if self.booted: return - self.debug("starting vm") + self.log("starting vm") def clear(path: Path) -> Path: if path.exists(): @@ -1311,7 +1299,7 @@ class QemuMachine(BaseMachine): self.pid = self.process.pid self.booted = True - self.debug(f"QEMU running (pid {self.pid})") + self.log(f"QEMU running (pid {self.pid})") def shutdown(self) -> None: """ @@ -1414,7 +1402,7 @@ class QemuMachine(BaseMachine): def release(self) -> None: if self.pid is None: return - self.logger.debug(f"kill QemuMachine (pid {self.pid})") + self.logger.info(f"kill QemuMachine (pid {self.pid})") assert self.process assert self.shell assert self.monitor @@ -1504,7 +1492,7 @@ class NspawnMachine(BaseMachine): if self.machine_sock: self.machine_sock.close() - self.logger.debug(f"kill NspawnMachine (pid {self.pid})") + self.logger.info(f"kill NspawnMachine (pid {self.pid})") assert self.process is not None self.process.terminate() self.process = None @@ -1622,7 +1610,7 @@ class NspawnMachine(BaseMachine): proc = self.process # 1. Wait for the directory to actually be created by the container - self.debug(f"Waiting for journal at {journal_path}...") + self.log(f"Waiting for journal at {journal_path}...") max_attempts = 10 attempts = 0 while not journal_path.exists() and attempts < max_attempts: @@ -1659,7 +1647,7 @@ class NspawnMachine(BaseMachine): if proc.poll() is not None: break except Exception as e: - self.error(f"Error while reading journalctl output: {e}") + self.log(f"Error while reading journalctl output: {e}") finally: log_proc.terminate() log_proc.wait() @@ -1697,7 +1685,7 @@ class NspawnMachine(BaseMachine): self.pid = self.process.pid - self.debug(f"systemd-nspawn running (pid {self.pid})") + self.log(f"systemd-nspawn running (pid {self.pid})") journal_thread = threading.Thread(target=self._stream_journal, daemon=True) journal_thread.start() From 861fa36af2d740826ca18a7547bdc5f3a817d452 Mon Sep 17 00:00:00 2001 From: Jost Alemann Date: Tue, 21 Apr 2026 11:24:48 +0200 Subject: [PATCH 6/7] ty: 0.0.31 -> 0.0.32 Changelog: https://github.com/astral-sh/ty/releases/tag/0.0.32 Diff: https://github.com/astral-sh/ty/compare/0.0.31...0.0.32 --- pkgs/by-name/ty/ty/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/ty/ty/package.nix b/pkgs/by-name/ty/ty/package.nix index 471069fe1b54..cab90cffbd0d 100644 --- a/pkgs/by-name/ty/ty/package.nix +++ b/pkgs/by-name/ty/ty/package.nix @@ -14,14 +14,14 @@ rustPlatform.buildRustPackage (finalAttrs: { pname = "ty"; - version = "0.0.31"; + version = "0.0.32"; src = fetchFromGitHub { owner = "astral-sh"; repo = "ty"; tag = finalAttrs.version; fetchSubmodules = true; - hash = "sha256-TJGEI22hp+YZCxIvZgNc8BF2Dd+z/TzpnRW2pO1f3X0="; + hash = "sha256-534/xT6JfbgEboH1q4R4JTl2/gLKKs1wU9eqoZf0Asw="; }; # For Darwin platforms, remove the integration test for file notifications, @@ -35,7 +35,7 @@ rustPlatform.buildRustPackage (finalAttrs: { cargoBuildFlags = [ "--package=ty" ]; - cargoHash = "sha256-JTE/zRf+VqBoLaoMaQ4ioVsr3Njm3OGkpMMnsPg3lsA="; + cargoHash = "sha256-uQkrvSmvQXJj+WlGLI+2fHNQeCd1eYJrJJ1z3OZSHbA="; nativeBuildInputs = [ installShellFiles ]; From d2c949d725459d0dc2160f910b28cd2625c1d552 Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Sun, 18 Jan 2026 22:48:32 +0100 Subject: [PATCH 7/7] nixos/dbus: switch default implementation to dbus-broker dbus-broker provides higher performance and reliability compared to the classic dbus-daemon. The prerequisite PR #477800 has been merged, making this switch safe. Note that services.dbus.implementation is a switch inhibitor: changing the D-Bus implementation between generations requires a reboot rather than nixos-rebuild switch, since restarting D-Bus mid-session is unsafe. Fixes #299476 --- nixos/doc/manual/release-notes/rl-2605.section.md | 9 +++++++++ nixos/modules/services/system/dbus.nix | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/nixos/doc/manual/release-notes/rl-2605.section.md b/nixos/doc/manual/release-notes/rl-2605.section.md index f883372fd450..edc589c2193e 100644 --- a/nixos/doc/manual/release-notes/rl-2605.section.md +++ b/nixos/doc/manual/release-notes/rl-2605.section.md @@ -42,6 +42,15 @@ - The default kernel package has been updated from 6.12 to 6.18. All supported kernels remain available. +- The default D-Bus implementation has been switched from `dbus` to `dbus-broker`. dbus-broker provides + higher performance and reliability while maintaining compatibility with the D-Bus reference implementation. + + Note that changing `services.dbus.implementation` is a **switch inhibitor**: switching between + implementations requires a reboot rather than just `nixos-rebuild switch`, because restarting D-Bus + mid-session is unsafe. + + Users who wish to keep the classic daemon can set: `services.dbus.implementation = "dbus";` + ## New Modules {#sec-release-26.05-new-modules} diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 8cb03b08c2f6..3e4b4ecd1530 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -68,7 +68,7 @@ in "dbus" "broker" ]; - default = "dbus"; + default = "broker"; description = '' The implementation to use for the message bus defined by the D-Bus specification. Can be either the classic dbus daemon or dbus-broker, which aims to provide high