Commit Graph

125 Commits

Author SHA1 Message Date
r-vdp
bb258c2dbe nixos/systemd-boot: update via Varlink instead of parsing bootctl status
systemd v261 lists the new systemd-boot-fallback binary in `bootctl
status`, so our regex picked up the older fallback version and ran
`bootctl update` on an already current ESP, which then exits non-zero.

Switch from parsing the `bootctl --status` output to having bootctl
compare versions itself by calling io.systemd.BootControl.Install over
Varlink. bootctl is spawned as a stdio Varlink server so that we always
use the bootctl from the target closure. An already current binary comes
back as an io.systemd.System error carrying ESTALE, which we treat as
success.
2026-07-01 12:08:51 +02:00
r-vdp
5f267f4dda nixos/boot: allow passing extra initrd archives to the bootloader
This is for instance useful on Asahi where an additional initrd archive
containing firmware blobs and per-device calibration files is placed
on the ESP and updated by the Asahi Linux Installer.
These need to be loaded alongside the NixOS initrd.

Implemented for systemd-boot and Limine. Grub is left out since its
install script does not use bootspec yet.

Co-authored-by: Florian Klink <flokli@flokli.de>
2026-06-26 13:39:08 +03:00
r-vdp
dff88cbd79 nixos/systemd-boot: drop bootspec synthesize fallback
Older generations without boot.json are skipped with a
warning.
2026-06-09 22:03:07 +03:00
r-vdp
919b70b29f nixos/systemd-boot: refuse to wipe ESP when no generations found 2026-06-05 18:01:06 +03:00
r-vdp
9eb570f453 nixos/systemd-boot-builder: drop unused BootFile.{current,system_identifier}
Both fields are now write-only after the previous two commits, so
remove them. BootFile is back to being just a (path, writer) pair.
2026-06-02 12:20:55 +03:00
r-vdp
c38ca6ab7d nixos/systemd-boot-builder: handle initrd-secrets failure in the writer
The CalledProcessError can only come from the append-initrd-secrets
script, so catching it in the generic write loop and then asserting
on the writer type to reach back into its `source` is the wrong
layer. Move the catch, the pristine-initrd fallback and the warning
into InitrdWithSecretsWriter itself, and pass `critical` through the
writer protocol so it can decide between aborting and falling back.

The writer carries the generation number so the warning can still
name the affected generation. write_boot_files no longer knows
anything about secrets and the isinstance assertion is gone.

Suggested-by: Will Fancher <elvishjerricco@gmail.com>
2026-06-02 12:20:55 +03:00
r-vdp
9d46e91c49 nixos/systemd-boot-builder: track critical paths separately from BootFile
Whether a write failure must be fatal is a property of the destination
path (is it needed by the configuration we are switching to?), not of
the particular BootFile instance that happened to survive
deduplication. Compute the set of critical paths up front and look it
up in write_boot_files, so the dedup loop no longer needs to pick the
"right" instance and becomes a plain order-preserving seen-set walk.

This leaves BootFile.current unused.

Suggested-by: Will Fancher <elvishjerricco@gmail.com>
2026-06-02 12:20:55 +03:00
r-vdp
dff3315fac nixos/systemd-boot-builder: use with for the secrets temp file
This guarantees the descriptor is closed even when copyfileobj raises,
matching the other writer implementations. The append-initrd-secrets
script reopens the file by path, so flush() is enough before invoking
it and the explicit close() is no longer needed.
2026-06-02 12:20:55 +03:00
r-vdp
30552ab00b nixos/systemd-boot-builder: clarify stale initrd secrets warning
Tell the user what actually happens (the old secrets stay in place) and
how to get rid of the warning, instead of just saying it is "normal".

Suggested-by: Will Fancher <elvishjerricco@gmail.com>
2026-06-02 12:20:54 +03:00
r-vdp
b4e756627d nixos/systemd-boot-builder: write each ESP path only once
Shared kernels and initrds appear once per generation in boot_files, so
InitrdWithSecretsWriter rebuilt the same file repeatedly. Prefer the
current configuration's entry so its failures stay fatal.
2026-06-02 12:20:54 +03:00
r-vdp
76673e2736 nixos/systemd-boot-builder: fall back to pristine initrd when secrets fail
Otherwise the .conf for that generation references a missing initrd and
the boot entry fails to load.
2026-06-02 12:20:54 +03:00
r-vdp
3ff32972f8 nixos/systemd-boot-builder: verify content of existing entry files
A file named nixos-<hash>.conf whose content no longer hashes to <hash>
is corrupt. Skip it so GC removes it and a fresh entry is written.
2026-06-02 12:20:54 +03:00
r-vdp
820d20f8b9 nixos/systemd-boot-builder: cache boot_path()
It calls Path.resolve() and is invoked several times per generation for
the same store paths.
2026-06-02 12:20:53 +03:00
r-vdp
85d59c4f3d nixos/systemd-boot-builder: use a set for GC root lookup
has_gc_root() iterated the entire BootFileList for every file on the
ESP, giving O(files * roots) comparisons. Build the set of kept paths
once and use O(1) membership tests instead.
2026-06-02 12:20:53 +03:00
r-vdp
146acf965f nixos/systemd-boot-builder: warn instead of aborting when an old gen's secrets fail
After removing or renaming a file in boot.initrd.secrets, older
generations' append scripts start failing. Aborting on that blocks
deploying the new configuration, so only treat a failure as fatal when
it belongs to the configuration being switched to.
2026-06-02 12:20:53 +03:00
r-vdp
6eba7d60f3 nixos/systemd-boot-builder: rebuild secret-bearing initrds atomically each run
Appending to the existing file made it grow on every rebuild and a
failed script could leave it half-written. Always rebuild from the
pristine initrd into a temp file and rename into place.
2026-06-02 12:20:53 +03:00
r-vdp
6ef460ec9d nixos/systemd-boot-builder: write loader.conf after the entries it points at
A crash between the two would leave `default <id>` referring to a
.conf that does not exist yet.
2026-06-02 12:20:53 +03:00
Will Fancher
44a974d0eb nixos/systemd-boot: Rerun secrets every switch 2026-06-02 12:20:52 +03:00
Will Fancher
1d081050c3 nixos/systemd-boot: Separate finding the placement of files from writing files 2026-06-02 12:20:52 +03:00
r-vdp
b4c278c06b nixos/systemd-boot-builder: store boot loader configs using content hashing
Co-Authored-By: AkechiShiro <14914796+AkechiShiro@users.noreply.github.com>
2026-06-02 12:20:51 +03:00
r-vdp
69ce6b2391 nixos/systemd-boot-builder: re-instate boot counting
Co-Authored-By: Julien Malka <julien@malka.sh>
Co-Authored-By: AkechiShiro <14914796+AkechiShiro@users.noreply.github.com>
2026-06-02 12:20:12 +03:00
r-vdp
ac2410be5d nixos/systemd-boot-builder: format 2026-06-02 12:20:12 +03:00
Vladimír Čunát
d6acf1b543 Revert "nixos/initrd: refactor secrets option into secretPaths and extraSecretsHook" 2026-03-21 15:58:52 +01:00
cyclopentane
72e4df576e nixos/initrd: add secretPaths and extraSecretsHook 2026-02-24 21:38:40 +01:00
qbisi
e9391c4e7a nixos/systemd-boot-builder: add leading slash to devicetree path 2025-10-23 05:27:35 +08:00
sternenseemann
85c7452e80 nixos/systemd-boot: fsync() copied files
Since mkstemp() gives us a file descriptor, we may as well call fsync().
2025-09-24 01:35:51 +02:00
sternenseemann
94c190a55c nixos/systemd-boot: atomically update copied destination files
We absolutely do not want to leave an incomplete file behind in /boot
since an incomplete initrd would render the machine unbootable. Errors
while writing are relatively common, mostly due to full /boot
partitions.

systemd-boot-builder does never attempt to re-write already existing
files which means that such situations are not fixable by re-running
nixos-rebuild etc. Instead the user needs to know about internals of the
systemd-boot and manually delete the correct file to recover from a
partially written kernel or (more commonly) initrd in /boot.

Note that this used to be a non issue since systemd-boot-builder used to
always delete all kernels and initrds before copying kernels and
initrds, so dest.exist() would always return False. This was fixed in
f2ca990558, revealing the underlying bad
assumption (that copyfile() always succeeds or fails without writing
anything).

The solution is to write to a temporary file first and move it to the
destination path only after this has succeeded. This way, if an error
occurs during copying, only a file distinct from dest is left behind
which would be cleaned up by subsequent runs of remove_old_entries().

Resolves #444066.
2025-09-24 01:00:44 +02:00
r-vdp
c4753ff331 nixos/systemd-boot-builder: make sure to print informational messages to stderr
Otherwise this gets printed to stdout when running things like
nixos-rebuild, while people rely on the toplevel store path being the only
output of such commands.
2025-09-15 10:19:15 +02:00
Jeremy Fleischman
683d9e3b54 nixos/systemd-boot-builder: remove old devicetree files
I just stumbled across this during code inspection. I haven't tested
this at all.
2025-09-03 13:35:57 +01:00
Linus Heckemann
f2ca990558 nixos/systemd-boot-builder: use pathlib.Path where possible
`switch-to-configuration boot` was taking suspiciously long on a machine
of mine where the boot partition is on a slow SD card. Some tracing led
me to discover that it was in fact deleting all the kernels and initrds
every time, only to rewrite them.

This turned out to be because of the naive (non-path-normalising) string
concatenation used to construct paths in `known_paths`, so all the files
were recognised as obsolete and deleted:


known_paths=['/EFI/nixos/5jz3m9df1cbxn4hzjjs3aaz8lb9vvimc-linux-6.15.7-Image.efi', '/EFI/nixos/xri8qzfvzclf89x7nfwgq248miw7jbp0-initrd-linux-6.15.7-initrd.efi', '/EFI/nixos/b18llskzrcdgw2nbib58qqcaabiik6yc-linux-6.16-Image.efi', '/EFI/nixos/mdj53j746bii1vw227dfhkyd8ajwab2w-initrd-linux-6.16-initrd.efi', '/EFI/nixos/b18llskzrcdgw2nbib58qqcaabiik6yc-linux-6.16-Image.efi', '/EFI/nixos/mdj53j746bii1vw227dfhkyd8ajwab2w-initrd-linux-6.16-initrd.efi', '/EFI/nixos/b18llskzrcdgw2nbib58qqcaabiik6yc-linux-6.16-Image.efi', '/EFI/nixos/mdj53j746bii1vw227dfhkyd8ajwab2w-initrd-linux-6.16-initrd.efi', '/EFI/nixos/5jz3m9df1cbxn4hzjjs3aaz8lb9vvimc-linux-6.15.7-Image.efi', '/EFI/nixos/1ihk03c1i5518hlgm5mnhrig2hy3hq24-initrd-linux-6.15.7-initrd.efi', '/EFI/nixos/5jz3m9df1cbxn4hzjjs3aaz8lb9vvimc-linux-6.15.7-Image.efi', '/EFI/nixos/1ihk03c1i5518hlgm5mnhrig2hy3hq24-initrd-linux-6.15.7-initrd.efi', '/EFI/nixos/5jz3m9df1cbxn4hzjjs3aaz8lb9vvimc-linux-6.15.7-Image.efi', '/EFI/nixos/1ihk03c1i5518hlgm5mnhrig2hy3hq24-initrd-linux-6.15.7-initrd.efi']
path='/boot//EFI/nixos/5jz3m9df1cbxn4hzjjs3aaz8lb9vvimc-linux-6.15.7-Image.efi'
path='/boot//EFI/nixos/xri8qzfvzclf89x7nfwgq248miw7jbp0-initrd-linux-6.15.7-initrd.efi'
path='/boot//EFI/nixos/b18llskzrcdgw2nbib58qqcaabiik6yc-linux-6.16-Image.efi'
path='/boot//EFI/nixos/mdj53j746bii1vw227dfhkyd8ajwab2w-initrd-linux-6.16-initrd.efi'
path='/boot//EFI/nixos/1ihk03c1i5518hlgm5mnhrig2hy3hq24-initrd-linux-6.15.7-initrd.efi'


This can be avoided by using pathlib.Path, which normalises paths and
generally provides a more consistent and convenient API. I therefore
went ahead and replaced all use of `str` for path handling with `Path`
in the builder. This may fix some other, similar bugs, as well, but I
haven't checked in detail.
2025-08-18 20:11:57 +02:00
jack
dedf852ccd nixos/systemd-boot: refactor json.load() logic for better error message 2025-07-27 13:05:03 +02:00
Jörg Thalheim
b6c1663986 systemd-boot: improve error message if no previous systemd boot is found. 2025-05-20 15:39:07 +02:00
Jared Baur
3de7bccd4a nixos/systemd-boot: strip newline from machine-id
To make each line in the entry file consistent, strip the newline from
the machine-id content.
2025-02-13 18:52:14 -08:00
Arian van Putten
a4008da2d4 nixos/systemd-boot: Don't write to /etc/machine-id
This reverts commit 4daccf208f

The reverted commit claims that bootctl fails if machine-id is not set.
I can not reproduce this. I think this has since been fixed now that
bootctl has support for arbtirary entry-tokens and not just machine-id.

In the case of NixOS the entry-token is the string "nixos"
2024-10-09 15:34:34 +02:00
Jared Baur
05aefd6f05 nixos/systemd-boot: remove semicolon 2024-08-24 12:50:26 -07:00
Jared Baur
6327b07b25 nixos/systemd-boot: use unique path for devicetree blob
Use the store directory for the devicetree package containing the
desired DTB when installing to the ESP. This allows for more than one
NixOS generation containing differing DTBs to coexist on the same ESP
(similar to how we can have multiple kernels & initrds). This change
removes the assumption that the filepath passed to `copy_from_file` is a
file that lives at the toplevel of a nix output path (which prior to the
systemd-boot DTB support was the case for the kernel and initrd
derivations).
2024-08-24 12:50:24 -07:00
Will Fancher
0637303ca8 Revert "Merge pull request #330017 from Mic92/boot-counting"
This reverts commit 3d3c0f4d34, reversing
changes made to 47f7e25a77.
2024-08-13 23:11:18 -04:00
Will Fancher
b78bd2f912 Revert "Merge pull request #333952 from r-vdp/specialisation-name-regex"
This reverts commit fc35704bc8, reversing
changes made to c67d90d517.
2024-08-13 21:33:15 -04:00
r-vdp
d38257b024 systemd-boot-builder: allow underscores in the specialisation name 2024-08-11 23:33:18 +02:00
Franz Pletz
481d7272d1 Merge pull request #201202 from m-bdf/sdboot-infinite-timeout 2024-08-06 16:25:25 +02:00
Franz Pletz
97ebf11501 Merge pull request #319422 from jmbaur/systemd-boot-devicetree 2024-08-06 13:39:29 +02:00
Thibault Polge
a68b81c429 nixos/systemd-boot: Add reboot-for-bitlocker support
Windows with BitLocker and TPM enabled doesn't support boot chaining.
This option activates a special experimental mode in systemd-boot that
tries to detect such systems and, if detected and selected by the user
at the boot menu, set the BootNext EFI variable to it before resetting.
2024-08-05 13:17:25 +03:00
Maëlys Bras de fer
7ae6219163 nixos/systemd-boot: fix infinite timeout 2024-08-05 08:48:54 +00:00
Jared Baur
fca8ee915d nixos/systemd-boot: add support for devicetree entry
The [Boot Loader Specification](https://uapi-group.org/specifications/specs/boot_loader_specification/)
allows for using a key called "devicetree" for specifying which
devicetree the bootloader should use during boot. With regards to
systemd-boot, this key is used to specify which file should be picked up
from the ESP to install to the EFI DTB Configuration Table. Linux then uses
this Configuration Table to setup the machine. This change is similar to
the one done in https://github.com/NixOS/nixpkgs/pull/295096, where that
change was for adding DTB support to systemd-stub, and this is for
systemd-boot.
2024-08-01 11:15:15 -07:00
Julien Malka
64edc7f00f nixos/systemd-boot: init boot counting
Update nixos/modules/system/boot/loader/systemd-boot/boot-counting.md

Co-authored-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
2024-07-26 20:04:37 +02:00
turtton
be20b91547 nixos/systemd-boot-builder: fix installed_match regex
Fix regular expression used to get bootloader versions from bootctl status.
This avoids problems that occur in minor environments like mine.

References:  #296563
2024-07-13 09:20:13 +02:00
Jörg Thalheim
ebfee308fc systemd-boot-builder: use type literals 2024-06-29 19:09:38 +02:00
Jörg Thalheim
6d0be2bec1 systemd-boot-builder: allow exceptions from python naming scheme 2024-06-29 19:09:28 +02:00
Jörg Thalheim
1ae4daa608 systemd-boot-builder: use safe run wrapper
we have a zoo of ways to call subprocesses.
Let's just replace this with one function that has reasonable defaults.
i.e. I catched instances where commands where run in a shell.
2024-06-29 19:09:06 +02:00
Jörg Thalheim
5cbf195292 systemd-boot-builder: use regex strings 2024-06-29 19:09:04 +02:00