
I recently picked up a Framework 13 Pro (Intel Core Ultra X7 358H) and naturally the first thing I did was wipe Windows and install Gentoo. Not because it’s easy, but because I enjoy the process and I wanted full control over the stack. Here’s what I ran into and how I solved it, so you don’t have to spend as long staring at dracut errors as I did.
the setup
The target setup was:
- systemd-boot as the bootloader
- Unified Kernel Image (UKI) via dracut
- LUKS2 full disk encryption on the NVMe
- LVM on top of LUKS (
system-swapandsystem-linux) - btrfs as the root filesystem with a
@gentoosubvolume - TPM2 auto-unlock so boot is seamless when Secure Boot is intact
- Plymouth for a nice splash screen at the LUKS prompt
partition layout
One thing that tripped me up early: systemd-boot with the Boot Loader Specification actually wants two partitions:
- ESP at
/efi— stores the bootloader.efifiles and UKIs - XBOOTLDR at
/boot— stores kernels and initramfs
In practice, since I only had one partition for boot, I went with the ESP at
/efi only and let installkernel put UKIs directly into /efi/EFI/Linux/.
systemd-boot auto-discovers these, so no loader entries needed.
the /boot mount check
When you first try to emerge linux-firmware, you’ll hit this:
* Your /boot partition is not mounted
* Please mount it and retry.
The eclass (mount-boot-utils.eclass) checks that something is actually
mounted at /boot, not just that the directory exists. The real fix depends
on your setup:
- If you have an XBOOTLDR partition, mount it at
/bootbefore emerging - If you’re ESP-only like me, you can bypass the check with:
# /etc/portage/package.env/linux-firmware
sys-kernel/linux-firmware no-boot-check.conf
# /etc/portage/env/no-boot-check.conf
DONT_MOUNT_BOOT=yes
Note: DONT_MOUNT_BOOT is the real variable name — I initially thought it was
SKIP_BOOT_CHECK but that doesn’t exist.
clock sync matters
If you’re installing from the Gentoo livecd and see SSL certificate errors when downloading distfiles, check your system clock first:
ntpd -qg
The livecd can boot with the clock significantly off, which makes Let’s Encrypt certs appear invalid.
lvm2 needs the lvm USE flag
This one caught me off guard. I had sys-fs/lvm2 installed but dracut kept
failing with:
dracut[E]: Module 'lvm' cannot be installed.
Turns out sys-fs/lvm2 without the lvm USE flag only installs the
device-mapper bits (dmsetup) — not the actual lvm binary. Dracut’s lvm
module needs lvm to be present.
echo "sys-fs/lvm2 lvm" >> /etc/portage/package.use/lvm2
emerge -av sys-fs/lvm2
the big one: dracut + systemd + LUKS
This is the main gotcha and the one most likely to send you down a rabbit hole.
When dracut detects the systemd module is active, the crypt module skips
installing the cryptsetup binary, assuming systemd will handle LUKS via
systemd-cryptsetup. But then systemd-cryptsetup-generator needs
/etc/crypttab to be present in the initramfs to know what to unlock — and by
default it isn’t.
The result: boot reaches dracut, never prompts for a passphrase, and hangs waiting for the root device forever. No password prompt, no emergency shell.
There are two fixes:
Option A (most reliable): omit systemd from the initramfs entirely. The
initramfs runs dracut’s own init and the traditional crypt module handles
LUKS. Your real system still boots into systemd normally.
omit_dracutmodules+=" systemd systemd-initrd dracut-systemd i18n systemd-udevd "
add_dracutmodules+=" lvm btrfs crypt dm rootfs-block "
add_drivers+=" dm_crypt "
Option B: keep systemd but force crypttab into the initramfs:
install_items+=" /etc/crypttab "
I initially went with Option A to get booting, then switched to Option B later
once I set up TPM2 (which requires systemd-cryptsetup).
tpm2 auto-unlock
Once you have a working boot, this is the fun part. The goal is: if Secure Boot is intact and the firmware hasn’t been tampered with, the TPM unseals the LUKS key automatically. If something looks wrong, it falls back to asking for your passphrase.
First, enable the right USE flags on systemd:
echo "sys-apps/systemd cryptsetup tpm" >> /etc/portage/package.use/systemd
emerge -av sys-apps/systemd
emerge -av app-crypt/tpm2-tools app-crypt/tpm2-tss
Enroll the TPM2 key into LUKS (keeps your passphrase as a fallback):
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/nvme0n1p2
PCR 0 binds to firmware, PCR 7 binds to Secure Boot state. If either changes, the TPM won’t unseal.
Update /etc/crypttab:
cryptroot UUID=<your-luks-uuid> none luks,tpm2-device=auto
Then update dracut to include crypttab and re-enable the systemd path:
# /etc/dracut.conf
install_items+=" /etc/crypttab "
add_dracutmodules+=" lvm btrfs crypt dm rootfs-block plymouth "
add_drivers+=" dm_crypt "
hostonly="yes"
uefi="yes"
kernel_cmdline="rd.luks.uuid=<uuid> rd.lvm.vg=system rd.lvm.lv=system/linux root=UUID=<root-uuid> rootfstype=btrfs rootflags=subvol=@gentoo rd.luks.allow-discards quiet splash"
Rebuild the UKI:
emerge --config '=sys-kernel/gentoo-kernel-bin-<version>:<version>'
Reboot — if everything is wired up correctly, you’ll boot straight through without a passphrase prompt.
plymouth
For the nice graphical splash (the one Fedora has), install Plymouth and add it to dracut:
emerge -av sys-boot/plymouth
plymouth-set-default-theme bgrt # shows the Framework logo
Add plymouth to add_dracutmodules in dracut.conf and make sure
quiet splash is in your kernel cmdline. Rebuild the UKI and you’re done.
final dracut.conf
install_items+=" /etc/crypttab "
add_dracutmodules+=" lvm btrfs crypt dm rootfs-block plymouth "
add_drivers+=" dm_crypt "
filesystems+=" btrfs "
early_microcode="yes"
hostonly="yes"
uefi="yes"
kernel_cmdline="rd.luks.uuid=<luks-uuid> rd.lvm.vg=system rd.lvm.lv=system/linux root=UUID=<root-uuid> rootfstype=btrfs rootflags=subvol=@gentoo rd.luks.allow-discards quiet splash"
wrapping up
The Framework 13 Pro works great on Gentoo. WiFi (Intel BE211), Bluetooth,
audio, touchpad, webcam, and the fingerprint reader all came up with no extra
configuration beyond what linux-firmware provides. The ucsi_acpi USB-C errors
in dmesg are a known Framework/kernel quirk and don’t affect functionality.
The whole LUKS + LVM + btrfs + TPM2 stack is solid once you get past the dracut systemd interaction. Hopefully this saves someone a few hours of head-scratching.
Jesse out. Peace!
