staging-nixos merge for 2026-02-16 (#490990)
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -742,6 +742,8 @@ in
|
||||
};
|
||||
|
||||
systemd = {
|
||||
generatorPath = [ cfg.package ];
|
||||
|
||||
sockets.sshd = lib.mkIf cfg.startWhenNeeded {
|
||||
description = "SSH Socket";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
@@ -30,7 +30,6 @@ let
|
||||
);
|
||||
postBootCommands = pkgs.writeText "local-cmds" ''
|
||||
${config.boot.postBootCommands}
|
||||
${config.powerManagement.powerUpCommands}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
})
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -48,6 +48,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
"initrd-init"
|
||||
"find-etc"
|
||||
"resolve-in-root"
|
||||
"env-generator"
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
|
||||
@@ -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<String, String>);
|
||||
|
||||
/// 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(())
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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'")
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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("<nixpkgs/nixos>", None), {"nix_flag": True})
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user