Gentoo Linux Installation Guide: Encrypted Btrfs with OpenRC, EFI Stub, Secure Boot & TPM
Target audience: Intermediate–advanced Linux users.
Features: Full disk encryption (LUKS2), Btrfs with subvolumes, OpenRC init, EFI stub boot, Secure Boot (with custom keys), TPM2 auto-unlock via Clevis.
Based on: Gentoo Wiki, Arch Wiki, and personal tweaks.
Now let us get started!!
1. Preparation & Boot
- Boot from a valid Gentoo ISO (download).
- Configure your network – the ISO usually gets DHCP automatically.
If needed, follow the Gentoo Handbook Networking. - Optional but recommended: start SSH daemon so you can copy-paste commands from another machine
rc-service sshd start
passwd # set a root password2. UEFI Partition Layout
We'll use cfdisk on your main drive (e.g., /dev/nvme0n1).
| Partition | Size | Type | Label |
|---|---|---|---|
/dev/nvme0n1p1 | 1 GiB | EFI System | GentooBoot |
/dev/nvme0n1p2 | rest | Linux filesystem | (will be LUKS) |
cfdisk /dev/nvme0n1Example layout:
Device Start End Sectors Size Type
/dev/nvme0n1p1 882423808 884520959 2097152 1G EFI System
/dev/nvme0n1p2 34816 629198847 629164032 300G Linux filesystem
⚠️ Adjust partition numbers and sizes to your drive.
3. Encryption (LUKS2)
We encrypt the root partition (/dev/nvme0n1p2) with strong LUKS2 parameters.
cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 --key-size 512 \
--pbkdf argon2id --pbkdf-memory 1048576 --iter-time 4000 \
--label "GentooLuks" /dev/nvme0n1p2
cryptsetup open /dev/nvme0n1p2 root
Now the decrypted device is /dev/mapper/root.
4. Btrfs Filesystem & Subvolumes
Create filesystems:
mkfs.vfat -n GentooBoot -F 32 /dev/nvme0n1p1
mkfs.btrfs -L GentooRoot /dev/mapper/rootMount the root Btrfs volume and create subvolumes:
mkdir -p /mnt/gentoo
mount LABEL=GentooRoot /mnt/gentoo/
btrfs subvolume create /mnt/gentoo/@
btrfs subvolume create /mnt/gentoo/@home
btrfs subvolume create /mnt/gentoo/@.snapshots
btrfs subvolume create /mnt/gentoo/@usr
btrfs subvolume create /mnt/gentoo/@opt
btrfs subvolume create /mnt/gentoo/@srv
btrfs subvolume create /mnt/gentoo/@db
btrfs subvolume create /mnt/gentoo/@log
btrfs subvolume create /mnt/gentoo/@tmp
btrfs subvolume create /mnt/gentoo/@crash
btrfs subvolume create /mnt/gentoo/@spool
btrfs subvolume create /mnt/gentoo/@portage
btrfs subvolume create /mnt/gentoo/@NetworkManager
btrfs subvolume create /mnt/gentoo/@binpkgs
btrfs subvolume create /mnt/gentoo/@distfiles
btrfs subvolume create /mnt/gentoo/@boot
umount -l /mnt/gentooNow mount each subvolume to its final location:
mount -o subvol=@ LABEL=GentooRoot /mnt/gentoo
mkdir -p /mnt/gentoo/{home,.snapshots,usr,opt,srv,boot,efi,var/{db,log,tmp,crash,spool,lib/{portage,NetworkManager},cache/{binpkgs,distfiles}}}
mount -o subvol=@home LABEL=GentooRoot /mnt/gentoo/home
mount -o [email protected] LABEL=GentooRoot /mnt/gentoo/.snapshots
mount -o subvol=@usr LABEL=GentooRoot /mnt/gentoo/usr
mount -o subvol=@opt LABEL=GentooRoot /mnt/gentoo/opt
mount -o subvol=@srv LABEL=GentooRoot /mnt/gentoo/srv
mount -o subvol=@db LABEL=GentooRoot /mnt/gentoo/var/db
mount -o subvol=@log LABEL=GentooRoot /mnt/gentoo/var/log
mount -o subvol=@tmp LABEL=GentooRoot /mnt/gentoo/var/tmp
mount -o subvol=@crash LABEL=GentooRoot /mnt/gentoo/var/crash
mount -o subvol=@spool LABEL=GentooRoot /mnt/gentoo/var/spool
mount -o subvol=@portage LABEL=GentooRoot /mnt/gentoo/var/lib/portage
mount -o subvol=@NetworkManager LABEL=GentooRoot /mnt/gentoo/var/lib/NetworkManager
mount -o subvol=@binpkgs LABEL=GentooRoot /mnt/gentoo/var/cache/binpkgs
mount -o subvol=@distfiles LABEL=GentooRoot /mnt/gentoo/var/cache/distfiles
mount -o subvol=@boot LABEL=GentooRoot /mnt/gentoo/boot
mount LABEL=GentooBoot /mnt/gentoo/efi📁 Why so many subvolumes? It gives flexibility for snapshots (e.g., you can snapshot @ and @home separately) and fine-grained mount options (e.g., nodev,noexec for /var/db).
5. Download Stage3 & Verify
Download a hardened OpenRC stage3 (LLVM/musl stages may not work with these instructions).
cd /mnt/gentoo
wget stage3-amd64-hardened-openrc-2025XXXX.tar.xz
wget stage3-amd64-hardened-openrc-2025XXXX.tar.xz.asc
gpg --import /usr/share/openpgp-keys/gentoo-release.asc
gpg --verify stage3-amd64-*.tar.xz.ascOnce verified, extract:
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt/gentoo6. Portage Configuration
Edit /mnt/gentoo/etc/portage/make.conf:
COMMON_FLAGS="-march=native -O2 -pipe"
ACCEPT_LICENSE="*"
FEATURES="${FEATURES} getbinpkg binpkg-request-signature"Copy DNS info into the chroot:
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/7. Chroot & System Setup
Mount the virtual filesystems and enter the chroot:
mount --types proc /proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys && mount --make-rslave /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev && mount --make-rslave /mnt/gentoo/dev
mount --bind /run /mnt/gentoo/run && mount --make-slave /mnt/gentoo/run
chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) ${PS1}"Now inside chroot:
# Get latest repository snapshot
emerge-webrsync
# Setup binary package host (getuto = Gentoo's binary package service)
getuto
# Choose fastest mirrors
emerge --ask --verbose --oneshot app-portage/mirrorselect
mirrorselect -i -o >> /etc/portage/make.conf
# Full sync
emerge --sync
# Select profile (hardened OpenRC)
eselect profile list
eselect profile set 21 # adjust number to your choice
# CPU optimizations
emerge --ask --oneshot app-portage/cpuid2cpuflags
echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpu-flags
# Update @world
emerge -avuDUg @world
# Cleanup
emerge --ask --depclean
# Install a text editor
emerge --ask app-editors/nanoLocale & Timezone
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
eselect locale set en_US.utf8
ln -sf /usr/share/zoneinfo/YourRegion/City /etc/localtime
env-update && source /etc/profile && export PS1="(chroot) ${PS1}"8. Kernel, Initramfs & EFI Stub Boot
We'll use the distribution kernel (gentoo-kernel-bin) with dracut for initramfs.
# Use dracut with installkernel
echo "sys-kernel/installkernel dracut" >> /etc/portage/package.use/installkernel
# Required packages
emerge --ask sys-kernel/linux-firmware sys-firmware/sof-firmware \
sys-fs/btrfs-progs sys-fs/cryptsetup sys-kernel/installkernel
# Configure dracut
echo 'hostonly="yes"' >> /etc/dracut.conf
echo 'hostonly_mode=strict' >> /etc/dracut.conf
echo 'add_dracutmodules+=" crypt "' >> /etc/dracut.conf
# Install kernel
emerge --ask sys-kernel/gentoo-kernel-bin
echo 'USE="dist-kernel"' >> /etc/portage/make.confConfigure /etc/fstab
Create an extensive fstab – here’s a shortened version (full one in your tutorial).
Example entry for root:
LABEL=GentooRoot / btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@ 0 0
LABEL=GentooRoot /home btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@home 0 0
LABEL=GentooRoot /.snapshots btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@.snapshots 0 0
LABEL=GentooRoot /usr btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@usr 0 0
LABEL=GentooRoot /opt btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@opt 0 0
LABEL=GentooRoot /srv btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@srv 0 0
LABEL=GentooRoot /var/db btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,ssd,discard,space_cache=v2,compress-force=zstd:10,commit=120,subvol=/@db 0 0
LABEL=GentooRoot /var/log btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@log 0 0
LABEL=GentooRoot /var/tmp btrfs rw,nosuid,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@tmp 0 0
LABEL=GentooRoot /var/crash btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@crash 0 0
LABEL=GentooRoot /var/spool btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@spool 0 0
LABEL=GentooRoot /var/lib/portage btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@portage 0 0
LABEL=GentooRoot /var/lib/NetworkManager btrfs rw,nodev,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@NetworkManager 0 0
LABEL=GentooRoot /var/cache/binpkgs btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,ssd,discard,space_cache=v2,compress-force=zstd:10,commit=120,subvol=/@binpkgs 0 0
LABEL=GentooRoot /var/cache/distfiles btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,ssd,discard,space_cache=v2,compress-force=zstd:10,commit=120,subvol=/@distfiles 0 0
LABEL=GentooRoot /boot btrfs rw,nosuid,nodev,noexec,noatime,lazytime,skip_balance,nodatacow,ssd,discard,space_cache=v2,commit=120,subvol=/@boot 0 0
LABEL=GentooBoot /efi vfat rw,nosuid,nodev,noexec,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,discard,flush,errors=remount-ro 0 2EFI Stub Boot with installkernel
mkdir -p /efi/EFI/Gentoo
# Enable efistub in installkernel
echo "sys-kernel/installkernel efistub" >> /etc/portage/package.use/installkernel
# Rebuild installkernel
emerge sys-kernel/installkernel
# Generate initramfs and kernel EFI binary
installkernel -a /lib/modulesSet kernel command line in /etc/default/uefi-mkconfig:
KERNEL_CONFIG="%entry_id %linux_name Linux %kernel_version ; rd.luks.label=GentooLuks root=LABEL=GentooRoot rootfstype=btrfs rootflags=subvol=@ video=efifb:mode=0"Now create a boot entry:
uefi-mkconfig
rebootIf EFI stub fails, fall back to GRUB or rEFInd (see Gentoo wiki).
9. System Configuration
Inside the new system (after reboot), complete basic setup:
# Hostname
echo "gentoo" > /etc/hostname
# Clock (if dual‑boot with Windows)
echo 'clock="local"' >> /etc/conf.d/hwclock
echo 'clock_systohc="YES"' >> /etc/conf.d/hwclock
# OpenRC parallel startup
echo 'rc_parallel="YES"' >> /etc/rc.conf
echo 'rc_autostart_user="NO"' >> /etc/rc.conf
# NetworkManager
emerge --ask net-misc/networkmanager
rc-update add NetworkManager default
# User account
useradd -m -s /bin/bash -G audio,video,wheel username
passwd username
EDITOR=nano visudo # uncomment %wheel ALL=(ALL) ALL10. Secure Boot (Custom Keys)
We'll generate our own keys and sign the kernel EFI binary.
Install tools:
emerge --ask app-crypt/efitools app-crypt/sbsigntools dev-libs/opensslKey generation (run as root)
mkdir -p /etc/efikeys && cd /etc/efikeys
# Save current keys (optional, but good for backup)
efi-readvar -v PK -o old_PK.esl
efi-readvar -v KEK -o old_KEK.esl
efi-readvar -v db -o old_db.esl
efi-readvar -v dbx -o old_dbx.esl
# Create GUID
uuidgen --random > guid.txt
# Generate keys (Platform Key, KEK, db)
openssl req -new -x509 -newkey rsa:4096 -subj "/CN=My Platform Key/" -keyout pk.key -out pk.crt -days 3650 -nodes -sha512
openssl req -new -x509 -newkey rsa:4096 -subj "/CN=My Key Exchange Key/" -keyout kek.key -out kek.crt -days 3650 -nodes -sha512
openssl req -new -x509 -newkey rsa:4096 -subj "/CN=My Signature DB Key/" -keyout db.key -out db.crt -days 3650 -nodes -sha512
# Create signature lists
cert-to-efi-sig-list -g "$(< guid.txt)" pk.crt pk.esl
sign-efi-sig-list -k pk.key -c pk.crt PK pk.esl pk.auth
cert-to-efi-sig-list -g "$(< guid.txt)" kek.crt kek.esl
cert-to-efi-sig-list -g "$(< guid.txt)" db.crt db.eslEnroll keys (UEFI must be in Setup Mode)
# Combine with old keys if you want to keep them
cat old_KEK.esl kek.esl > combined_KEK.esl
cat old_db.esl db.esl > combined_db.esl
# Update variables
efi-updatevar -e -f old_dbx.esl dbx
efi-updatevar -e -f combined_db.esl db
efi-updatevar -e -f combined_KEK.esl KEK
efi-updatevar -f pk.auth PKNow enable Secure Boot in your UEFI firmware.
Sign the kernel
# Remove old unsigned binaries
rm /efi/EFI/Gentoo/*
# Sign the kernel module (vmlinuz)
sbsign --key /etc/efikeys/db.key --cert /etc/efikeys/db.crt \
--output "/lib/modules/$(uname -r)/vmlinuz" \
"/lib/modules/$(uname -r)/vmlinuz"
# Regenerate EFI stub
installkernel
# Verify
sbverify --cert /etc/efikeys/db.crt /efi/EFI/Gentoo/vmlinuz-$(uname -r).efi11. TPM2 Auto‑Unlock with Clevis
This binds your LUKS key to TPM2 + Secure Boot PCRs, so the system unlocks automatically if firmware/bootloader are unchanged.
Install Clevis
eselect repository enable guru
emerge --sync
ACCEPT_KEYWORDS="~amd64" emerge -a app-crypt/clevisBind LUKS slot to TPM2
clevis luks bind -d /dev/nvme0n1p2 tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,7,9"}'PCR 0 = firmware, PCR 7 = Secure Boot state, PCR 9 = firmware config. Adjust as needed.
Encrypt the Secure Boot db.key (optional but recommended)
clevis encrypt tpm2 '{"pcr_bank":"sha256","pcr_ids":"0"}' < /etc/efikeys/db.key > /etc/efikeys/db.key.jweAutomate kernel signing during updates
Create a portage hook:
mkdir -p /etc/portage/env/sys-kernel
nano /etc/portage/env/sys-kernel/gentoo-kernel-binContent:
pre_pkg_postinst() {
sbsign --key <(clevis decrypt < /etc/efikeys/db.key.jwe) \
--cert /etc/efikeys/db.crt \
--output "/lib/modules/$(uname -r)/vmlinuz" \
"/lib/modules/$(uname -r)/vmlinuz"
}Make executable: chmod +x /etc/portage/env/sys-kernel/gentoo-kernel-bin
Now every kernel rebuild will be automatically signed using the TPM‑decrypted key
emerge -1 gentoo-kernel-binFinally, regenerate initramfs so the TPM unlock works at boot:
installkernel12. Troubleshooting & References
- EFI stub doesn’t appear – Check that
/efi/EFI/Gentoocontains.efifiles and your firmware boot order includes them. - Secure Boot fails – Put your firmware in Setup Mode before enrolling keys. Some boards require clearing Secure Boot settings.
- TPM unlock not working – Verify TPM is detected:
dmesg | grep -i tpm. Also ensureclevisis in your initramfs (dracut should include it automatically). - General Gentoo help – Stick to the Gentoo Handbook.
- Clevis & TPM – Gentoo Wiki: TPM/LUKS
🎉 Final words
You now have a hardened, encrypted, Btrfs‑snapshot‑ready Gentoo system with Secure Boot and TPM2 auto‑unlock. This setup balances security and convenience – the only password you need is your user account’s (and maybe the LUKS fallback password if TPM fails).
Disclaimer: This guide is for advanced users. Always test in a VM first if you’re unsure. The author is not responsible for data loss or bricked firmware.
Enjoy your custom Gentoo build!
Found this helpful? Share the post or leave a comment below.