Edit Date | Note |
---|---|
2020.01.10T02:41 | Updated script to use UUID. Also need {console,tty,null} devices for before devtmpfs is mounted. |
Packages
Packages | Compile notes |
---|---|
sys-apps/busybox | Compile with USE+=static . |
sys-fs/cryptsetup | Compile with USE+=static . |
sys-fs/lvm2 |
Compile with USE+=static .
On my minimal profile OpenRC system this needed eudev with
USE+=static-libs as well.
Otherwise the lvm2 compile would fail with a linking error about
not finding -ludev .
|
Initramfs folder setup
As with the linked reference guide, we'll also use
/usr/src/initramfs
to store the initramfs files.
-
Create the folder hierarchy
mkdir /usr/src/initramfs
cd /usr/src/initramfs
mkdir -p {bin,dev,etc,lib,lib64,mnt/root,proc,root,sbin,sys}
-
Copy needed binaries/files. Verify that the binaries are static by using
file
and/orldd
.cp -a /dev/{console,null,tty} dev/
cp -a /dev/{urandom,random} dev/
cp -a /bin/busybox bin/busybox
cp -a /sbin/cryptsetup sbin/cryptsetup
cp -a /sbin/lvm.static sbin/lvm
Setup LVM to not use udev
In etc/lvm/lvm.conf
, place the following.
devices { # Disable scanning udev for md/multipath components. # This is required with recent versions of lvm2, even if you use another solution for # your LV device nodes; without it lvm commands will stall for minutes waiting for udev. multipath_component_detection = 0 md_component_detection = 0 } activation { # Set to 0 to disable udev synchronisation (if compiled into the binaries). udev_sync = 0 # Set to 0 to disable the udev rules installed by LVM2 udev_rules = 0 }
Create the init
script
Do touch init && chmod +x init
. Now place the following into
init
.
Adjust the config section with crypt device, Volume Group, and Logical Volume
names.
#!/bin/busybox sh # # Init script for root on LUKS + LVM. # https://wiki.gentoo.org/wiki/Custom_Initramfs # ###### START config ############### # What is the device? CRYPT_UUID="a8a160c4-dedc-403b-9040-8e402574f3c6" # What should we name the crypt device when we open it? CRYPT_NAME="immanuel-crypt" # The Volume Group where the root Logical Volume lies. VG_NAME="immanuel-vg" # The name of the root Logical Volume in above ${VG_NAME}. LV_ROOT="gentoo-root" ###### END config ############### fail() { echo "ERROR: $@" echo "Something went wrong. Sleeping for 10 and then shutting down." sleep 10 exit 1 } # Mount the /dev, /proc, and /sys filesystems. echo "INFO: Mounting temporary /dev, /proc, and /sys." mount -t devtmpfs none /dev || fail "/dev mount failed." mount -t proc none /proc || fail "/proc mount failed." mount -t sysfs none /sys || fail "/sys mount failed." # Waiting for drive to come online. UUID_DEVICE="" for i in $(seq 1 5); do echo "INFO: [attempt ${i}] Trying to find ${CRYPT_UUID}." sleep 1 UUID_DEVICE="$(findfs UUID="${CRYPT_UUID}")" if [ -n "${UUID_DEVICE}" ]; then echo "INFO: Found UUID!" break fi done [ -z "${UUID_DEVICE}" ] && fail "Could not find the UUID within time." # Do your stuff here. echo "INFO: Unlocking LUKS ${CRYPT_DEVICE} as ${CRYPT_NAME}" mkdir -p -m0700 /run/cryptsetup cryptsetup --tries=5 luksOpen "${UUID_DEVICE}" "${CRYPT_NAME}" \ || fail "luksOpen failed." echo "INFO: Activating root LV." lvm vgscan --mknodes # Creates /dev/mapper/control lvm lvchange -a ly "${VG_NAME}/${LV_ROOT}" || fail "Could not find LV root." lvm vgscan --mknodes # Creates /dev/mapper/${VG_NAME} and # /dev/${VG_NAME}/${LV_ROOT} # Mount the root filesystem. echo "INFO: Mounting the root filesystem system." mount "/dev/${VG_NAME}/${LV_ROOT}" /mnt/root \ || fail "Failed to mount root file system." # Clean up. echo "INFO: Unmounting up temporary /proc and /sys." umount /dev || fail "/dev failed to unmount." umount /proc || fail "/proc failed to unmount." umount /sys || fail "/sys failed to unmount." # Boot the real thing. echo "INFO: Switching root to real system." exec switch_root /mnt/root /sbin/init || fail "Failed to switch_root."An 'up-to-date' version can be found here https://gitlab.com/mrkmr/gentoo-conf/-/blob/master/initramfs/init.
Kernel configuration
Now we need to include the initramfs in our kernel.
After make menuconfig
in /usr/src/linux
, search for
CONFIG_INITRAMFS_SOURCE.
Set this value to /usr/src/initramfs
.
Now the kernel will use the initramfs folder we created with our init script on
boot!
Next we need to ensure we have EFISTUB enabled so we can directly boot the
kernel from UEFI without a bootloader.
Ensure CONFIG_EFI_STUB is enabled.
Now make
, make modules_install
, and
make install
.
You may also want to add quiet loglevel=5
to
CONFIG_CMDLINE so that it is easier to see initramfs output like
the cryptsetup password prompt.
EFISTUB booting
The way I have my partition setup is no /boot
partition (it's a
part of the root partition).
I have an EFI partition mounted on /boot/efi
.
Copy your recently compiled kernel (should be in
/boot/vmlinuz-XXX-gentoo-rX
) into /boot/efi
.
Now we can create the EFI boot entry to directly boot our kernel.
Here the /boot/efi
partition is partition 1 on disk
nvme0n1.
My kernel is vmlinuz-5.4.80-gentoo-r1.
efibootmgr --create --disk /dev/nvme0n1 --part 1 --label Gentoo 5.4.80 r1
--loader \vmlinuz-5.4.80-gentoo-r1