diff --git a/nixos/modules/config/power-management.nix b/nixos/modules/config/power-management.nix index 6b2253068c0b..b5ae488697a2 100644 --- a/nixos/modules/config/power-management.nix +++ b/nixos/modules/config/power-management.nix @@ -62,6 +62,19 @@ in config = lib.mkIf cfg.enable { + warnings = lib.optional (cfg.powerUpCommands != "") '' + powerManagement.powerUpCommands is deprecated due to it having unclear ordering semantics. + It will be removed in NixOS 26.11. + It is recommended to create an explicit systemd oneshot service instead, + that is pulled in at the right time during the boot process. + See https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html + for more information on possible targets that can be used for this. + + If you also want to run this service upon waking up from resume, the recommended + method to do so is described here: + https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html#sleep.target + ''; + systemd.targets.post-resume = { description = "Post-Resume Actions"; requires = [ "post-resume.service" ]; @@ -81,14 +94,25 @@ in serviceConfig.Type = "oneshot"; }; + systemd.services.post-boot = { + description = "Post-boot Actions"; + # It's not well defined at what point in the bootup sequence this should run + # we should eventually just remove this. + wantedBy = [ "multi-user.target" ]; + restartIfChanged = false; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + ${cfg.powerUpCommands} + ''; + }; + systemd.services.post-resume = { description = "Post-Resume Actions"; - after = [ - "suspend.target" - "hibernate.target" - "hybrid-sleep.target" - "suspend-then-hibernate.target" - ]; + # Pulled in by post-resume.service above + after = [ "sleep.target" ]; script = '' /run/current-system/systemd/bin/systemctl try-restart --no-block post-resume.target ${cfg.resumeCommands} diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index c289d1961205..b87e5ccad65f 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -742,6 +742,8 @@ in }; systemd = { + generatorPath = [ cfg.package ]; + sockets.sshd = lib.mkIf cfg.startWhenNeeded { description = "SSH Socket"; wantedBy = [ "sockets.target" ]; diff --git a/nixos/modules/system/activation/nixos-init.nix b/nixos/modules/system/activation/nixos-init.nix index 9d5094017c0b..1ab2e546d40a 100644 --- a/nixos/modules/system/activation/nixos-init.nix +++ b/nixos/modules/system/activation/nixos-init.nix @@ -58,10 +58,6 @@ in assertion = config.boot.postBootCommands == ""; message = "nixos-init cannot be used with boot.postBootCommands"; } - { - assertion = config.powerManagement.powerUpCommands == ""; - message = "nixos-init cannot be used with powerManagement.powerUpCommands"; - } ]; }) ]; diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix index 680f5eed55c0..9b72391c20ac 100644 --- a/nixos/modules/system/boot/stage-2.nix +++ b/nixos/modules/system/boot/stage-2.nix @@ -30,7 +30,6 @@ let ); postBootCommands = pkgs.writeText "local-cmds" '' ${config.boot.postBootCommands} - ${config.powerManagement.powerUpCommands} ''; }; }; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 2d81b1bb3d44..467a5d04516f 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -233,6 +233,8 @@ let proxy_env = config.networking.proxy.envVars; + json = pkgs.formats.json { }; + in { @@ -356,6 +358,28 @@ in ''; }; + generatorEnvironment = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { + MY_VAR = "my-value"; + }; + description = '' + Environment variables for systemd generators. + + The `PATH` environment variable is populated via `systemd.generatorPath`. + ''; + }; + + generatorPath = mkOption { + type = types.listOf types.package; + default = [ ]; + example = lib.literalExpression "[ pkgs.hello ]"; + description = '' + Packages added to the `PATH` environment variable of all systemd generators. + ''; + }; + shutdown = mkOption { type = types.attrsOf types.path; default = { }; @@ -636,6 +660,12 @@ in "systemd/user-preset/00-nixos.preset".text = '' ignore * ''; + + "systemd/generator-environment.json".source = + json.generate "systemd-generator-environment.json" cfg.generatorEnvironment; + + "systemd/system-environment-generators/env-generator".source = + "${config.system.nixos-init.package}/bin/env-generator"; }; services.dbus.enable = true; @@ -683,12 +713,7 @@ in systemd.managerEnvironment = { # Doesn't contain systemd itself - everything works so it seems to use the compiled-in value for its tools # util-linux is needed for the main fsck utility wrapping the fs-specific ones - PATH = lib.makeBinPath ( - config.system.fsPackages - ++ [ cfg.package.util-linux ] - # systemd-ssh-generator needs sshd in PATH - ++ lib.optional config.services.openssh.enable config.services.openssh.package - ); + PATH = lib.makeBinPath (config.system.fsPackages ++ [ cfg.package.util-linux ]); LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; TZDIR = "/etc/zoneinfo"; # If SYSTEMD_UNIT_PATH ends with an empty component (":"), the usual unit load path will be appended to the contents of the variable @@ -704,6 +729,16 @@ in DefaultIPAccounting = lib.mkDefault true; }; + # These are needed for systemd-fstab-generator to schedule systemd-fsck@ + # units. + systemd.generatorPath = config.system.fsPackages ++ [ + cfg.package.util-linux + ]; + + systemd.generatorEnvironment = { + PATH = lib.makeBinPath cfg.generatorPath; + }; + system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled [ "DEVTMPFS" "CGROUPS" diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index 9f67f937c2f1..ad0121a48498 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -92,6 +92,7 @@ let # Declare root explicitly to avoid shellcheck warnings, it comes from the env declare root + mkdir -p "$root/usr/bin" mkdir -p "$root/etc" "$root/var/lib" chmod 0755 "$root/etc" "$root/var/lib" mkdir -p "$root/var/lib/private" "$root/root" /run/nixos-containers diff --git a/nixos/tests/initrd-luks-empty-passphrase.nix b/nixos/tests/initrd-luks-empty-passphrase.nix index 47215c4bc998..3a906685f0ca 100644 --- a/nixos/tests/initrd-luks-empty-passphrase.nix +++ b/nixos/tests/initrd-luks-empty-passphrase.nix @@ -19,8 +19,6 @@ in nodes.machine = { pkgs, ... }: { - imports = lib.optionals (!systemdStage1) [ ./common/auto-format-root-device.nix ]; - virtualisation = { emptyDiskImages = [ 512 ]; useBootLoader = true; @@ -30,7 +28,6 @@ in # the new root device is /dev/vdb # an empty 512MiB drive, containing no Nix store. mountHostNixStore = true; - fileSystems."/".autoFormat = lib.mkIf systemdStage1 true; }; boot.loader.systemd-boot.enable = true; @@ -90,6 +87,8 @@ in # Create encrypted volume machine.wait_for_unit("multi-user.target") machine.succeed("echo "" | cryptsetup luksFormat /dev/vdb --batch-mode") + machine.succeed("echo "" | cryptsetup luksOpen /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks-wrong-keyfile.conf") machine.succeed("sync") machine.crash() diff --git a/nixos/tests/luks.nix b/nixos/tests/luks.nix index 685643c4c9dc..7440d110ad28 100644 --- a/nixos/tests/luks.nix +++ b/nixos/tests/luks.nix @@ -5,7 +5,6 @@ nodes.machine = { pkgs, ... }: { - imports = [ ./common/auto-format-root-device.nix ]; # Use systemd-boot virtualisation = { @@ -48,7 +47,12 @@ # Create encrypted volume machine.wait_for_unit("multi-user.target") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -") + machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") + machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -") + machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdc cryptroot2") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2") # Boot from the encrypted disk machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf") diff --git a/nixos/tests/systemd-initrd-luks-keyfile.nix b/nixos/tests/systemd-initrd-luks-keyfile.nix index 3723307946dd..8b7f28947f72 100644 --- a/nixos/tests/systemd-initrd-luks-keyfile.nix +++ b/nixos/tests/systemd-initrd-luks-keyfile.nix @@ -38,7 +38,6 @@ in }; }; virtualisation.rootDevice = "/dev/mapper/cryptroot"; - virtualisation.fileSystems."/".autoFormat = true; boot.initrd.secrets."/etc/cryptroot.key" = keyfile; }; }; @@ -47,6 +46,8 @@ in # Create encrypted volume machine.wait_for_unit("multi-user.target") machine.succeed("cryptsetup luksFormat -q --iter-time=1 -d ${keyfile} /dev/vdb") + machine.succeed("cryptsetup luksOpen --key-file ${keyfile} /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") # Boot from the encrypted disk machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf") diff --git a/nixos/tests/systemd-initrd-luks-password.nix b/nixos/tests/systemd-initrd-luks-password.nix index 0f7c2f51a034..4e059f514257 100644 --- a/nixos/tests/systemd-initrd-luks-password.nix +++ b/nixos/tests/systemd-initrd-luks-password.nix @@ -31,7 +31,6 @@ cryptroot2.device = "/dev/vdc"; }; virtualisation.rootDevice = "/dev/mapper/cryptroot"; - virtualisation.fileSystems."/".autoFormat = true; # test mounting device unlocked in initrd after switching root virtualisation.fileSystems."/cryptroot2".device = "/dev/mapper/cryptroot2"; }; @@ -40,7 +39,11 @@ testScript = '' # Create encrypted volume machine.wait_for_unit("multi-user.target") + machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -") + machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") + machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -") machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdc cryptroot2") machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2") diff --git a/nixos/tests/systemd-initrd-luks-tpm2.nix b/nixos/tests/systemd-initrd-luks-tpm2.nix index 6cc42bbbda73..931959f05464 100644 --- a/nixos/tests/systemd-initrd-luks-tpm2.nix +++ b/nixos/tests/systemd-initrd-luks-tpm2.nix @@ -32,7 +32,6 @@ }; }; virtualisation.rootDevice = "/dev/mapper/cryptroot"; - virtualisation.fileSystems."/".autoFormat = true; }; }; @@ -40,6 +39,8 @@ # Create encrypted volume machine.wait_for_unit("multi-user.target") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -") + machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") machine.succeed("PASSWORD=supersecret SYSTEMD_LOG_LEVEL=debug systemd-cryptenroll --tpm2-pcrs= --tpm2-device=auto /dev/vdb |& systemd-cat") # Boot from the encrypted disk diff --git a/nixos/tests/systemd-initrd-luks-unl0kr.nix b/nixos/tests/systemd-initrd-luks-unl0kr.nix index 875e1beb7187..f9dbce1ccdd8 100644 --- a/nixos/tests/systemd-initrd-luks-unl0kr.nix +++ b/nixos/tests/systemd-initrd-luks-unl0kr.nix @@ -79,9 +79,12 @@ in }; testScript = '' - # Create encrypted volume machine.wait_for_unit("multi-user.target") + machine.succeed("echo -n ${passphrase} | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -") + machine.succeed("echo -n ${passphrase} | cryptsetup luksOpen -q /dev/vdb cryptroot") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot") + machine.succeed("echo -n ${passphrase} | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -") machine.succeed("echo -n ${passphrase} | cryptsetup luksOpen -q /dev/vdc cryptroot2") machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2") diff --git a/nixos/tests/systemd-ssh-proxy.nix b/nixos/tests/systemd-ssh-proxy.nix index 6ccdc0012b4f..38ae79ba9c1c 100644 --- a/nixos/tests/systemd-ssh-proxy.nix +++ b/nixos/tests/systemd-ssh-proxy.nix @@ -19,6 +19,7 @@ in nodes = { virthost = { + environment.systemPackages = [ pkgs.jq ]; services.openssh = { enable = true; settings.PermitRootLogin = "prohibit-password"; @@ -48,6 +49,10 @@ in virthost.succeed("cp '${snakeOilEd25519PrivateKey}' ~/.ssh/id_ed25519") virthost.succeed("chmod 600 ~/.ssh/id_ed25519") + with subtest("Check the environment generator"): + print(virthost.succeed("jq '.' /etc/systemd/generator-environment.json")) + print(virthost.succeed("/etc/systemd/system-environment-generators/env-generator")) + with subtest("ssh into a container with AF_UNIX"): virthost.wait_for_unit("container@guest.service") virthost.wait_until_succeeds("ssh -i ~/.ssh/id_ed25519 unix/run/systemd/nspawn/unix-export/guest/ssh echo meow | grep meow") diff --git a/pkgs/applications/virtualization/qemu/default.nix b/pkgs/applications/virtualization/qemu/default.nix index 9fd672be28de..eab01e012993 100644 --- a/pkgs/applications/virtualization/qemu/default.nix +++ b/pkgs/applications/virtualization/qemu/default.nix @@ -136,11 +136,11 @@ stdenv.mkDerivation (finalAttrs: { + lib.optionalString nixosTestRunner "-for-vm-tests" + lib.optionalString toolsOnly "-utils" + lib.optionalString userOnly "-user"; - version = "10.2.0"; + version = "10.2.1"; src = fetchurl { url = "https://download.qemu.org/qemu-${finalAttrs.version}.tar.xz"; - hash = "sha256-njCtG4ufe0RjABWC0aspfznPzOpdCFQMDKbWZyeFiDo="; + hash = "sha256-o3F0d9jiyE1jC//7wg9s0yk+tFqh5trG0MwnaJmRyeE="; }; depsBuildBuild = [ @@ -267,50 +267,6 @@ stdenv.mkDerivation (finalAttrs: { sha256 = "sha256-oC+bRjEHixv1QEFO9XAm4HHOwoiT+NkhknKGPydnZ5E="; revert = true; }) - - # Implement termios2 (TCGETS2 etc) for glibc 2.42 compatibility. Should be in the next release. - # https://gitlab.com/qemu-project/qemu/-/issues/3065 - # https://lore.kernel.org/qemu-devel/20260103153239.15787-1-dilfridge@gentoo.org/t/#u - (fetchpatch { - name = "0001-Add-termios2-support-to-linux-user.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/e9a8a10e84c1bf6e2e8be000e4dd5c83ba0d8470.patch"; - hash = "sha256-Zc+ZjiSug3uT/F7+mmoYc2VXqw2MV6UubYqB+pr2dNY="; - }) - (fetchpatch { - name = "0002-Add-termios2-support-to-alpha-target.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/8d8c6aeee8599a099e49ec4411f3d1e087ae40ad.patch"; - hash = "sha256-5e5vUp9nr96ZmVA98W/ETReLbkofayysJXlx1Ck9gDs="; - }) - (fetchpatch { - name = "0003-Add-termios2-support-to-hppa-target.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/edc741710acedd61011f937967b960d154794258.patch"; - hash = "sha256-nls6eTOB06eqACjQ/r1sQvb9YaYmrpJcegsDGqKAOaI="; - }) - (fetchpatch { - name = "0004-Add-termios2-support-to-mips-target.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/edf9184f4feb691b0f70dc544443db2380891598.patch"; - hash = "sha256-GrBhyMq2QiCc+WlUwaB9j4G8vB3ipxJRV5Hvyab/5Fk="; - }) - (fetchpatch { - name = "0005-Add-termios2-support-to-sh4-target.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/afbe0ff81c29d674b9c18a588bcaab34ddcb8a7b.patch"; - hash = "sha256-h+9eC6H8/GJ85Lt1Y0ggdJbbgTIvDfIJkPQfX/FgO4c="; - }) - (fetchpatch { - name = "0006-Add-termios2-support-to-sparc-target.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/947b971cad90375040f399899909a3f1f32b483f.patch"; - hash = "sha256-/JvF25aSR2mBSvkpqupDySMJYZI+lv7L0YwhqiaDk3A="; - }) - (fetchpatch { - name = "0007-linux-user-Add-missing-termios-baud-rates.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/4f22fcb5c67f40a36e6654f6cfaee23f9f9e93d1.patch"; - hash = "sha256-CM81yL0/i+fmQe8qzemre13N3A74J1HIC7ilCbb7ESQ="; - }) - (fetchpatch { - name = "0008-linux-user-fixup-termios2-related-things-on-PowerPC.patch"; - url = "https://gitlab.com/qemu-project/qemu/-/commit/d68f0e2e906939bef076d0cd52f902d433c8c3da.patch"; - hash = "sha256-vF47CKqg0wBBOUkHeJ3hv3nUHCftl2OwD3Nh0dL1PNk="; - }) ] ++ lib.optional nixosTestRunner ./force-uid0-on-9p.patch; diff --git a/pkgs/build-support/kernel/make-initrd-ng.nix b/pkgs/build-support/kernel/make-initrd-ng.nix index 0b1db74f0449..768af8f5c48d 100644 --- a/pkgs/build-support/kernel/make-initrd-ng.nix +++ b/pkgs/build-support/kernel/make-initrd-ng.nix @@ -16,7 +16,6 @@ in pkgsBuildHost, makeInitrdNGTool, binutils, - runCommand, # Name of the derivation (not of the resulting file!) name ? "initrd", @@ -74,47 +73,53 @@ in _compressorMeta.ubootName or (throw "Unrecognised compressor ${_compressorName}, please specify uInitrdCompression"), }: -runCommand name - { - compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}"; - passthru = { - compressorExecutableFunction = _compressorFunction; - compressorArgs = _compressorArgsReal; - }; +stdenvNoCC.mkDerivation (finalAttrs: { + __structuredAttrs = true; - inherit - extension - makeUInitrd - uInitrdArch - prepend - ; - ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression; + # the initrd will be self-contained so we can drop references + # to the closure that was used to build it + unsafeDiscardReferences.out = true; - passAsFile = [ "contents" ]; - contents = builtins.toJSON contents; + inherit + name + extension + makeUInitrd + uInitrdArch + prepend + ; + ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression; - nativeBuildInputs = [ - makeInitrdNGTool - cpio - ] - ++ lib.optional makeUInitrd ubootTools; - } - '' + compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}"; + contentsJSON = builtins.toJSON contents; + + nativeBuildInputs = [ + makeInitrdNGTool + cpio + ] + ++ lib.optional makeUInitrd ubootTools; + + buildCommand = '' mkdir -p ./root/{run,tmp,var/empty} ln -s ../run ./root/var/run - make-initrd-ng "$contentsPath" ./root + make-initrd-ng <(echo "$contentsJSON") ./root mkdir "$out" (cd root && find . -exec touch -h -d '@1' '{}' +) - for PREP in $prepend; do + for PREP in ''${prepend[@]}; do cat $PREP >> $out/initrd done (cd root && find . -print0 | sort -z | cpio --quiet -o -H newc -R +0:+0 --reproducible --null | eval -- $compress >> "$out/initrd") if [ -n "$makeUInitrd" ]; then - mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img - # Compatibility symlink - ln -sf "initrd.img" "$out/initrd" + mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img + # Compatibility symlink + ln -sf "initrd.img" "$out/initrd" else - ln -s "initrd" "$out/initrd$extension" + ln -s "initrd" "$out/initrd$extension" fi - '' + ''; + + passthru = { + compressorExecutableFunction = _compressorFunction; + compressorArgs = _compressorArgsReal; + }; +}) diff --git a/pkgs/build-support/kernel/make-initrd.nix b/pkgs/build-support/kernel/make-initrd.nix index 6f300369aa50..364507ba8e7e 100644 --- a/pkgs/build-support/kernel/make-initrd.nix +++ b/pkgs/build-support/kernel/make-initrd.nix @@ -81,42 +81,44 @@ in _compressorMeta.ubootName or (throw "Unrecognised compressor ${_compressorName}, please specify uInitrdCompression"), }: -stdenvNoCC.mkDerivation ( - rec { - inherit - name - makeUInitrd - extension - uInitrdArch - prepend - ; +stdenvNoCC.mkDerivation (finalAttrs: { + __structuredAttrs = true; - builder = ./make-initrd.sh; + # the initrd will be self-contained so we can drop references + # to the closure that was used to build it + unsafeDiscardReferences.out = true; - nativeBuildInputs = [ - cpio - ] - ++ lib.optional makeUInitrd ubootTools; + inherit + name + extension + makeUInitrd + uInitrdArch + prepend + ; + ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression; - compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}"; + builder = ./make-initrd.sh; - # Pass the function through, for reuse in append-initrd-secrets. The - # function is used instead of the string, in order to support - # cross-compilation (append-initrd-secrets running on a different - # architecture than what the main initramfs is built on). - passthru = { - compressorExecutableFunction = _compressorFunction; - compressorArgs = _compressorArgsReal; - }; + nativeBuildInputs = [ + cpio + ] + ++ lib.optional makeUInitrd ubootTools; - # !!! should use XML. - objects = map (x: x.object) contents; - symlinks = map (x: x.symlink) contents; - suffices = map (x: if x ? suffix then x.suffix else "none") contents; + compress = "${_compressorExecutable} ${lib.escapeShellArgs _compressorArgsReal}"; - closureInfo = "${pkgsBuildHost.closureInfo { rootPaths = objects; }}"; - } - // lib.optionalAttrs makeUInitrd { - uInitrdCompression = uInitrdCompression; - } -) + # !!! should use XML. + objects = map (x: x.object) contents; + symlinks = map (x: x.symlink) contents; + suffices = map (x: if x ? suffix then x.suffix else "none") contents; + + closureInfo = "${pkgsBuildHost.closureInfo { rootPaths = finalAttrs.objects; }}"; + + # Pass the function through, for reuse in append-initrd-secrets. The + # function is used instead of the string, in order to support + # cross-compilation (append-initrd-secrets running on a different + # architecture than what the main initramfs is built on). + passthru = { + compressorExecutableFunction = _compressorFunction; + compressorArgs = _compressorArgsReal; + }; +}) diff --git a/pkgs/build-support/kernel/make-initrd.sh b/pkgs/build-support/kernel/make-initrd.sh index cc67c14a6a50..f3bc977279b5 100644 --- a/pkgs/build-support/kernel/make-initrd.sh +++ b/pkgs/build-support/kernel/make-initrd.sh @@ -1,9 +1,5 @@ set -o pipefail -objects=($objects) -symlinks=($symlinks) -suffices=($suffices) - mkdir root # Needed for splash_helper, which gets run before init. @@ -12,14 +8,14 @@ mkdir root/sys mkdir root/proc -for ((n = 0; n < ${#objects[*]}; n++)); do - object=${objects[$n]} - symlink=${symlinks[$n]} - suffix=${suffices[$n]} - if test "$suffix" = none; then suffix=; fi +for ((n = 0; n < ${#objects[@]}; n++)); do + object=${objects[n]} + symlink=${symlinks[n]} + suffix=${suffices[n]} + if test "$suffix" = none; then suffix=; fi - mkdir -p $(dirname root/$symlink) - ln -s $object$suffix root/$symlink + mkdir -p $(dirname root/$symlink) + ln -s $object$suffix root/$symlink done @@ -34,16 +30,16 @@ storePaths="$(cat $closureInfo/store-paths)" # Put the closure in a gzipped cpio archive. mkdir -p $out -for PREP in $prepend; do +for PREP in ${prepend[@]}; do cat $PREP >> $out/initrd done (cd root && find * .[^.*] -exec touch -h -d '@1' '{}' +) (cd root && find * .[^.*] -print0 | sort -z | cpio --quiet -o -H newc -R +0:+0 --reproducible --null | eval -- $compress >> "$out/initrd") if [ -n "$makeUInitrd" ]; then - mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img - # Compatibility symlink - ln -sf "initrd.img" "$out/initrd" + mkimage -A "$uInitrdArch" -O linux -T ramdisk -C "$uInitrdCompression" -d "$out/initrd" $out/initrd.img + # Compatibility symlink + ln -sf "initrd.img" "$out/initrd" else - ln -s "initrd" "$out/initrd$extension" + ln -s "initrd" "$out/initrd$extension" fi diff --git a/pkgs/by-name/ca/capstone/package.nix b/pkgs/by-name/ca/capstone/package.nix index e774c10f4372..2f0bb919d37c 100644 --- a/pkgs/by-name/ca/capstone/package.nix +++ b/pkgs/by-name/ca/capstone/package.nix @@ -8,13 +8,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "capstone"; - version = "5.0.6"; + version = "5.0.7"; src = fetchFromGitHub { owner = "capstone-engine"; repo = "capstone"; rev = finalAttrs.version; - hash = "sha256-ovIvsxVq+/q5UUMzP4WpxzaE0898uayNc1g2Coignnc="; + hash = "sha256-+6QReHZK+iIXspizy6Kvk7cj016HOKgiaKSaP4h7mao="; }; cmakeFlags = [ diff --git a/pkgs/by-name/ni/nixos-init/package.nix b/pkgs/by-name/ni/nixos-init/package.nix index 0e4c26cb2dd3..c84c711c7599 100644 --- a/pkgs/by-name/ni/nixos-init/package.nix +++ b/pkgs/by-name/ni/nixos-init/package.nix @@ -48,6 +48,7 @@ rustPlatform.buildRustPackage (finalAttrs: { "initrd-init" "find-etc" "resolve-in-root" + "env-generator" ]; postInstall = '' diff --git a/pkgs/by-name/ni/nixos-init/src/env_generator.rs b/pkgs/by-name/ni/nixos-init/src/env_generator.rs new file mode 100644 index 000000000000..69995b601e59 --- /dev/null +++ b/pkgs/by-name/ni/nixos-init/src/env_generator.rs @@ -0,0 +1,53 @@ +use std::{ + collections::HashMap, + fs, + io::{self, Write}, +}; + +use anyhow::{Context, Result}; +use serde::Deserialize; + +const CONFIG_PATH: &str = "/etc/systemd/generator-environment.json"; +const KMSG_PATH: &str = "/dev/kmsg"; + +#[derive(Deserialize)] +struct Config(HashMap); + +/// Implementation for the entrypoint of the `env-generator` binary. +/// +/// Reads the JSON config for the systemd generator environment and prints it in KEY=VALUE format +/// to stdout. This makes the configured environment variables available for all systemd +/// generators. +fn env_generator_impl() -> Result<()> { + let content = fs::read(CONFIG_PATH).with_context(|| format!("Failed to read {CONFIG_PATH}"))?; + let config: Config = serde_json::from_slice(&content).context("Failed to parse config")?; + + let mut buffer = Vec::new(); + for (key, value) in config.0 { + writeln!(&mut buffer, "{key}=\"{value}\"").context("Failed to write to buffer")?; + } + + let stdout = io::stdout(); + let mut locked = stdout.lock(); + locked + .write_all(&buffer) + .context("Failed to write to stdout")?; + + Ok(()) +} + +/// Entrypoint for the `env-generator` binary. +/// +/// Generators cannot use normal logging but have to write to /dev/kmsg. +/// +/// The return value is just here so that we can use the `main.rs` entrypoint for this binary. +/// Errors returned from this function will not be logged and thus are meaningless. +pub fn env_generator() -> Result<()> { + if let Err(err) = env_generator_impl() { + // Sometimes we do not have /dev/kmsg, e.g. inside a container + if let Ok(mut kmsg) = fs::OpenOptions::new().write(true).open(KMSG_PATH) { + let _ = write!(kmsg, "<3>env-generator: {err:#}"); + } + } + Ok(()) +} diff --git a/pkgs/by-name/ni/nixos-init/src/lib.rs b/pkgs/by-name/ni/nixos-init/src/lib.rs index 2ee90c6f8228..e9a716724051 100644 --- a/pkgs/by-name/ni/nixos-init/src/lib.rs +++ b/pkgs/by-name/ni/nixos-init/src/lib.rs @@ -1,5 +1,6 @@ mod activate; mod config; +mod env_generator; mod find_etc; mod fs; mod init; @@ -14,6 +15,7 @@ use anyhow::{Context, Result, bail}; pub use crate::{ activate::activate, + env_generator::env_generator, find_etc::find_etc, init::init, initrd_init::initrd_init, diff --git a/pkgs/by-name/ni/nixos-init/src/main.rs b/pkgs/by-name/ni/nixos-init/src/main.rs index a051af590be3..4f74415b8d36 100644 --- a/pkgs/by-name/ni/nixos-init/src/main.rs +++ b/pkgs/by-name/ni/nixos-init/src/main.rs @@ -2,7 +2,7 @@ use std::{env, io::Write, process::ExitCode}; use log::Level; -use nixos_init::{find_etc, initrd_init, resolve_in_root}; +use nixos_init::{env_generator, find_etc, initrd_init, resolve_in_root}; fn main() -> ExitCode { let arg0 = env::args() @@ -15,6 +15,7 @@ fn main() -> ExitCode { "find-etc" => find_etc, "resolve-in-root" => resolve_in_root, "initrd-init" => initrd_init, + "env-generator" => env_generator, _ => { log::error!("Command {arg0} unknown"); return ExitCode::FAILURE; diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/nixos-rebuild.8.scd b/pkgs/by-name/ni/nixos-rebuild-ng/nixos-rebuild.8.scd index 43b8c233e290..b2298ce10639 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/nixos-rebuild.8.scd +++ b/pkgs/by-name/ni/nixos-rebuild-ng/nixos-rebuild.8.scd @@ -308,6 +308,14 @@ It must be one of the following: option, it is possible to build non-flake NixOS configurations even if the current NixOS systems uses flakes. +*--diff* + show the diff between the system closure in /run/current-system + and the newly built system closure. + (avaliable for actions: build, boot, test, switch) + + This is similar to running: + "nix store diff-closures /run/current-system result" after build + In addition, *nixos-rebuild* accepts following options from nix commands that the tool calls: diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py index ad0f45b3971b..814d6c481c2f 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py @@ -197,6 +197,12 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa help="Selects an image variant to build from the " "config.system.build.images attribute of the given configuration", ) + main_parser.add_argument( + "--diff", + action="store_true", + help="prints out the diff between the current system " + "and the newly built one using nix store diff-closures" + ) main_parser.add_argument("action", choices=Action.values(), nargs="?") return main_parser, sub_parsers @@ -259,6 +265,20 @@ def parse_args( if args.no_build_nix: parser_warn("--no-build-nix is deprecated, we do not build nix anymore") + if args.diff and args.action not in ( + # case for calling build_and_activate_system + # except excluding DRY_BUILD and DRY_ACTIVATE, + # in which --diff is uniquely a no-op + Action.SWITCH.value, + Action.BOOT.value, + Action.TEST.value, + Action.BUILD.value, + Action.BUILD_IMAGE.value, + Action.BUILD_VM.value, + Action.BUILD_VM_WITH_BOOTLOADER.value, + ): + parser_warn(f"--diff is a no-op with '{args.action}'") + if args.action == Action.EDIT.value and (args.file or args.attr): parser.error("--file and --attr are not supported with 'edit'") diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/nix.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/nix.py index d2c5ceace95c..2804ea94a7b2 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/nix.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/nix.py @@ -1,3 +1,4 @@ +import sys import json import logging import os @@ -537,6 +538,25 @@ def list_generations(profile: Profile) -> list[GenerationJson]: reverse=True, ) +def diff_closures(current_config: Path, new_config: Path, target_host: Remote | None = None): + print( + f"<<< {current_config}\n" + f">>> {new_config}", + file=sys.stderr + ) + run_wrapper( + [ + "nix", + *FLAKE_FLAGS, + "store", + "diff-closures", + current_config, + new_config, + ], + remote=target_host, + stdout=sys.stderr + ) + def repl(build_attr: BuildAttr, nix_flags: Args | None = None) -> None: run_args = ["nix", "repl", "--file", build_attr.path] diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py index 735be1680013..933c2f8de10e 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py @@ -321,6 +321,13 @@ def build_and_activate_system( grouped_nix_args=grouped_nix_args, ) + current_config = Path("/run/current-system") + if args.diff: + if current_config.exists(): + nix.diff_closures(current_config=current_config.readlink(), new_config=path_to_config, target_host=target_host) + else: + logger.warning(f"missing '{str(current_config)}', skipping configuration diff...") + _activate_system( path_to_config=path_to_config, action=action, diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_nix.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_nix.py index c4b37bf0c32f..69d29422337a 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_nix.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_nix.py @@ -1,3 +1,4 @@ +import sys import textwrap import uuid from pathlib import Path @@ -550,6 +551,29 @@ def test_list_generations(mock_get_generations: Mock, tmp_path: Path) -> None: ] +@patch(get_qualified_name(n.run_wrapper, n), autospec=True) +def test_diff_closures(mock_run: Mock) -> None: + + assert n.diff_closures( + Path("/run/current-system"), + Path("/nix/var/nix/profiles/system"), + None + ) == None + mock_run.assert_called_with( + [ + "nix", + "--extra-experimental-features", + "nix-command flakes", + "store", + "diff-closures", + Path("/run/current-system"), + Path("/nix/var/nix/profiles/system"), + ], + remote=None, + stdout=sys.stderr + ) + + @patch(get_qualified_name(n.run_wrapper, n), autospec=True) def test_repl(mock_run: Mock) -> None: n.repl(m.BuildAttr("", None), {"nix_flag": True}) diff --git a/pkgs/by-name/ru/ruff/package.nix b/pkgs/by-name/ru/ruff/package.nix index d4f1aca0b200..70a260c75721 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.15.0"; + version = "0.15.1"; src = fetchFromGitHub { owner = "astral-sh"; repo = "ruff"; tag = finalAttrs.version; - hash = "sha256-Q3xujVNv5i3mgdsjnvgTiPoKmK9aeSgz+2IoVrNur4k="; + hash = "sha256-Bj4ATRVYrKqigISNiDvgjUw4MLMwfgdID8MqaiVxz0g="; }; cargoBuildFlags = [ "--package=ruff" ]; - cargoHash = "sha256-JMMDOANg+nqrCoxiuIXTcdqm7UZ61pIJwUTJB20TjUM="; + cargoHash = "sha256-IF60aGv56Kh+wDYyN7XzLBywepvAxv2HMqSOz+Su2b4="; nativeBuildInputs = [ installShellFiles ]; diff --git a/pkgs/by-name/st/strace/package.nix b/pkgs/by-name/st/strace/package.nix index 7fc77c29599a..9820ae631ab2 100644 --- a/pkgs/by-name/st/strace/package.nix +++ b/pkgs/by-name/st/strace/package.nix @@ -11,11 +11,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "strace"; - version = "6.18"; + version = "6.19"; src = fetchurl { url = "https://strace.io/files/${finalAttrs.version}/strace-${finalAttrs.version}.tar.xz"; - hash = "sha256-CtXcupc6aed5ZQ7xyzNbEu5gcW/HMmYJiVvTPm0qcyU="; + hash = "sha256-4HbIUe7AlySG7IQhZP3FRUf50Xq9PRRJ3osSD10pkUM="; }; separateDebugInfo = true; diff --git a/pkgs/os-specific/linux/kernel/kernels-org.json b/pkgs/os-specific/linux/kernel/kernels-org.json index 121b8e175905..140c3ecc04d0 100644 --- a/pkgs/os-specific/linux/kernel/kernels-org.json +++ b/pkgs/os-specific/linux/kernel/kernels-org.json @@ -20,23 +20,23 @@ "lts": true }, "6.6": { - "version": "6.6.124", - "hash": "sha256:0kkri7y9g5c7hylwsdc2wq2drhniay171nnccr533qlvisgzpbm7", + "version": "6.6.125", + "hash": "sha256:0g88r1v5q0m1n1ii2f16awc8w9m471m6hqx7r5whad4a8dpkpqwf", "lts": true }, "6.12": { - "version": "6.12.70", - "hash": "sha256:1w1flq4phr3i51c85bz8d9a8cg780vn7dr29y4j4izyfv33wwk4v", + "version": "6.12.72", + "hash": "sha256:0ybijkw2zadhlg49r0wvnvy3s2czj5jnb149cz8ybvzvp90qgxdi", "lts": true }, "6.18": { - "version": "6.18.10", - "hash": "sha256:1plfwknqh5831kjq6f2yxcm4lqvp68a6kvcfnbxa5ba12wb7glyn", + "version": "6.18.11", + "hash": "sha256:1xrsc7s3kh7mipfs0v33n97gfi55ll83x4hxvwi969qh8293ibrq", "lts": false }, "6.19": { - "version": "6.19", - "hash": "sha256:0mqka8ii7bvmx9hvfjdiyva9ib0j7m390gxhh8gki3qb4nl7jc1h", + "version": "6.19.1", + "hash": "sha256:1vlki73j7m2khjl39hq4fy42qql9als18nmnjg00a8yklhqzb0qb", "lts": false } }