Gentoo linux installation encrypted btrfs openrc EFI stub boot secure boot tpm
Gentoo is one of my best Linux distro as compared to Arch which used to be my daily driver for quite some time. The great thing about gentoo for me is Portage; which is the package manager. This guide will take you through the many hurdles most people encounter during Gentoo installation, especially when trying to set up encryption.
Remember you will still need to follow the install guide to setup network, adding users among others that suit your preference. Now let us get thing started!
Gentoo linux installation encrypted btrfs openrc EFI stub boot secure boot tpm
Boot from a valid Gentoo ISO, configure the network, and set up SSH if possible.
Set up your UEFI Standard partition layout
cfdisk /dev/nvme0n1
Device Start End Sectors Size Type
/dev/nvme0n1p1 882423808 884520959 2097152 1G EFI System
/dev/nvme0n1p2 34816 629198847 629164032 300G Linux filesystem
Encrypt your block device for root filesystem{#2}
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
Create filesystems{#3}
mkfs.vfat -n GentooBoot -F 32 /dev/nvme0n1p1
mkfs.btrfs -L GentooRoot /dev/mapper/root
Setup Mounts
mkdir -p /mnt/gentoo
mount LABEL=GentooRoot /mnt/gentoo/
# Create btrfs subvolumes accordingly your needs
btrfs su cr /mnt/gentoo/{@,@home,@.snapshots,@usr,@opt,@srv,@db,@log,@tmp,@crash,@spool,@portage,@NetworkManager,@binpkgs,@distfiles,@boot}
umount -l /mnt/gentoo
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
Download your preferred openrc stage3 file and verify its integrity{#4}
Some LLVM/musl Stages may not work
cd /mnt/gentoo
wget stage3-amd64-hardened-openrc-xxxx.tar.xz
wget stage3-amd64-hardened-openrc-xxxx.tar.xz.asc
gpg --import /usr/share/openpgp-keys/gentoo-release.asc
gpg --verify stage3-amd64-<release>-<init>.tar.xz.asc
# Once verified, extract it
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt/gentoo
Configuring portage
nano /mnt/gentoo/etc/portage/make.conf
COMMON_FLAGS="-march=native -O2 -pipe"
ACCEPT_LICENSE="*"
FEATURES="${FEATURES} getbinpkg"
FEATURES="${FEATURES} binpkg-request-signature"
Copy DNS info
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
Preparing for 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}"
Configure the system
# Fetch the latest snapshots
emerge-webrsync
# Setting up for binary packages
getuto
# Pick the nearest mirrors
emerge --ask --verbose --oneshot app-portage/mirrorselect
mirrorselect -i -o >> /etc/portage/make.conf
# Update the Gentoo ebuild repository
emerge --sync
# Choose your preferred openrc profile (Some LLVM/musl profiles may not work)
eselect profile list
[21] default/linux/amd64/23.0/hardened (stable) *
eselect profile set 21
# Enable cpu specific optimizations
emerge --ask --oneshot app-portage/cpuid2cpuflags
cpuid2cpuflags
echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpu-flags
# Update the @world set
emerge -avuDUg @world
# Review & remove obsolete packages
emerge --ask --pretend --depclean
emerge --ask --depclean
# Install your preferred text editor
emerge --ask app-editors/nano
Set up localizations
nano /etc/locale.gen
en_US.UTF-8 UTF-8
locale-gen
eselect locale list
[4] en_US.utf8 *
eselect locale set 4
ln -sf /usr/share/zoneinfo/YourRegion/City /etc/localtime
env-update && source /etc/profile && export PS1="(chroot) ${PS1}"
Configure installkernel for initramfs
echo "sys-kernel/installkernel dracut" >> /etc/portage/package.use/installkernel
Install some required packages
emerge --ask sys-kernel/linux-firmware sys-firmware/sof-firmware sys-fs/btrfs-progs sys-fs/cryptsetup sys-kernel/installkernel
Configure dracut
nano /etc/dracut.conf
hostonly="yes"
hostonly_mode=strict
add_dracutmodules+=" crypt "
Installing a distribution kernel
emerge --ask sys-kernel/gentoo-kernel-bin
echo 'USE="dist-kernel"' >> /etc/portage/make.conf
Add fsbab mounts
nano /etc/fstab
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 2
Installing some necessary system tools
emerge --ask --autounmask-continue app-admin/sudo app-shells/bash-completion net-misc/networkmanager
# Add sudo privileged user account
useradd -m -s /bin/bash -G audio,video username
passwd username
EDITOR=nano visudo
username ALL=(ALL) ALL
# Set the hostname
echo gentoo > /etc/hostname
Configure the clock options
nano /etc/conf.d/hwclock
clock="local"
clock_systohc="YES"
Configure OpenRC
nano /etc/rc.conf
rc_parallel="YES"
rc_autostart_user="NO"
Configure installkernel for automated efistub booting{#5}
nano /etc/portage/package.accept_keywords/installkernel
sys-kernel/installkernel
sys-boot/uefi-mkconfig
app-emulation/virt-firmware
echo "sys-kernel/installkernel efistub" >> /etc/portage/package.use/installkernel
# And Rebuild the installkernel
emerge sys-kernel/installkernel
mkdir -p /efi/EFI/Gentoo
# Generate initramfs again using installkernel
installkernel -a /lib/modules
Configure kernel parameters
nano /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"
Finalize and reboot
# Create a boot entry
uefi-mkconfig
# If your EFI stub boot isn't working, consider using other boot methods
reboot
Configure Secure Boot{#6}
emerge --ask app-crypt/efitools app-crypt/sbsigntools dev-libs/openssl
Key generation
# Disable secureboot if you haven’t already
dmesg | grep -i "secure" # Checking Secure Boot Status
mkdir -p /etc/efikeys && cd /etc/efikeys
# Saving the current keys
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
# Creating a GUID
uuidgen --random > guid.txt
# Creating new keypairs
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
# Creating signature lists and sign with the created keys
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.esl
# Now combining them with the older keys
cat old_KEK.esl kek.esl > combined_KEK.esl
cat old_db.esl db.esl > combined_db.esl
Enrolling the keys
Reset Secure Boot to setup mode & update the Secure Boot database
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 PK
Enabling Secure Boot
# Remove all unsigned EFI binaries from ESP
rm /efi/EFI/Gentoo/*
# Now sign the module
sbsign --key /etc/efikeys/db.key \
--cert /etc/efikeys/db.crt \
--output "/lib/modules/$(uname -r)/vmlinuz" \
"/lib/modules/$(uname -r)/vmlinuz"
# And generate the module
installkernel
# Verify the EFI Binary & Enable the Secure Boot
sbverify --cert /etc/efikeys/db.crt /efi/EFI/Gentoo/vmlinuz-$(uname -r).efi
Encryption setup with using Clevis
Add the guru repository to install clevis
emerge --ask app-eselect/eselect-repository
eselect repository enable guru && emerge --sync
ACCEPT_KEYWORDS="~amd64" emerge -a app-crypt/clevis
Secure Boot key encryption{#7}
Encrypt the Signature DB and bind it to the TPM PCR
clevis encrypt tpm2 '{"pcr_bank":"sha256","pcr_ids":"0"}' < /etc/efikeys/db.key > /etc/efikeys/db.key.jwe
Now you can store your important keys on the safe place
Automated module signing with an emerge phase hook
Ensure TPM is functioning correctly and the db.crt and db.key.jwe files are accessible from their specified paths, then sbsign should sign the module during the kernel installation
mkdir -p /etc/portage/env/sys-kernel
nano /etc/portage/env/sys-kernel/gentoo-kernel-bin
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"
}
# Script should have execute permissions
chmod +x /etc/portage/env/sys-kernel/gentoo-kernel-bin
# Now rebuild the kernel and verify the EFI binaries
emerge -1 gentoo-kernel-bin
sbverify --cert /etc/efikeys/db.crt /efi/EFI/Gentoo/vmlinuz-$(uname -r).efi
sbverify --cert /etc/efikeys/db.crt /efi/EFI/Gentoo/vmlinuz-$(uname -r)-old.efi
Auto Luks2 unlocking
Check out the Gentoo wiki before proceeding, it may have bugs
clevis luks bind -d /dev/nvme0n1p2 tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,7,9"}'
# Then regenerate the initramfs
installkernel
If you experience any issues during installation, please follow the official Gentoo Linux Installation guide. I used references from Gentoo Wiki and ArchWiki with some minor tweaks myself. I hope you find something helpful.
That should be it! Reboot your system and enjoy Gentoo Linux..
