Skip to content

nixos/iso-image: Support systemd initrd#291750

Merged
emilazy merged 1 commit intoNixOS:masterfrom
ElvishJerricco:systemd-initrd-iso
Aug 10, 2025
Merged

nixos/iso-image: Support systemd initrd#291750
emilazy merged 1 commit intoNixOS:masterfrom
ElvishJerricco:systemd-initrd-iso

Conversation

@ElvishJerricco
Copy link
Copy Markdown
Contributor

@ElvishJerricco ElvishJerricco commented Feb 27, 2024

Description of changes

This modifies the ISO configuration to be able to use systemd initrd. It should still work without systemd initrd as well.

Something to note is the removal of the awkward use of the root= kernel param. In scripted stage 1, the value of this parameter ends up being symlinked to /dev/root, and previously the ISO used this to mount /iso. For one thing, this is an incorrect usage of root=. But, I do not know how this will affect other tools flashing the image to a bootable drive. I know we only really support directly writing the image to disk, but I don't want to degrade the experience from people's historical expectations. Also, the findiso= mechanism will not be supported with systemd initrd. This is a niche feature to begin with, and we intend to stop using grub for the ISO in the near future anyway.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Feb 27, 2024
@ElvishJerricco ElvishJerricco requested review from a team, K900 and RaitoBezarius February 27, 2024 06:48
Copy link
Copy Markdown
Contributor

@K900 K900 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff LGTM, will test on weird setups later

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

Oh, forgot to mention the weird thing with findiso=. Added that to the todo list

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Feb 27, 2024
@K900
Copy link
Copy Markdown
Contributor

K900 commented Feb 27, 2024

Things I found so far:

  • can't find rootfs with ventoy
  • when failing to find rootfs, can't enter recovery shell because root account is locked

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

ElvishJerricco commented Feb 27, 2024

@K900 Fixed the recovery shell thing; though not in a way compliant with the boot.shell_on_fail thing, which is why that's in the todo list

@misuzu
Copy link
Copy Markdown
Contributor

misuzu commented Feb 27, 2024

Related: #217173

@nikstur
Copy link
Copy Markdown
Contributor

nikstur commented Mar 10, 2024

I think the overlay thing doesn't create the same depends values. Though, see #233707 or #273642

Afaik the depends are just a no-op right now even in the scripted initrd.

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

ElvishJerricco commented Mar 16, 2024

@nikstur depends currently exclusively works for file systems mounted by scripted stage 1. File systems are toposorted by path and depends and then traversed by stage-1-init.sh in that order. But depends currently does nothing for systemd stage 1 or for stage 2, which is what the linked prs are about.

@RaitoBezarius
Copy link
Copy Markdown
Member

RaitoBezarius commented Mar 18, 2024

@K900 Fixed the recovery shell thing; though not in a way compliant with the boot.shell_on_fail thing, which is why that's in the todo list

What does that mean? From my understanding, the boot.shell_on_fail does not exist under systemd initrd, it's just systemd emergency access and that requires manual upgrades, I'd say?

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

@RaitoBezarius well that's what I mean. Ideally, systemd stage 1 would still support (most of) the same cmdline parameters (see: #170125). The boot.debug1 one for instance equates to (sort of) rd.systemd.unit=emergency.target ((sort of)), so it would be nice if we could somehow make that an alias. But we don't really have a way to say "if stage 1 fails, drop straight into a shell", which is the currently expected behavior of the ISO.

@nikstur
Copy link
Copy Markdown
Contributor

nikstur commented Mar 28, 2024

we don't really have a way to say "if stage 1 fails, drop straight into a shell", which is the currently expected behavior of the ISO.

IMO systemd's emergency shell fulfills this use case adequately, even if it's not the same exact behaviour as before.

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

@nikstur Yea, I've come to largely the same conclusion that we don't need one to one kernel param compatibility. I'm also adding systemd's debug shell service in a separate PR (#299717), so that provides even more functionality similar to what we have in scripted stage 1.

We'll just have to document the differences in the cmdline options.

@nixos-discourse
Copy link
Copy Markdown

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/custom-nixos-installer-plug-install-play-how-to-achieve-this/61710/13

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Mar 17, 2025
@nixpkgs-ci nixpkgs-ci bot added 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 12.approvals: 1 This PR was reviewed and approved by one person. and removed 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md labels Jun 25, 2025
@ElvishJerricco ElvishJerricco changed the title nixos/iso-image: Use systemd initrd nixos/iso-image: Support systemd initrd Aug 1, 2025
@nixpkgs-ci nixpkgs-ci bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Aug 1, 2025
@ElvishJerricco ElvishJerricco marked this pull request as ready for review August 1, 2025 04:54
@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

With #429845 done, I think we're ready to get this one done now. We plan to switch systemd initrd on by default in the near future, so this PR simply prepares for that by adding support for systemd initrd, rather than switching the ISO to using it directly.

Also, I've decided not to try and support the findiso= feature, as we're going to lose that feature when we switch off grub anyway.

@flokli
Copy link
Copy Markdown
Member

flokli commented Aug 1, 2025

can't find rootfs with ventoy

@K900 Is this still broken? Still being able to load a NixOS ISO to a ventoy stick seems important, as that's how NixOS frequently gets installed.

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

ElvishJerricco commented Aug 1, 2025

@flokli I've researched that pretty extensively and concluded that that was already a problem for the ISO without systemd initrd, it was just less likely. The "hook" it uses just searches the initrd for a directory it thinks it should inject a udev rule file into, but whether or not it guesses the right one correctly basically depends on the order of the hash-addressed paths in the store, and the larger number of store paths in systemd initrd just makes it more likely for that to fail.

The only way to fix this is to adopt ventoy's custom protocol that lets the ISO implement ventoy support itself instead of relying on this broken "hook". I have a branch where I've implemented this but it requires a bunch of new code and I'm not happy about that

EDIT: To be clear, since researching this, I have encountered countless users who have the same problem with ventoy not working for this reason with the current ISO builds.

@emilazy
Copy link
Copy Markdown
Member

emilazy commented Aug 1, 2025

Yeah I don’t think we should block on something that’s already broken and inherently fragile. We don’t recommend Ventoy anywhere and one of the first Google results for “Ventoy NixOS” is a Reddit thread full of people talking about how Ventoy doesn’t work with NixOS ISOs.

Copy link
Copy Markdown
Member

@emilazy emilazy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM; haven’t tested this myself but I expect you have done more thorough testing than I would. (This PR doesn’t flip the default, anyway.)

I personally don’t think it makes sense to support both systemd stage 1 and scripted stage 1 in something we ship as a self‐contained appliance, but since we’re adding support before changing the default that’s somewhat unavoidable for now anyway.

Comment on lines +905 to +938
# Most of util-linux is not included by default.
initrdBin = [ config.boot.initrd.systemd.package.util-linux ];
services.copytoram = {
description = "Copy ISO contents to RAM";
requiredBy = [ "initrd.target" ];
before = [
"${utils.escapeSystemdPath "/sysroot/nix/.ro-store"}.mount"
"initrd-switch-root.target"
];
unitConfig = {
RequiresMountsFor = "/sysroot/iso";
ConditionKernelCommandLine = "copytoram";
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
path = [
pkgs.coreutils
config.boot.initrd.systemd.package.util-linux
];
script = ''
device=$(findmnt -n -o SOURCE --target /sysroot/iso)
fsSize=$(blockdev --getsize64 "$device" || stat -Lc '%s' "$device")
mkdir -p /tmp-iso
mount --bind --make-private /sysroot/iso /tmp-iso
umount /sysroot/iso
mount -t tmpfs -o size="$fsSize" tmpfs /sysroot/iso
cp -r /tmp-iso/* /sysroot/iso/
umount /tmp-iso
rm -r /tmp-iso
'';
};
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This is kind of gross, but I realize that doing anything about it is out of scope for this PR.)

@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 2 This PR was reviewed and approved by two persons. and removed 12.approvals: 1 This PR was reviewed and approved by one person. labels Aug 1, 2025
@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 3+ This PR was reviewed and approved by three or more persons. and removed 12.approvals: 2 This PR was reviewed and approved by two persons. labels Aug 7, 2025
@bjornfor
Copy link
Copy Markdown
Contributor

bjornfor commented Aug 7, 2025

EDIT: To be clear, since researching this, I have encountered countless users who have the same problem with ventoy not working for this reason with the current ISO builds.

When did NixOS ISOs stop working with Ventoy? I tested NixOS 25.05 in Ventoy this week, and that worked. I will be sad if it stops working.

@ElvishJerricco
Copy link
Copy Markdown
Contributor Author

When did NixOS ISOs stop working with Ventoy? I tested NixOS 25.05 in Ventoy this week, and that worked. I will be sad if it stops working.

@bjornfor They never worked reliably with Ventoy. The hook it uses to inject its software in our initrd often fails, seemingly depending on the specific build of the ISO you use rather than any runtime details. IIRC it basically ends up putting its udev rules (which call its small OS's-worth of binaries to set things up in a cursed way) into the wrong directory, probably because the hashes in nix store path names effectively randomizes their order on every build.

systemd stage 1 just makes this problem more likely to occur, probably because we don't do the same extraUtils thing that scripted stage 1 did, so we end up with a lot more top level paths in the initrd's nix store.

I can fix this by using Ventoy's custom boot protocol. Tbh it's a relatively sane protocol, except that by default it wants us to scan /dev/mem on legacy BIOS platforms because Windows 7 ISOs break when it passes info in as an ACPI table; so that part's pretty cursed. Overall though it's much more sane than the hook it uses for ISOs not employing the protocol. But AFAICT no other distro implements this protocol in their ISOs, and it's a lot of added code to nixpkgs, so I'm not exactly eager to actually add it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 12.approvals: 3+ This PR was reviewed and approved by three or more persons.

Development

Successfully merging this pull request may close these issues.