UKI/systemd-boot tracker
systemd-boot has a lot of uptake and is very simple for the UEFI path. We need to support it.
One thing this deeply intersects with is https://github.com/ostreedev/ostree/issues/2753 and https://github.com/ostreedev/ostree/issues/1951 as well as https://github.com/containers/bootc/issues/20
I think with the new https://github.com/containers/composefs/issues/332 we could try doing a "big bang" where we:
- Teach bootloader.rs how to detect and install systemd-boot (trivial)
- Have a mode where we basically drop all the ostree stuff out of the container image...we make a merged composefs client side from the container image content and for good measure just do all the selinux labeling client side to start (ref https://github.com/ostreedev/ostree-rs-ext/issues/510 - though we could also start honoring
security.selinuxin the tar stream) - Deploying an image also copies the UKI out into the ESP (and we use the UKIs as a garbage collection root for the objects)
- For
/etcit is tempting to try switching to what flatcar does by default where we change to using an overlayfs for/etcwith the lowerdir, but we could also automatically do the/usr/etchandling in our image (reusing the ostree code...either way); a challenge in this is we document configuring things inostree-prepare-root.conftoday but we could start parsing those options in bootc instead. - We could hence then potentially start by dropping
ostree-prepare-root.servicefrom the initramfs and have a spike on what it'd look like to move the mount logic in the initramfs maybe in this project.
One thing that came up is it could be really helpful for us to support the "pure UKI" path first with no bootloader. That's likely a good way to try severing some of the ostree dependency in that path - we'd just need to handle UKI copying and garbage collection on the bootc side alone. In this initial UKI flow we wouldn't try to handle composefs binding, basically just support adding e.g. Fedora's kernel-uki-virt into a bootc image and make that work.
More background on this: It looks like today kernel-uki-virt defers to kernel-install as executed by %postun and %post...we could investigate doing the same instead of directly copying to the esp.
This also touches on e.g. https://github.com/coreos/rpm-ostree/pull/5135 a bit in that I think we may want to define an explicit kernel layout for this?
cc @allisonkarlitskaya
A note for when you do start integrating with systemd-boot is that if we want the distro details to appear in the systemd-boot menu (and optionally the ostree slot number and the order of the menu to be correct) someone needs to embed a os-release file into the .osrel section of the binary. In particular someone needs to set or add a suffix to PRETTY_NAME=. That someone could be bootc/ostree or could be the image vendor during build time.
You also need to determine how discovery of the correct ostree deployment to boot during initramfs would be done, which is covered in some of the issues linked in this issue's description.
Such embedding, if done on the target machines, will break any existing Secure Boot signatures added by the image vendor. My current cobbled together solution does handle .osrel, .cmdline and .pcrsig, but I measure and re-sign the binary with machine-specific keys at ostree finalize time. I suspect that is something bootc or ostree won't want to handle directly. One scalable option would be to encourage image vendors to use Multi-Profile UKIs and add a profile which triggers booting an ostree fallback deployment.
This is less of a problem if you're doing your own invocations of efibootmgr or similar and leveraging the firmware menu for rollback because the entry titles, command line, default entry, and entry ordering are directly in your control. Setting the command line in the efi boot entry would preclude using PCR 11 to unlock a TPM secret as the kernel command line is not fixed and signed.
See https://uapi-group.org/specifications/specs/boot_loader_specification/#type-2-efi-unified-kernel-images and https://uapi-group.org/specifications/specs/unified_kernel_image/#unified-kernel-image-uki for more details about .osrel and the .cmdline sections.
EDIT: Updated the first paragraph because a lot of this can be done by the image builder.
One thing https://gitlab.com/fedora/bootc/base-images/-/blob/main/bootc-base-imagectl?ref_type=heads now exists and could gain a new verb like bootc-base-imagectl composefs-uki-sign that transforms an existing container image to mutate the UKI and add the composefs signing metadata.
But this also relates to e.g. buildah mkcw which now exists to transform containers to disk images.
I have systemd-boot working in my bootc ucore inspired image. I have not tried UKI yet.
sd-boot wants the vmlinuz and intrd on the efi partition, so I re-partitioned the disk and remade the efi partition with the space from boot. I tried mounting this to /boot, but rpm-ostree wants a symlinked /boot/loader, so I created a /boot/loader.n to make it happy. The only gotcha in this case is that you have to copy and modify the loader entries to match the efi partition.
Per discussion I would be happy to take an even experimental patch to bootc like:
- If bootupd is missing from the image being installed and systemd-boot is present (and the target system is EFI): Use systemd-boot
- Add bootloader=systemd-boot to install config toml
- Add
--bootloader=systemd-bootwhich forcibly overrides even if bootupd is installed
That said there's a wholly other path which is basically:
- Make grub support conditional in bootupd, and have the same logic there where bootupd becomes a super thin wrapper for systemd-boot; it's really the grub stuff that's the cross-distribution mess
cc @p5 re ⬆️