Change:
With , my screen's brightness is reset to 100% on reboot. starts up but doesn't. Not sure how to debug this. I'm on a thinkpad T14s. Clarification: the issue is not that the brightness level is 100% in the initrd, but that it stays 100% after booting. In other words never starts.
You probably need in for this to work. That may inflate your initramfs by quite a bit. I'm also not sure if/how systemd passes this state into the initramfs though, so this may fundamentally not work?
That didn't do it, nor with (in fact I ).
Interestingly I'm getting these errors in the log: which points me to with a similar issue. This looks like a hardware-specific problem so I'll close for now.
This does not look like a hardware-specific or even driver issue. On my machine is not even active, but manually starting it works. In short there is a udev rule shipped by systemd in saying And it should bring these units up.
Setting do brings the unit up, but now it fails with , like a missing store path in the initrd.
Also, adding somehow delays the vconsole setup until after the LUKS decryption, so I have to type in my passphrase in QWERTY.
I'm curious about the behavior change of systemd/udev when systemd stage 1 is in use, I thought that ought to be activated after switching root, not even relevant to the initrd, however the reality is quite the opposite. Moreover running clearly shows the rules being evaluated correctly, but systemd is just not taking any action. After removing from my configuration, now backlight is correctly restored. The theory is now that devices initialized in the initrd is not reconsidered for udev rules evaluation after switching roots.
I still don't know how it's supposed to work at all --- restoring backlight levels implies knowing what they previously were, and that can only be determined from the root filesystem. I suppose it could also be stored in an EFI variable, but I don't think that it is. So the reason it doesn't work is that it doesn't know what level it should restore to. EDIT: and NickCao's issue is because if i915 is present it tries to restore the level (but doesn't know what to restore to), while if it's not loaded until the main system is booted it does.
is obviously , thus it should be mounted in initrd, in that way it is possible to restore backlight in the initrd, but considering is actually mounted under , this won't work in practice. So I believe the correct way is to restore backlight after switching root. Meanwhile and does not, and do not need to exist in the initrd, there's no attempt to restore the backlight back in the initrd, the issue is systemd (or udev) does not reevaluate the rules after switching root to determine that it is now the time to do so. Despite that there's little information out there about , the practice systemd do to pass information from initrd to itself after switching root, I think it might contains information about special units such as , which tricks udevd to believe that the rules on these devices has already been evaluated in the initrd, thus refusing to reevaluate.
but not really useful, especially considering that one of the main uses for seeing what the initramfs is doing is seeing an encryption passphrase prompt (and if the filesystem hasn't been decrypted yet, it's not possible...)
To be clear, I don't think the goal should be to restore backlight levels in the initrd. At least that's not what this issue is about. The goal is the restore backlight levels at all, which currently doesn't happen for me when using the systemd initrd.
My guess was a bit off, but indeed it was udev db leaked from initrd to the udevd after switching root. Now that the referenced issue is fixed and released upstream, we can safely enable , and the udev rules will be properly reevaluated after switching root.
Oooooh. Yeah I was completely missing the point, sorry!
This keeps getting weirder: while fixes the issue for me, I can also fix it another way: by removing from (for example, by not importing the module from nixos-hardware). I'm pretty sure I had tried that in June and it did not fix the issue at the time, but now it does. Also, not including in the initrd modules fixes another issue: about a second after the passphrase prompt appears, the screen seems to "reset" (with no change to the brightness level), and the framebuffer gets scrolled up a few lines while the prompt stays in the same place: <details<summaryScreenshot</summary </detailsHere's the  where you can see that "about a second after the passphrase prompt appears" seems to line up with the moment is detected/initialised/started (?). This is all regardless of whether is included. Having in behaves the same as when it's in .

Discussion:
SUBSYSTEM=="input", KERNEL=="mice", TAG+="systemd" ''; <ins> nixosInitrdRules = '' # Mark dm devices as db_persist so that they are kept active after switching root SUBSYSTEM=="block", KERNEL=="dm-[0-9]*", ACTION=="add|change", OPTIONS+="db_persist" ''; </ins> # Perform substitutions in all udev rules files. udevRulesFor = { name, udevPackages, udevPath, udev, systemd, binPackages, initrdBin ? null }: pkgs.runCommand name { preferLocalBuild = true;

EOF ''; <ins> boot.initrd.services.udev.rules = nixosInitrdRules; </ins> boot.initrd.systemd.additionalUpstreamUnits = [ <del> # TODO: "initrd-udevadm-cleanup-db.service" is commented out because of https://github.com/systemd/systemd/issues/12953 </del> <ins> "initrd-udevadm-cleanup-db.service" </ins> "systemd-udevd-control.socket" "systemd-udevd-kernel.socket" "systemd-udevd.service"

cryptroot2.device = "/dev/vdd"; }; virtualisation.bootDevice = "/dev/mapper/cryptroot"; <ins> # test mounting device unlocked in initrd after switching root virtualisation.fileSystems."/cryptroot2".device = "/dev/mapper/cryptroot2"; </ins> }; };

machine.wait_for_unit("multi-user.target") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdd -") <ins> machine.succeed("echo -n supersecret | cryptsetup luksOpen   -q               /dev/vdd cryptroot2") machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2") </ins> # Boot from the encrypted disk machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf")

machine.wait_for_unit("multi-user.target") assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount") <ins> assert "/dev/mapper/cryptroot2 on /cryptroot2 type ext4" in machine.succeed("mount") </ins> ''; })