logo
Jiff Slater
🤔 About
✍️ Contact
📚Knowledge
30 Jul 2021
These articles have been archived. You may find them useful but I am no longer offering support for them. Check out my latest articles on plkt.io.
Installing Gentoo in 2020
27 September 2020

I had my once a year conundrum recently – install Gentoo or Ubuntu. This year I chose Gentoo and was immediately awash with nostalgia from seeing this screen.

The last time I ran Gentoo seriously was back in 2008 and now to see this in all its glory really brings me back.

In memory of those good times, I wanted to document the installation process on a modern 2020 PC.  Overall, I would say not much has changed except the availability of systemd as a init option.

Initial setup

I began by downloading the Gentoo minimal install CD. For AMD64 it’s available here.  As with all Gentoo installations it’s wise to have the handbook nearby for support.  It’s available here for AMD64 here.

I burned the CD image to a USB stick using Etcher by Balena.  It’s not my favourite tool but it’s reliably despite the ads.  dd is also another alternative.

Next, I rebooted in the the USB stick via the UEFI boot menu and chose the default Grub menu.  If you have a wired network configured then in most cases the network will already be working and configured with DHCP.

Configuring disks

The hardest part about configuring a fresh installation of Linux is deciding on the storing configuration.  The usual deciding factors are tolerance for risk and available storage devices.  In my case, I have a SSD solely dedicated to Linux and a pair of HDDs for longer term storage.

livecd ~ # lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 390.1M 1 loop /mnt/livecd
sda 8:0 0 1.8T 0 disk 
└─md156 9:126 0 3.8T 0 raid0 
├─md156p1 259:0 0 128M 0 part 
└─md156p2 259:1 0 3.8T 0 part 
sdb 8:16 0 1.8T 0 disk 
└─md156 9:126 0 3.8T 0 raid0 
├─md156p1 259:0 0 128M 0 part 
└─md156p2 259:1 0 3.8T 0 part 
sdc 8:32 0 460.8G 0 disk 
├─sdc1 8:33 0 512M 0 part 
├─sdc2 8:34 0 244M 0 part 
└─sdc3 8:35 0 460G 0 part 
sde 8:64 1 14.6G 0 disk 
├─sde1 8:65 1 427M 0 part /mnt/cdrom
└─sde2 8:66 1 6.4M 0 part 
sr0 11:0 1 1024M 0 rom

Here you can see I have two 2TB drives already in RAID from an existing Linux installation, the USB stick mounted at /mnt/cdrom and the rootfs for the livecd mounted at /mnt/livecd.

For the filesystem, I usually select btrfs for the SSD and btrfs in RAID1 for the HDDs.  This gives me the best balance of recoverability, reliability, and performance for my usecases.  However, because I’m curious to try some of the latest technology this time round I’m going btrfs across all my drives.

Here’s the storage configuration:

Configuring the SSD

First before partitioning I usually erase the SSD.  I have more than normal faith in the ATA secure erase or NVMe secure erase and commonly use it before partitioning drives.  hdparm -I /dev/<drive> quickly tells me what my options are.   In case I’m told my drive is frozen, a quick hotplug (while the computer is on) will unfreeze the device so you can send the secure erase command.  I also had to make sure that the BIOS had the drives connected using AHCI.

Next I set up the partition table.  MBR with DOS disklabel is deprecated (and has been for a while) so I’ll use GPT.  I want the disk to be bootable in any case so I usually use a /boot partition that’s unencrypted, along with EFI and rootfs partitions.  This setup can be changed later to a completely encrypted drive with boot USB.

After the partition table was created, it looked something like this:

livecd ~ # fdisk -l /dev/sdc
Disk /dev/sdc: WW GiB, XX bytes, YY sectors
Disk model: WDC WXXXXXXXXX
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: ZZ-ZZ-ZZ-ZZ-ZZ

Device Start End Sectors Size Type
/dev/sdc1 2048 1050623 1048576 512M EFI System
/dev/sdc2 1050624 1550335 499712 244M Linux filesystem
/dev/sdc3 X Y Z 450G Linux filesystem
/dev/sdb4 X Y Z 32G Swap

mkfs.fat -F32 /dev/sdc1 (for the EFI system partition)

mkfs.ext2 /dev/scdc2 (for the boot partition)

Next I’ll turn the last partition into a LUKS container by using the cryptsetup command.  Read more about LUKS here.

First the performance of the disk is evaluated by using cryptsetup benchmark.  From the results and my risk profile, I can choose the configuration that makes the most sense for you.

cryptsetup --key-size 512 --hash whirlpool --iter-time 5000 --use-random --cipher aes-xts-plain64 --pbkdf-memory=4194304 --pbkdf=argon2id luksFormat /dev/sdc3
cryptsetup luksOpen /dev/sdc3 xtsroot

Next, I’ll set up btrfs on the encrypted root filesystem.

mkfs.btrfs -L broot /dev/mapper/xtsroot

I created a btrfs block device with label broot.  Next, I mounted it with light compression turned on along with disk quotas.  I made sure to have the rootfs and storage directories beneath the toplevel directory for ease of snapshots.

mkdir /toplevel
mount -o compress=lzo /dev/mapper/xtsroot /toplevel
# btrfs quota enable /toplevel # we will not be enabling this yet.
btrfs subvolume create /toplevel/rootfs
btrfs subvolume create /toplevel/rootfs/gentoo
btrfs subvolume create /toplevel/savestate
btrfs subvolume create /toplevel/storage
btrfs subvolume create /toplevel/storage/home
btrfs subvolume create /toplevel/storage/home/user
mount -o subvol=/rootfs/gentoo,compress=lzo /dev/mapper/xtsroot /mnt/gentoo

Finally, I turned on swap from the filesystem I made earlier.

mkswap /dev/sdc4
swapon /dev/sdc4

Installing Gentoo

Before continuing I made sure the date is correct – date.  In most cases, it will already be set correctly.  Next, I downloaded the multilib tarball from the Gentoo’s website.

wget https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds/20200920T214503Z/stage3-amd64-systemd-20200920T214503Z.tar.xz \
wget https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20200923T214503Z.tar.xz.CONTENTS.gz \
wget https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20200923T214503Z.tar.xz.DIGESTS \
wget https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20200923T214503Z.tar.xz.DIGESTS.asc
tar xpvf stage3-amd64-systemd-20200920T214503Z.tar.xz --xattrs-include='*.*' --numeric-owner
nano -w /mnt/gentoo/etc/portage/make.conf

For my compilation options, I chose the following: MAKEOPTS=”-j2″; EMERGE_DEFAULT_OPTS=”–jobs=3″; and COMMON_FLAGS=”-Ofast -flto -pipe -march=native -funroll-loops”.

Next, I continued following the guide by selecting mirrors and the ebuild repository.  Finally, I chrooted into the new directory as per the Gentoo handbook.

For my profile, I opted to use default/linux/amd64/17.1/systemd. Next I set my default Python interpreter to python 3.7 by adding the lines below to /etc/portage/package.use

*/* PYTHON_TARGETS: python3_7
*/* PYTHON_SINGLE_TARGET: -* python3_7

# For systemd, I added some specific use flags +cryptsetup +homed +pkcs11 +policykit and for python I added sqlite as a dependency.

After this I issued “emerge –ask –verbose –update –deep –newuse @world“.  I commonly check the default USE flags for the profile before going further – it’s stored in /var/db/repos/gentoo/profiles/* and more information here.

Furthermore, when I need to check the current Portage configuration it’s just a “emerge –info“ away.  The Gentoo wiki page also serves as a helpful reference.

For the kernel, I followed the handbook and made sure I had the following functionality:

I also added the following to my bootflags kernel command line:

Next, for the initramfs I opted to use genkernel and I used the following configuration.

genkernel --lvm --mdadm --bcache  --btrfs --e2fsprogs --dmraid --bootloader=grub2 --luks --busybox --install --kernel-config=/usr/src/linux/.config initramfs

For configuring systemd and grub2 you’ll need to add the following to /etc/default/grub

GRUB_CMDLINE_LINUX="init=/lib/systemd/systemd crypt_root=<device> dobtrfs"

Remember to specify the UUID of the real_root in GRUB_DEVICE and to uncomment GRUB_TERMINAL=console if you want to see errors during bootup.

I usually compile two kernels – one custom configured by me and the other by genkernel in case I get stuck.  Also in the modern day and age, there’s no region to configure any framebuffers, so at best I only set the EFI framebuffer and simple framebuffer kernel option.

genkernel --kernel-append-localversion=-custom all
grub-mkconfig -o /boot/grub/grub.cfg

Once finished, I rebooted, selected the new entry in Grub, entered my password for my encrypted root drive, and immediately started emerging Firefox.

Welcome home!