Initramfs
cache22 splits the initramfs into separate img files. The UKI builder
(/usr/libexec/cache22/resign-uki) assembles them into one UKI at install and
on every bootc upgrade. The kernel unpacks concatenated cpio segments, so
several imgs combine into one initramfs at boot.
The imgs
Base img
/usr/lib/modules/<kver>/initramfs.img, built by
scripts/generate-initramfs.sh. It is the bare minimum needed to find the root
filesystem and unlock LUKS: storage controllers, btrfs/xfs/ext4, device-mapper,
dm-crypt, TPM2, the boot stack (bootc, ostree, systemd, and the erofs + overlay
modules ostree-prepare-root needs to mount the composefs root), and basic
input for typing a passphrase.
The base img is always sufficient to boot on its own. Tooling that loads only it
(an older resign-uki, or an ostree BLS entry before the builder has rewritten
it) still produces a bootable system.
Microcode img
/usr/lib/cache22/microcode.img, also built by generate-initramfs.sh. CPU
microcode is independent of the kernel version, so it is built once and shipped
as its own img. Both Intel and AMD microcode are included; the CPU applies
whichever vendor matches. resign-uki loads it first, ahead of the main
initramfs, because the CPU applies microcode before the main initramfs is
unpacked.
Keeping microcode out of the base img (early_microcode=no) means a microcode
package bump no longer re-pulls the whole initramfs layer.
User img (optional)
/var/lib/cache22/initramfs/user-<kver>.img, built per machine by
/usr/libexec/cache22/build-user-initrd when you configure additions. When
present, resign-uki uses it in place of the base img. See
Customizing below.
Extra segments (extensibility)
resign-uki also globs /usr/lib/cache22/initramfs.d/*.img in sorted order and
folds any imgs found there into the UKI, after the base img. The directory is
empty today. It exists so a future image can split high-churn content out of the
base img (for example firmware, or a driver set) into its own img, and therefore
its own OCI layer, by simply shipping a numbered img there. Because resign-uki
globs this directory rather than hardcoding names, the resign-uki already
deployed on a machine picks up such a new img on the next upgrade with no code
change. The microcode and base imgs stay hardcoded: microcode must load first,
and the base img is the kernel-specific anchor ostree manages.
Assembly
/usr/libexec/cache22/cache22-initramfs-list enumerates the ordered img set for
a deploy (microcode, then the user override or base img, then sorted extra
segments) and builds the user img on demand. It is the single source of truth for
what the initramfs contains; both firmware paths consume it, so they cannot
disagree:
- UEFI:
resign-ukipasses each img toukifyas a--initrdand writes one signed UKI per deploy to the ESP. sd-stub loads the concatenated segments. - BIOS:
cache22-bios-initramfsconcatenates the same imgs into one initrd file per BLS entry on the/bootpartition (/cache22/<entry>/initrd.img) and rewrites the entry’sinitrd=line to point at it. GRUB loads the single file and the kernel unpacks the concatenated cpio segments. A single file is the format ostree already writes and GRUB unambiguously supports, so the BIOS path carries no dependency on blscfg multi-initrd handling.
Both run at install, at finalize (chrooted into the new deploy via
resign-uki-finalize, so the build uses the new deploy’s modules and config),
and at runtime (cache22-resign-uki.service, dispatched by firmware through
cache22-boot-rebuild).
What is excluded, and why
Out-of-tree and DKMS modules (nvidia, zfs, the Realtek and Intel NIC DKMS
drivers, and so on) are excluded from every img. They are not needed to reach
the root filesystem: the GPU and network come up from the real root via udev
after switch_root, and cache22 never uses a ZFS root. They also change on
every driver bump, which would re-pull the initramfs layer. The exclusion is
written dynamically by generate-initramfs.sh into
/usr/lib/dracut/dracut.conf.d/20-cache22-omit-dkms.conf by enumerating
updates/ and extramodules/, so new DKMS modules are excluded automatically.
The dracut config (/usr/lib/dracut/dracut.conf.d/10-cache22.conf) also omits
modules that are not on the boot path for a local btrfs/xfs/ext4 root over
optional LUKS: network-root (iscsi/nfs/cifs), lvm, mdraid, nvdimm, resume,
fido2, pkcs11, hwdb, the VM share/net helpers, and module-signature checking
(enforcement is off). Some of these (lvm, mdraid, resume) may return as their
own imgs if cache22 grows support for them.
Customizing
To add drivers or other content to your machine’s initramfs, for example a NIC driver and an SSH client so the initramfs can fetch a remote LUKS key:
-
Drop a dracut config file into
/etc/dracut.conf.d/. It is read on top of the image default. Example/etc/dracut.conf.d/90-remote-unlock.conf:add_drivers+=" i40e " add_dracutmodules+=" network-manager " install_items+=" /usr/bin/curl " -
Apply it. This rebuilds the running deploy’s user img from the current config and folds it into the boot-time initramfs (the UKI on UEFI, the combined initrd on BIOS):
sudo systemctl start cache22-resign-uki.serviceIt is also applied automatically on the next
bootcupgrade or reboot. To build the img by hand, for example for a kernel version that is not running, runsudo /usr/libexec/cache22/build-user-initrd [kver].
resign-uki builds the user img for each live deploy in that deploy’s own
context. For the deploy it can build in context (the running deploy, or the
deploy being staged at finalize) it rebuilds the img on every run, so editing
/etc/dracut.conf.d and re-running it picks up the change instead of reusing a
stale img. For any other deploy (a rollback) it builds only when that deploy has
no img yet, by chrooting into it; that deploy’s /etc is frozen, so it needs no
rebuild otherwise. A deploy whose /etc carries no override keeps the base img.
The img is built to a temp file and renamed, so a failed rebuild never replaces a
working img.
Because the override lives in /etc, which ostree merges forward onto each new
deploy, a customization applies to the current deploy and to every deploy created
afterward. A deploy that predates the override (an existing rollback) stays on the
base img and still boots. On a kernel update no manual step is needed: the new
deploy’s initramfs is built at finalize against that deploy’s own kernel modules.
If a build fails, that deploy falls back to the base img with a warning, so the
machine still boots.
Firmware parity
The microcode, user, and extra imgs apply on both UEFI and BIOS: UEFI carries them as UKI sections, BIOS as the per-entry combined initrd (see Assembly). The one thing BIOS does not get is the UEFI-only security chain (Secure Boot signing and the TPM2 PCR measurements sd-stub makes); the initramfs contents are identical. Microcode is included on BIOS for completeness; a virtual-machine guest ignores it (the host applies CPU microcode), but a bare-metal BIOS install applies it.