From dc6f2c134f1f023f9ebd266ea76f59284744dc66 Mon Sep 17 00:00:00 2001 From: nikstur Date: Thu, 4 Jun 2026 00:35:13 +0200 Subject: [PATCH 1/2] systemd: add README This establishes a repeatable and clear process for preparing and testing changes to systemd. It should help existing maintainers to follow a consistent process with clear judgment (when these tests pass, the change is good to merge) and potential new maintainers. --- pkgs/os-specific/linux/systemd/README.md | 86 ++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 pkgs/os-specific/linux/systemd/README.md diff --git a/pkgs/os-specific/linux/systemd/README.md b/pkgs/os-specific/linux/systemd/README.md new file mode 100644 index 000000000000..41e4f12e9400 --- /dev/null +++ b/pkgs/os-specific/linux/systemd/README.md @@ -0,0 +1,86 @@ +# Maintaining systemd + +This document guides you through some of the important parts of maintaining +systemd. + +## Preparing and Testing Changes + +Changing systemd (most importantly updating!) is quite cumbersome: + +- It is very close to the root of the dependency tree and thus causes rebuilds + of a lot of packages. It always needs to target staging. +- ALL tests need to be rebuilt if systemd changes because systemd is a + mandatory part of NixOS. + +To alleviate this, we have a special procedure for preparing and testing +changes to systemd. It is quite different from maintaining other packages in +Nixpkgs. Please read this carefully if you want to open a PR for systemd. + +1. In your fork of Nixpkgs, create a new branch from the merge base of the + master branch and staging. Changes to systemd need to target staging and + this helps to keep the number of rebuilds minimal. + +```sh +git switch --create systemd-changes $(git merge-base upstream/master upstream/staging) +``` + +2. Change the systemd package. Test it by (1) building the systemd package and + (2) building `systemd.nixosTests.simple-vm`. When this is successful, commit the + changes. + +3. Check out master again and add your new branch to a new worktree. + +```sh +git switch master +git worktree add ../systemd-changes systemd-changes +``` + +4. Apply this patch to your master checkout of Nixpkgs so that all tests use + the systemd package from the newly created worktree. This allows you to only + rebuild the systemd package itself without having to build all the other + packages that depend on systemd. Note that the path for `systemdTest` in + this patch will depend on the name of your worktree. + +```patch +diff --git i/nixos/modules/module-list.nix w/nixos/modules/module-list.nix +index c57b627e875c..89f026efd786 100644 +--- i/nixos/modules/module-list.nix ++++ w/nixos/modules/module-list.nix +@@ -2040,4 +2040,5 @@ + ./image/repart.nix + ]; + } ++ ({ pkgs, ... }: {systemd.package = pkgs.systemdTest;}) + ] +diff --git i/pkgs/top-level/all-packages.nix w/pkgs/top-level/all-packages.nix +index 0e2defb6566c..c60c1f201828 100644 +--- i/pkgs/top-level/all-packages.nix ++++ w/pkgs/top-level/all-packages.nix +@@ -8538,6 +8538,10 @@ with pkgs; + + libsysprof-capture = callPackage ../development/tools/profiling/sysprof/capture.nix { }; + ++ systemdTest = callPackage ../../../systemd-changes/pkgs/os-specific/linux/systemd { ++ # break some cyclic dependencies ++ util-linux = util-linuxMinimal; ++ }; + systemd = callPackage ../os-specific/linux/systemd { + # break some cyclic dependencies + util-linux = util-linuxMinimal; +``` + +5. Build all the systemd NixOS tests + +```sh +nix-build -A systemd.nixosTests +``` + +You are encouraged to use a tool like [brr](https://github.com/nikstur/brr) or +[nix-fast-build](https://github.com/Mic92/nix-fast-build) to speed up +evaluation and building all these tests. + +In conclusion, there are three quality gates for changes to systemd: + +1. The package needs to build on staging. +2. The test `systemd.nixosTests.simple-vm` needs to pass on staging. +3. All `systemd.nixosTests` must pass on master with the changed systemd from a separate worktree. From 640c05e8f315ac9b59b06f92a68f45aa06a5801a Mon Sep 17 00:00:00 2001 From: nikstur Date: Thu, 4 Jun 2026 00:37:34 +0200 Subject: [PATCH 2/2] systemd: add passthru.nixosTests Reorganize the passthru.tests to be able to comment out/disable individual tests that were previously hidden in an attrset. Also comment out tests that are currently broken on master. Once this is merged, the tests in passthru.nixosTests serve as a hard quality gate for merging changes to systemd as per the newly addded README that lives next to the systemd derivation. These tests were only commented out because I believe they are still valuable and should be fixed. However, actually fixing them is out of scope for this change. This removed the `installer-systemd-stage-1` tests because they were to costly to evaluate and build for normal maintainers. We also don't have all the other installer tests here. All tests use systemd, but we need to balance the executability in a sensible timescale with test coverage. --- pkgs/os-specific/linux/systemd/default.nix | 220 ++++++++++++--------- 1 file changed, 127 insertions(+), 93 deletions(-) diff --git a/pkgs/os-specific/linux/systemd/default.nix b/pkgs/os-specific/linux/systemd/default.nix index e589188a6099..7451a098ae33 100644 --- a/pkgs/os-specific/linux/systemd/default.nix +++ b/pkgs/os-specific/linux/systemd/default.nix @@ -710,106 +710,140 @@ stdenv.mkDerivation (finalAttrs: { # enabled. See https://github.com/systemd/systemd/blob/876ee10e0eb4bbb0920bdab7817a9f06cc34910f/units/meson.build#L521 withTpm2Units = withTpm2Tss && withBootloader && withOpenSSL; - tests = + # These are all the tests that need to pass in order to merge a PR that + # updates systemd. + # + # This list cannot grow indefinitely. It needs to balance the coverage of + # important features of a NixOS system exposed via systemd and the actual + # ability of maintainers to execute the tests. Only if this remains + # executable with reasonable effort, can it serve its purpose as a quality + # gate for updating systemd. + nixosTests = let - # Some entries in the `nixosTests.systemd-*` set of attributes are collections of tests, - # not individual tests themselves. Let's gather them into one set. - gatherNixosTestsFromCollection = - prefix: collection: + prefixTests = + prefix: lib.mapAttrs' (name: value: { name = "${prefix}-${name}"; inherit value; - }) collection; - - # Here's all the nixosTests that are collections of tests, rather than individual tests. - collectedNixosTests = lib.mergeAttrsList ( - lib.mapAttrsToList gatherNixosTestsFromCollection { - inherit (nixosTests) - systemd-binfmt - systemd-boot - systemd-initrd-networkd - systemd-repart - installer-systemd-stage-1 - ; - } - ); - - # ... and here's all the individual tests. - individualNixosTests = { - inherit (nixosTests) - fsck-systemd-stage-1 - hibernate-systemd-stage-1 - switchTest - systemd - systemd-analyze - systemd-bpf - systemd-confinement - systemd-coredump - systemd-cryptenroll - systemd-credentials-tpm2 - systemd-escaping - systemd-initrd-btrfs-raid - systemd-initrd-luks-fido2 - systemd-initrd-luks-keyfile - systemd-initrd-luks-empty-passphrase - systemd-initrd-luks-password - systemd-initrd-luks-tpm2 - systemd-initrd-modprobe - systemd-initrd-shutdown - systemd-initrd-simple - systemd-initrd-swraid - systemd-initrd-vconsole - systemd-initrd-networkd-ssh - systemd-initrd-networkd-openvpn - systemd-initrd-vlan - systemd-journal - systemd-journal-gateway - systemd-journal-upload - systemd-machinectl - systemd-networkd - systemd-networkd-bridge - systemd-networkd-dhcpserver - systemd-networkd-dhcpserver-static-leases - systemd-networkd-ipv6-prefix-delegation - systemd-networkd-vrf - systemd-no-tainted - systemd-nspawn - systemd-nspawn-configfile - systemd-oomd - systemd-portabled - systemd-pstore - systemd-resolved - systemd-shutdown - systemd-sysupdate - systemd-sysusers-mutable - systemd-sysusers-immutable - systemd-sysusers-password-option-override-ordering - systemd-timesyncd-nscd-dnssec - systemd-user-linger - systemd-user-tmpfiles-rules - systemd-misc - systemd-userdbd - systemd-homed - ; - }; - - # Finally, make an attrset we're fairly sure is just tests. - relevantNixosTests = lib.mapAttrs ( - name: value: - assert lib.assertMsg (lib.isDerivation value) "${name} is not a derivation"; - value - ) (individualNixosTests // collectedNixosTests); + }) nixosTests."${prefix}"; in - relevantNixosTests + { + inherit (prefixTests "systemd-binfmt") + systemd-binfmt-basic + systemd-binfmt-chroot + systemd-binfmt-ldPreload + systemd-binfmt-preserveArgvZero + ; + } // { - cross = - let - systemString = if stdenv.buildPlatform.isAarch64 then "gnu64" else "aarch64-multiplatform"; - in - pkgsCross.${systemString}.systemd; - - pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; + inherit (prefixTests "systemd-initrd-networkd") + systemd-initrd-networkd-basic + systemd-initrd-networkd-doFlush + systemd-initrd-networkd-dontFlush + ; + } + // { + inherit (prefixTests "systemd-boot") + systemd-boot-basic + systemd-boot-basicXbootldr + systemd-boot-bootCounting + systemd-boot-bootCountingSpecialisation + systemd-boot-defaultEntry + systemd-boot-defaultEntryWithBootCounting + systemd-boot-edk2-uefi-shell + systemd-boot-entryFilenameXbootldr + systemd-boot-extraEntries + systemd-boot-extraFiles + systemd-boot-fallback + systemd-boot-garbage-collect-entry + systemd-boot-garbageCollectEntryWithBootCounting + systemd-boot-memtest86 + systemd-boot-memtestSortKey + systemd-boot-netbootxyz + systemd-boot-secureBoot + systemd-boot-specialisation + systemd-boot-switch-test + systemd-boot-update + systemd-boot-windows + ; + } + // { + inherit (prefixTests "systemd-repart") + systemd-repart-after-initrd + systemd-repart-basic + systemd-repart-create-root + systemd-repart-encrypt-tpm2 + systemd-repart-factory-reset + ; + } + // { + inherit (nixosTests) + simple-vm + fsck-systemd-stage-1 + hibernate-systemd-stage-1 + switchTest + # systemd # broken on master + systemd-analyze + systemd-bpf + systemd-confinement + # systemd-coredump # broken on master + systemd-cryptenroll + systemd-credentials-tpm2 + systemd-escaping + systemd-initrd-btrfs-raid + # systemd-initrd-luks-fido2 # broken on master + systemd-initrd-luks-keyfile + systemd-initrd-luks-empty-passphrase + systemd-initrd-luks-password + systemd-initrd-luks-tpm2 + systemd-initrd-modprobe + systemd-initrd-shutdown + systemd-initrd-simple + systemd-initrd-swraid + # systemd-initrd-vconsole # broken on master + systemd-initrd-networkd-ssh + systemd-initrd-networkd-openvpn + systemd-initrd-vlan + systemd-journal + # systemd-journal-gateway # broken on master + systemd-journal-upload + # systemd-machinectl # broken on master + systemd-networkd + systemd-networkd-bridge + systemd-networkd-dhcpserver + systemd-networkd-dhcpserver-static-leases + systemd-networkd-ipv6-prefix-delegation + systemd-networkd-vrf + systemd-no-tainted + systemd-nspawn + systemd-nspawn-configfile + systemd-oomd + systemd-portabled + systemd-pstore + systemd-resolved + systemd-shutdown + systemd-sysupdate + systemd-sysusers-mutable + systemd-sysusers-immutable + systemd-sysusers-password-option-override-ordering + # systemd-timesyncd-nscd-dnssec # broken on master + systemd-user-linger + systemd-user-tmpfiles-rules + systemd-misc + systemd-userdbd + # systemd-homed # broken on master + ; }; + + tests = finalAttrs.passthru.nixosTests // { + cross = + let + systemString = if stdenv.buildPlatform.isAarch64 then "gnu64" else "aarch64-multiplatform"; + in + pkgsCross.${systemString}.systemd; + + pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; + }; }; meta = {