From 4006c624640e0453630da0fc5ae2fd7081235bc7 Mon Sep 17 00:00:00 2001 From: Joseph Marrero Corchado Date: Mon, 14 Sep 2026 10:25:38 -0400 Subject: [PATCH] docs: Add guidance for machine-local initramfs content Admins might need to add machine-specific initramfs content after install (a udev rule to unlock local storage is the classic case) and reach for editing /boot, which bootc overwrites on update. Document the supported path: build a machine-local derived image that regenerates the initramfs, so the image stays the source of truth. Also record why rpm-ostree's client-side initramfs is incompatible with bootc upgrade, and the UKI-addon direction. Assisted-by: AI Signed-off-by: Joseph Marrero Corchado --- docs/src/SUMMARY.md | 1 + docs/src/booting-local-builds.md | 50 ++++++++++++++ docs/src/initramfs.md | 110 +++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 docs/src/initramfs.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 51500d1c7a..febae75cdb 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -22,6 +22,7 @@ - [Accessing registries and offline updates](registries-and-offline.md) - [Logically bound images](logically-bound-images.md) - [Booting local builds](booting-local-builds.md) +- [Managing the initramfs after installation](initramfs.md) - [`man bootc`](man/bootc.8.md) - [`man bootc-status`](man/bootc-status.8.md) - [`man bootc-upgrade`](man/bootc-upgrade.8.md) diff --git a/docs/src/booting-local-builds.md b/docs/src/booting-local-builds.md index 6edaaccdfa..9b7970deb6 100644 --- a/docs/src/booting-local-builds.md +++ b/docs/src/booting-local-builds.md @@ -39,3 +39,53 @@ From there, the new image will be queued for the next boot and a `reboot` will apply it. For more on valid transports, see [containers-transports](https://github.com/containers/image/blob/main/docs/containers-transports.5.md). + +## Automating local rebuilds + +The build and switch above can be automated with a systemd service and timer. +For example, keep the build context in `/var/lib/machine-bootc` and build the +image on a schedule: + +```systemd +# /etc/systemd/system/machine-bootc-build.service +[Unit] +Description=Build the machine-local bootc image +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +WorkingDirectory=/var/lib/machine-bootc +ExecStart=/usr/bin/podman build --security-opt=label=disable --pull=newer --tag localhost/machine-bootc:latest . +``` + +```systemd +# /etc/systemd/system/machine-bootc-build.timer +[Unit] +Description=Build the machine-local bootc image daily + +[Timer] +OnCalendar=*-*-* 06:00:00 +Persistent=true + +[Install] +WantedBy=timers.target +``` + +```console +$ sudo systemctl daemon-reload +$ sudo systemctl enable --now machine-bootc-build.timer +``` + +This automates only the build. Staging the new image with `bootc switch` and +rebooting are intentionally left as explicit operations; automate them only +with a reboot policy appropriate for the machine. + +Automating the rebuild is only worthwhile if the build reliably produces a new +image *when, and only when, an input changed*. With `--pull=newer` an identical +rebuild is a full cache hit and yields the same image, so nothing new is +deployed. But that relies on the build cache, not on reproducible output: a +step whose result is not deterministic (regenerating an initramfs is a common +example) can produce a different image on a cache-busted rebuild even when +nothing meaningful changed, causing needless reboots. Prefer reproducible build +steps for anything driven on a timer. diff --git a/docs/src/initramfs.md b/docs/src/initramfs.md new file mode 100644 index 0000000000..a03772edbc --- /dev/null +++ b/docs/src/initramfs.md @@ -0,0 +1,110 @@ +# Managing the initramfs after installation + +The initramfs is part of the container image and is updated together with the +image. On systems using the OSTree backend with a split kernel and initramfs, +the canonical path is `/usr/lib/modules/$kver/initramfs.img`. Editing the copy +in `/boot` is not supported because `bootc` replaces it from the container +image during an update. + +For how to modify and regenerate the initramfs *inside* an image build, +including dracut drop-in configuration, see your operating system's +documentation, for example Fedora's +[bootc initramfs guide](https://docs.fedoraproject.org/en-US/bootc/initramfs/). + +## Prefer generic configuration + +Content that at first looks machine-specific often does not need to be. A +single generic image can carry configuration that dispatches on a +machine-specific identifier at runtime — a hardware MAC address, a DMI +property, a disk serial, and so on. A udev rule that matches particular +hardware, for instance, can ship in the base or a shared derived image and +still only act on the machine that has that hardware. + +Reach for a machine-local image only when the content genuinely cannot be +expressed generically. Keeping configuration in shared images means fewer +distinct images to build, test, and update. + +## Machine-local initramfs content + +When machine-specific initramfs content really is required — such as a udev +rule needed to unlock local storage that cannot be selected generically — and +until `bootc` has a dedicated interface for this use case, build a +machine-local derived image containing the configuration and its regenerated +initramfs. This keeps the image, rather than mutable files in `/boot`, as the +source of truth. + +> This procedure applies to the OSTree backend with a split kernel and +> initramfs. It does not apply to sealed composefs/UKI images. + +Create a build context containing the machine-specific files. For example: + +```text +. +├── Containerfile +└── 98-storage.rules +``` + +The `Containerfile` derives from the image shown by `bootc status`, adds the +files, and regenerates the initramfs. Configure dracut with a drop-in under +`/usr/lib/dracut/dracut.conf.d` and regenerate for the image's kernel, per your +OS's initramfs documentation: + +```Dockerfile +FROM quay.io/example/example-bootc:latest + +COPY 98-storage.rules /etc/udev/rules.d/98-storage.rules +RUN echo 'install_items+=" /etc/udev/rules.d/98-storage.rules "' \ + > /usr/lib/dracut/dracut.conf.d/50-storage.conf + +RUN set -xe; kver=$(ls /usr/lib/modules); \ + env DRACUT_NO_XATTR=1 dracut -vf "/usr/lib/modules/${kver}/initramfs.img" "$kver"; \ + bootc container lint +``` + +A bootc image must contain exactly one kernel, so `ls /usr/lib/modules` must +resolve to a single directory; `bootc container lint` checks this image +invariant. Dracut must be told the kernel version explicitly, because its +default targets the *running* kernel, which is not what a build should use. The +exact dracut modules and arguments depend on the base image and the content +being added. + +Build the image locally and deploy it exactly as any other local build; see +[Booting local builds](booting-local-builds.md) for building against the booted +image, the `containers-storage` transport, and automating the rebuild. Rebuild +and switch to this derived image whenever either the base image or the +machine-specific configuration changes. + +## The rpm-ostree client-side initramfs mechanism + +On rpm-ostree-managed systems, `rpm-ostree initramfs --enable` enables +client-side initramfs regeneration and accepts additional dracut arguments. +However, this mechanism predates bootc and records the regenerated initramfs as +a local rpm-ostree modification in the deployment origin (a +`regenerate-initramfs` key under `[rpmostree]`). + +Bootc does not currently know how to reproduce or carry that configuration +onto a new container-image deployment. It marks a deployment with rpm-ostree +local modifications as incompatible, and `bootc upgrade` refuses to update it +with an error such as "Deployment contains local rpm-ostree modifications". +Running `rpm-ostree reset` removes the local modifications and allows bootc to +manage the deployment again, but also removes the client-side initramfs +configuration. It may remove other rpm-ostree package layering and overrides as +well, so inspect the pending changes before running it. Therefore, do not use +`rpm-ostree initramfs --enable` for this workflow if the system is intended to +continue receiving updates through bootc; use a derived container image +instead. See also +[Relationship with rpm-ostree](relationships.md#relationship-with-rpm-ostree). + +## Future direction + +[UKI add-ons](https://uapi-group.org/specifications/specs/unified_kernel_image/#addon-uki-format) +are the intended mechanism for adding machine-specific kernel arguments or +initrd content without rebuilding a Unified Kernel Image. The bootc project is +working toward this model for composefs/UKI systems. + +For OSTree environments that do not use composefs with sealed UKIs, support for +supplementary initrds has been requested in +[ostree#3634](https://github.com/ostreedev/ostree/issues/3634), and a general +bootc interface is being designed in +[bootc#2414](https://github.com/bootc-dev/bootc/issues/2414). Until that design +is implemented, use the machine-local derived-image workflow above.