Installing Gentoo on EFI with LUKS

Installing Gentoo always introduces some pitfalls. This time we focus on EFI.

Prerequisites

Get the installation image on a USB drive or a disc:

dd if=Downloads/install-amd64-minimal-20201206T214503Z.iso of=/dev/sdh bs=4M status=progress

Then activate the network connection on the live installation OS, e.g.:

dhcpcd eth0
ifconfig

Then activate SSH to keep it simple. You can print the keys on the screen to check the connection from your master operating system:

/etc/init.d/sshd restart
ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub

Now connect from your master operating system to the installation environment:

passwd
ssh root@livecd.lan

Now you are ready for the installation.

Formatting the disk

We use fdisk to format the disk like this:

/dev/sda1     2048       6143      4096     2M Linux filesystem
/dev/sda2     6144     268287    262144   128M Linux filesystem
/dev/sda3   268288    1316863   1048576   512M Linux filesystem
/dev/sda4  1316864 1000215182 998898319 476.3G Linux filesystem

We need a small space for the bootloader, a little larger space (128M probably not necessary) for the EFI partition in vfat (FAT32) and enough space for a possible boot partition (can come handy). The rest will be our encrypted LUKS environment where we keep the partitions and swap.

Now we still need to format the partitions:

mkfs.fat -vvv -F32 /dev/sda2

cryptsetup luksFormat -c aes-xts-plain64 -s 256 /dev/sda4
cryptsetup luksOpen /dev/sda4 lvm

lvm pvcreate /dev/mapper/lvm  
vgcreate vg0 /dev/mapper/lvm  
lvcreate -L 120G -n root vg0  
lvcreate -L 50G -n var vg0  
lvcreate -l 100%FREE -n home vg0

mkfs.ext4 /dev/mapper/vg0-root  
mkfs.ext4 /dev/mapper/vg0-home
mkfs.ext4 /dev/mapper/vg0-var

mkdir /mnt/gentoo
mount /dev/mapper/vg0-root /mnt/gentoo

mkdir /mnt/gentoo/home
mount /dev/mapper/vg0-home /mnt/gentoo/home

mkdir /mnt/gentoo/var
mount /dev/mapper/vg0-var /mnt/gentoo/var
cd /mnt/gentoo/

Install the root file system

Find the current hardened stage3 on the gentoo downloads menu, copy the link and get it using wget inside the live installation system:

wget https://mirror.bytemark.co.uk/gentoo//releases/amd64/autobuilds/current-stage3-amd64/hardened/stage3-amd64-hardened+nomultilib-20201206T214503Z.tar.xz

Then unpack it:

tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner

Then we edit the following file:

nano -wc /mnt/gentoo/etc/portage/make.conf

We add the line to the end:

MAKEOPTS="-j13"
EMERGE_DEFAULT_OPTS="--jobs 8 --load-average 5.2 --quiet-build=n"

Then we continue:

mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf
mkdir --parents /mnt/gentoo/etc/portage/repos.conf
cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf

Get into the chroot

cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
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  
chroot /mnt/gentoo /bin/bash

# Inside chroot
source /etc/profile
export PS1="(chroot) ${PS1}"

Don’t forget to mount boot (yes, the vfat formatted second partition) now:

mount /dev/sda2 /boot

Make sure your partitions look like this:

(chroot) livecd / # lsblk -f
NAME           FSTYPE      FSVER LABEL                        UUID                                  FSAVAIL FSUSE% MOUNTPOINT
loop0          squashfs                                                                                                    
sda                                                                                                                        
├─sda1                                                                                                                     
├─sda2         vfat                             C98F-1027                                 126M     0% /boot
├─sda3                                                                                                                     
└─sda4         crypto_LUKS                      556886ca-16fd-4934-9f11-7273969df178                  
 └─lvm        LVM2_member                      2Ra93y-9vBX-GX8Y-Jvym-qgUM-agF8-hA65Ix                
   ├─vg0-root ext4                             f3a85b65-2a40-40d6-9497-412c78fe1edd    110.5G     1% /
   ├─vg0-var  ext4                             7ad1868c-80f7-47b5-ba82-4290ef0d3789     46.4G     0% /var
   └─vg0-home ext4                             9a4218ac-4554-4412-8bf9-31d41a69cc1f    285.1G     0% /home

Download the latest portage tree:

emerge-webrsync

Select a profile:

eselect profile list
eselect profile set 12 # default/linux/amd64/17.1/no-multilib/hardened

To configure the system with the optimal CPU flags we need to know them. If you are not sure which one you should use, leave them either empty or choose them via cpuid2cpuflags:

emerge --ask app-portage/cpuid2cpuflags
cpuid2cpuflags

Now configure the system via make.conf file:

nano -wc /etc/portage/make.conf

Add these lines to your config, change them according to your setup:

# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.
COMMON_FLAGS="-O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"

# NOTE: This stage was built with the bindist Use flag enabled
PORTDIR="/var/db/repos/gentoo"
DISTDIR="/var/cache/distfiles"
PKGDIR="/var/cache/binpkgs"

# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C

MAKEOPTS="-j13"
EMERGE_DEFAULT_OPTS="--jobs 8 --load-average 5.2 --quiet-build=n"

GENTOO_MIRRORS="https://ftp.halifax.rwth-aachen.de/gentoo/"

USE="-bindist X a52 aac acl acpi alsa bzip2 cdr cli -consolekit cracklib crypt cups dbus dts dvd dvdr elogind exif fam ffmpeg firefox flac gdbm gif glamor gpm hardened iconv icu ipv6 java jack jpeg kde kipi lcms ldap libnotify mad mng modules mp3 mp4 mpeg multitarget ncurses networkmanager nls nptl ogg opengl openmp pam pango pcre pdf phonon plasma png policykit ppds pulseaudio qml -qt4 qt5 readline sdl seccomp semantic-desktop session spell sse sse2 ssl startup-notification svg -systemd tcpd threads tiff truetype udev udisks unicode upower usb v orbis widgets wifi wxwidgets x264 xattr xcb xcomposite xinerama xml xscreensaver xv xvid zlib"
CPU_FLAGS_X86="aes avx avx2 f16c fma3 mmx mmxext pclmul popcnt rdrand sse sse2 sse3 sse4_1 sse4_2 ssse3"

ACCEPT_KEYWORDS="~amd64"

VIDEO_CARDS="intel i965 iris"
LINGUAS="en de"
L10N="en en-GB de"

# For Developing in C, valgrind against libc, split debug infos in separate files:
FEATURES="$FEATURES splitdebug"

Before we start we pull some admin tools which start logging the stats while doing the first large system build:

emerge -av metalog eix genlop gentoolkit portage-utils genkernel grub

Now we have a useful system configuration. Next, we update our system to make use of all USE-flags we enabled and disabled:

emerge --ask --verbose --update --deep --newuse @world

This can take some time and now is a good time to get some coffee or to do something else.

Now you can create a root password:

passwd root

Then you build a kernel you can use:

genkernel --luks --lvm --symlink all

Then you should have a working kernel in /boot. Finally, run grub to make the system and kernel bootable:

grub-install /dev/sda && grub-mkconfig -o /boot/grub/grub.cfg

Then you can reboot the system.