11个版本

0.2.9 2023年1月20日
0.2.6 2021年9月8日
0.2.5 2021年1月6日
0.2.4 2020年12月15日
0.1.2 2020年9月22日

#164操作系统

每月下载量44次

Apache-2.0

100KB
2K SLoC

bootupd: 引导加载程序的分布式独立更新

如今,许多Linux系统以不一致和临时的方式处理引导加载程序数据的更新。例如,在Fedora和Debian上,包管理器更新将更新/boot/efi中的UEFI二进制文件,但不会更新BIOS MBR数据。

事务性/“镜像”更新系统,如OSTree,以及双分区系统,如Container Linux更新系统,则更为一致:它们通常涵盖内核/用户空间,但不包括与引导加载程序相关的内容。

原因很简单:以“A/B”的方式执行引导加载程序更新需要在管理内核和根文件系统之外,完全独立的非平凡逻辑。如今,例如,OSTree选择了不更新/boot/efi(也不更新BIOS MBR)。

本项目目标是成为一个跨分布、不依赖于特定OS更新系统的工具,以管理以下内容的更新:

  • /boot/efi
  • x86 BIOS MBR
  • 其他架构的引导加载程序

本项目起源于这个Fedora CoreOS GitHub问题

范围限制在其他方面;例如,bootupd不会管理与内核相关的内容,如内核参数;这是为像grubbyostree这样的工具准备的。

状态

目前处于开发中,尚未准备好用于生产更新,但欢迎对设计提供早期反馈!

与其他项目的关系

dbxtool

dbxtool 管理安全启动数据库的更新 - bootupd 可能需要在dbxtool.service启动之前执行任何对shimx64.efi二进制文件的更新。但除此之外,它们是独立的。

fwupd

bootupd可以与fwupd进行比较,fwupd是一个现有的项目,用于更新硬件设备的固件 - 这些设备目前不是由apt/zypper/yum/rpm-ostree update管理的。

fwupd 目前作为一个 UEFI 二进制文件,因此 bootupd 可能会负责更新 fwupd,但今天 fwupd 自己处理这一过程。因此,bootupd 可能只会处理 GRUB 和 shim。请参阅 这个问题 的讨论。

systemd bootctl

systemd bootctl 可以更新自身;如果检测到使用 systemd-boot,该项目可能会仅作为代理。

其他目标

一个想法是,bootupd 可以帮助支持 冗余可启动磁盘。由于各种原因,尝试使用 RAID1 整个磁盘并不实际;ESP 必须特别处理。bootupd 可以学习如何从主分区同步多个 EFI 系统分区。

关于原因和集成的更多细节

对于基于 rpm-ostree 的系统,一个显著问题是 rpm -q shim-x64 是误导性的,因为它实际上并未在原地更新。

特别是 这个提交 清晰地说明了问题 - RPM 的数据进入 /usr(OSTree 的一部分),因此它不会触及 /boot/efi。但这个提交并没有改变 RPM 数据库的工作方式(并且更普遍地说,rpm-ostree 在今天改变 RPM 数据库的工作方式在技术上可能很复杂)。

我们最终想要的是 rpm -q shim-x64 返回 "未安装",因为它是通过 RPM 或 ostree 管理的。取而代之的是,人们将纯粹使用 bootupctl 来管理它。然而,它可能仍然被 构建 为 RPM,但不是以这种方式安装。RPM 版本号将用于与有效负载相关的 bootupd 版本,最终我们会教 rpm-ostree compose tree 如何单独下载引导加载程序并将它们传递给 bootupctl 后端

问题和答案

  • 为什么 bootupd 不是 ostree 的一部分?

ostree 的一个主要宣传特性是更新确实是事务性的。甚至有一个 测试案例 来验证在操作系统更新期间强制断电。简单来说,在基于 ostree 的系统中,不需要有一个 "请勿关闭计算机电源" 的屏幕。这反过来帮助管理员自信地启用自动更新。

对于引导加载程序(即 bootupd 的领域)做这件事是一个 完全 不同的难题。有一些关于我们如何使引导加载程序使用 A/B 类型的方案(或者至少更健壮)的想法,也许未来 bootupd 将使用其中的一些。

因此,这些更新具有不同级别的风险。实际上,引导加载程序落后是可以接受的;我们不需要每次都更新。

但出于保守起见,目前例如在 Fedora CoreOS 中,bootupd 默认是禁用的。另一方面,如果你的操作系统更新机制不是事务性的,那么你可能希望默认启用 bootupd。

  • 为什么 bootupd 是一个守护进程?

实际上并不是。这个名字的意图是 "bootloader-upDater" 而不是 "bootloader-updater-Daemon";"d" 后缀的选择在回顾起来可能太容易引起混淆了。

在技术层面上,确实有一个由套接字激活的系统d服务,它将启动一个 bootupd.service。然而——该服务会 非常快地 自动退出。没有长时间运行的内容,所以它实际上不是一个守护进程。

这种设计的理由是

  • 使用系统d服务提供了一个健壮的自然“锁定”机制。
  • 使用系统d服务确保关键日志元数据始终一致地进入系统d日志,而不是例如短暂的客户端SSH连接。
  • 系统d服务可以轻松地应用沙箱,尽管bootupd显然具有特权,我们仍然可以利用其中的一些。
  • 最终,我们可能需要一个非CLI API(无论是DBus、Cap'n Proto、varlink还是其他什么),拥有一个套接字(没有定义的稳定API)是为这个目的做准备工作。

依赖项

~13–25MB
~374K SLoC