Regenerating `initramfs` from another snapshot with `mkinitcpio`
I was hit by an unfortunate bug recently, in which a bundled ssl
library overrode the
system wide version rendering my system unbootable. I could not even get into early userspace because the
initramfs
generated with this library could not cryptsetup open
my encrypted root
partition.
This is usually a moment in which those who have a (btrfs/zfs/lvm) system, can calmly rollback their system and go on with their day. At some point in the future, they can try to upgrade again, and hope the problem is fixed.
(This is a good example to illustrate why /boot
along with the initramfs
files
should be kept under rollback control, otherwise snapshots using older kernels would still not be bootable,
because you would still be using the new initramfs
.)
Suppose we want to fix the issue directly: we need to know how to regenerate an initramfs
from a
system root that is not the current one (/
).
Suppose our snapshots look like this
/btrfs/@root
/btrfs/snapshots/@good_snapshot-1
/btrfs/snapshots/@good_snapshot-2
/btrfs/snapshots/@good_snapshot-3
After the update, /btrfs/@root
is broken (because
/btrfs/@root/boot/initramfs-linux.img
is broken) and suppose we are currently booted into
/btrfs/snapshots/@good_snapshot-3
. What it means for us to be “booted into”
/btrfs/snapshots/@good_snapshot-3
is that the snapshot
/btrfs/snapshots/@good_snapshot-3
is mounted to /
just after the root partition is
unlocked in the boot process.
Reading the manual of mkinitcpio
we see that we need the options
-g, --generate filename
Generate a CPIO image as filename. Default: no; this means nothing will
be written to the filesystem unless this option is specified.
-r, --moduleroot root
Specifies the root directory to find modules in, defaulting to /
-k, --kernel kernelversion
Use kernelversion, instead of the current running kernel. This may be a
path to a kernel image (only supported for x86-based architectures), a
specific kernel version or the special keyword none. In the latter case,
no kernel modules are added to the image.
The option -g
will tell mkinitcpio
where to save the initramfs, we want this to be
generated in the root of the currently broken snapshot /btrfs/@root/boot/initramfs-linux.img
.
Moreover, we want mkinitcpio
to read all module information from /btrfs/@root
and not
/
(which is currently mounted to /btrfs/snasphots/@good_snapshot-3
), so we pass this to
the -r
option. Finally, we want mkinitcpio
to read the correct kernel version (image)
from disk to create the initramfs
, so we need to pass -k
/btrfs/@root/boot/vmlinuz-linux
to mkinitcpio
. Now that the initramfs
has been
regenerated, we can re-install our bootloader entries and boot into /btrfs/@root
as usual.
This is another example where Unified Kernel Images (UKI’s) can really save you: after regenerating the
initramfs
, we can simply re-create a bootable UKI1 to create a bootable system. We need not worry about bootloaders
getting confused with archived snapshots and live systems.
-
and if necessary create a new EFI entry with
efibootmgr
↩︎