154 lines
7 KiB
Markdown
Executable file
154 lines
7 KiB
Markdown
Executable file
# bootupd: Distribution-independent updates for bootloaders
|
|
|
|
Today many Linux systems handle updates for bootloader data
|
|
in an inconsistent and ad-hoc way. For example, on
|
|
Fedora and Debian, a package manager update will update UEFI
|
|
binaries in `/boot/efi`, but not the BIOS MBR data.
|
|
|
|
Transactional/"image" update systems like [OSTree](https://github.com/ostreedev/ostree/)
|
|
and dual-partition systems like the Container Linux update system
|
|
are more consistent: they normally cover kernel/userspace but not anything
|
|
related to bootloaders.
|
|
|
|
The reason for this is straightforward: performing bootloader
|
|
updates in an "A/B" fashion requires completely separate nontrivial
|
|
logic from managing the kernel and root filesystem. Today OSTree e.g.
|
|
makes the choice that it does not update `/boot/efi` (and also doesn't
|
|
update the BIOS MBR).
|
|
|
|
The goal of this project is to be a cross-distribution,
|
|
OS update system agnostic tool to manage updates for things like:
|
|
|
|
- `/boot/efi`
|
|
- x86 BIOS MBR
|
|
- Other architecture bootloaders
|
|
|
|
This project originated in [this Fedora CoreOS github issue](https://github.com/coreos/fedora-coreos-tracker/issues/510).
|
|
|
|
The scope is otherwise limited; for example, bootupd will not
|
|
manage anything related to the kernel such as kernel arguments;
|
|
that's for tools like `grubby` and `ostree`.
|
|
|
|
## Status
|
|
|
|
bootupd supports updating GRUB and shim for UEFI firmware on x86_64, aarch64,
|
|
and riscv64, and GRUB for BIOS firmware on x86_64 and ppc64le.
|
|
|
|
The project is used in Bootable Containers and ostree/rpm-ostree based systems:
|
|
- [`bootc install`](https://github.com/containers/bootc/#using-bootc-install)
|
|
- [Fedora CoreOS](https://docs.fedoraproject.org/en-US/fedora-coreos/bootloader-updates/)
|
|
- Fedora Atomic Desktops
|
|
|
|
On systems booted using a UEFI firmware, bootloader updates performed by
|
|
bootupd are now considered safe, even in case of power failures (see:
|
|
[issue#454](https://github.com/coreos/bootupd/issues/454)).
|
|
|
|
On other systems (BIOS, etc.), bootloader updates performed by bootupd not safe
|
|
against a power failures at the wrong time.
|
|
|
|
Note that bootupd does not yet perform updates in a way that is safe against a
|
|
buggy bootloader update that fails to boot the system. This is tracked in
|
|
[issue#440](https://github.com/coreos/bootupd/issues/440).
|
|
|
|
Bootloader updates are enabled by default on Fedora Atomic Desktops, and will
|
|
soon be on all Bootable Containers systems. See
|
|
[fedora-coreos-tracker#1468](https://github.com/coreos/fedora-coreos-tracker/issues/1468).
|
|
|
|
The bootupd CLI should be considered stable.
|
|
|
|
## Relationship to other projects
|
|
|
|
### dbxtool
|
|
|
|
[dbxtool](https://github.com/rhboot/dbxtool) manages updates
|
|
to the Secure Boot database - `bootupd` will likely need to
|
|
perform any updates to the `shimx64.efi` binary
|
|
*before* `dbxtool.service` starts. But otherwise they are independent.
|
|
|
|
### fwupd
|
|
|
|
bootupd could be compared to [fwupd](https://github.com/fwupd/fwupd/) which is
|
|
a project that exists today to update hardware device firmware - things not managed
|
|
by e.g. `apt/zypper/yum/rpm-ostree update` today.
|
|
|
|
fwupd comes as a UEFI binary today, so bootupd *could* take care of updating `fwupd`
|
|
but today fwupd handles that itself. So it's likely that bootupd would only take
|
|
care of GRUB and shim. See discussion in [this issue](https://github.com/coreos/bootupd/issues/1).
|
|
|
|
### systemd bootctl
|
|
|
|
[systemd bootctl](https://man7.org/linux/man-pages/man1/bootctl.1.html) can update itself;
|
|
this project would probably just proxy that if we detect systemd-boot is in use.
|
|
|
|
## Other goals
|
|
|
|
One idea is that bootupd could help support [redundant bootable disks](https://github.com/coreos/fedora-coreos-tracker/issues/581).
|
|
For various reasons it doesn't really work to try to use RAID1 for an entire disk; the ESP must be handled
|
|
specially. `bootupd` could learn how to synchronize multiple EFI system partitions from a primary.
|
|
|
|
## More details on rationale and integration
|
|
|
|
A notable problem today for [rpm-ostree](https://github.com/coreos/rpm-ostree/) based
|
|
systems is that `rpm -q shim-x64` is misleading because it's not actually
|
|
updated in place.
|
|
|
|
Particularly [this commit][1] makes things clear - the data
|
|
from the RPM goes into `/usr` (part of the OSTree), so it doesn't touch `/boot/efi`.
|
|
But that commit didn't change how the RPM database works (and more generally it
|
|
would be technically complex for rpm-ostree to change how the RPM database works today).
|
|
|
|
What we ultimately want is that `rpm -q shim-x64` returns "not installed" - because
|
|
it's not managed by RPM or by ostree. Instead one would purely use `bootupctl` to manage it.
|
|
However, it might still be *built* as an RPM, just not installed that way. The RPM version numbers would be used
|
|
for the bootupd version associated with the payload, and ultimately we'd teach `rpm-ostree compose tree`
|
|
how to separately download bootloaders and pass them to `bootupctl backend`.
|
|
|
|
[1]: https://github.com/coreos/rpm-ostree/pull/969/commits/dc0e8db5bd92e1f478a0763d1a02b48e57022b59
|
|
|
|
|
|
## Questions and answers
|
|
|
|
- Why is bootupd not part of ostree?
|
|
|
|
A key advertised feature of ostree is that updates are truly transactional.
|
|
There's even a [a test case](https://blog.verbum.org/2020/12/01/committed-to-the-integrity-of-your-root-filesystem/)
|
|
that validates forcibly pulling the power during OS updates. A simple
|
|
way to look at this is that on an ostree-based system there is no need
|
|
to have a "please don't power off your computer" screen. This in turn
|
|
helps administrators to confidently enable automatic updates.
|
|
|
|
Doing that for the bootloader (i.e. bootupd's domain) is an *entirely* separate problem.
|
|
There have been some ideas around how we could make the bootloaders
|
|
use an A/B type scheme (or at least be more resilient), and perhaps in the future bootupd will
|
|
use some of those.
|
|
|
|
These updates hence carry different levels of risk. In many cases
|
|
actually it's OK if the bootloader lags behind; we don't need to update
|
|
every time.
|
|
|
|
But out of conservatism currently today for e.g. Fedora CoreOS, bootupd is disabled
|
|
by default. On the other hand, if your OS update mechanism isn't transactional,
|
|
then you may want to enable bootupd by default.
|
|
|
|
- Is bootupd a daemon?
|
|
|
|
It was never a daemon. The name was intended to be "bootloader-upDater" not
|
|
"bootloader-updater-Daemon". The choice of a "d" suffix is in retrospect
|
|
probably too confusing.
|
|
|
|
bootupd used to have an internally-facing `bootupd.service` and
|
|
`bootupd.socket` systemd units that acted as a locking mechanism. The service
|
|
would *very quickly* auto exit. There was nothing long-running, so it was not
|
|
really a daemon.
|
|
|
|
bootupd now uses `systemd-run` instead to guarantee the following:
|
|
|
|
- It provides a robust natural "locking" mechanism.
|
|
- It ensures that critical logging metadata always consistently ends up in the
|
|
systemd journal, not e.g. a transient client SSH connection.
|
|
- It benefits from the sandboxing options available for systemd units, and
|
|
while bootupd is obviously privileged we can still make use of some of this.
|
|
- If we want a non-CLI API (whether that's DBus or Cap'n Proto or varlink or
|
|
something else), we will create an independent daemon with a stable API for
|
|
this specific need.
|
|
|