This is a guide for future reference, written as I was installing Gentoo to keep track of the different steps.
After years of using Ubuntu (2014‑2018), my C/C++ up‑bringing has forced me to seek a more minimal and optimized distro. I’ve switched to Arch and never looked back since. The package manager and the dependency issues after each pacman -S ? made me rethink my life choices. So I decided to try Gentoo.
Preparation & Installation Medium¶
Download the desired ISO and dd it to the USB key (use lsblk to find the device):
# /dev/sdc not /dev/sdc1
dd if=install-amd64-minimal-{some date}.iso of=/dev/sdc bs=8192kI recommend the LiveGUI edition to avoid a frustrating start with Wi‑Fi/Network setup. If you still prefer the minimal installation medium, you can set up Wi‑Fi as follows:
# get the wifi device (wlp170s0 in my case)
ifconfig
# activate the interface
ip link set dev wlp170s0 up
echo ctrl_interface=/run/wpa_supplicant >> /etc/wpa_supplicant/wifi.conf
echo update_config=1 >> /etc/wpa_supplicant/wifi.conf
wpa_passphrase your_ssid your_password >> /etc/wpa_supplicant/wifi.conf
# connect using the creds
wpa_supplicant -B -i wlp170s0 -c /etc/wpa_supplicant/wifi.conf
# simple ping to check
ping google.comDisk Partitioning¶
To display the current partitions you can use fdisk -l or lsblk. My drive is /dev/nvme0n1.
Use fdisk to clear and create a new partition table:
fdisk /dev/nvme0n1
# p: print table, d: delete partition, g to clear it all.Simple setup¶
| partition | size | goal | fdisk sequence | filesystem |
|---|---|---|---|---|
| /dev/nvme0n1p1 | ~ 512 MB | EFI boot | n → Enter x 2 → +512M → t → 1 for EFI | vfat |
| /dev/nvme0n1p2 | ~ 32 GB | swap | 19 for swap | swap |
| /dev/nvme0n1p3 | ~ 320 GB | linux root | – (type is implied) | ext4 |
| /dev/nvme0n1p4 | ~ ? GB | linux home | – (type is implied) | ext4 |
Using RAID‑1¶
There are 2 types of hard drives:
Drives that have failed
Drives that have not failed yet
As the saying goes in Morocco: The person who gets bitten by a snake becomes scared of ropes. So now we need a safety hack for drive failures.
I set up redundant array based on software RAID-1 for the root and home partitions: both drives (nvme0,nvme1) would contain a partition pair (same size), and we need to create virtual partitions that will mirror the redundant pair as one.
Load the RAID‑1 module and create block‑device nodes:
modprobe raid1 # load module
mknod /dev/md1 b 9 1 # /root
mknod /dev/md2 b 9 2 # /homeCreate matching partitions on both disks (Linux RAID type – GPT code 42) and assemble them with mdadm:
# metadata: 0.90 (old kernels) or 1.20 (recommended)
mdadm --create --verbose --level=1 --metadata=1.2 --raid-devices=2 \
--name=root --homehost=ghriss /dev/md1 /dev/nvme0n1p3 /dev/nvme1n1p3
mdadm --create --verbose --level=1 --metadata=1.2 --raid-devices=2 \
--name=home --homehost=ghriss /dev/md2 /dev/nvme0n1p4 /dev/nvme1n1p4Watch the parity sync:
watch -n 1 cat /proc/mdstatWhen finished, save the RAID configuration for later use:
mdadm --detail --scan >> /tmp/mdadm.confFormats and mount paths¶
Use the following naming convention to keep things clear (non‑RAID or RAID):
| Device | Mount point | Filesystem |
|---|---|---|
/dev/sda1 | /boot | vfat |
/dev/sda2 | / | ext4 |
/dev/sda3 | /home | ext4 |
/dev/sda4 | none (swap) | swap |
Apply the filesystems:
mkfs.vfat -F 32 /dev/sda1
mkfs.ext4 /dev/sda2
mkfs.ext4 /dev/sda3
mkswap /dev/sda4
swapon /dev/sda4 # enable swappingMount the root and home filesystems:
mkdir -p /mnt/gentoo # create target tree
mount /dev/sda2 /mnt/gentoo/
mkdir /mnt/gentoo/home
mount /dev/sda3 /mnt/gentoo/homeVerify the layout with lsblk:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 423.5M 1 loop /mnt/livecd
...
sda 259:0 0 953.9G 0 disk
├─sda1 259:1 0 512M 0 part
├─sda2 259:2 0 320G 0 part /mnt/gentoo
├─sda3 259:3 0 580G 0 part /mnt/gentoo/home
└─sda4 259:4 0 32G 0 part [SWAP]Preparing Gentoo Root¶
Now we’re ready to get all the necessary base files to start the journey.
Start by setting up the time, assuming we got network access
chronyd -q
# display time
dateWe move to the (future) root directory and choose a stage tarball. I went with Stage 3 Desktop-OpenRC.
cd /mnt/gentoo
# terminal browser, go to downloads
links https://www.gentoo.org/downloads
# file: stage3-amd64-desktop-openrc...tar.xz
# unpack while preserving namespaces and ownerships
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-ownerSelect mirrors
mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.confCreate the ebuild repository config
cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.confCopy DNS settings
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/Bind Linux directories to the new root: these contain nodes of the processes and devices
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/runIf using RAID:
cp /tmp/mdadm.conf /mnt/gentoo/etc
Chrooting¶
Change the root directory to /mnt/gentoo:
chroot /mnt/gentoo /bin/bash
source /etc/profile
# add chroot to terminal to distinguish non-chroot
export PS1="(chroot) ${PS1}"
# Mount the boot partition
mount /dev/sda1 /bootTMPFS (optional)¶
I’ve noticed that my failed drive had #writes = 3 x #reads. Probably due the swapping and caching. For the caching, we can use RAM via tmpfs to reduce IO on SSD and accelerate compilation:
mount -t tmpfs tmpfs /tmp
# /var/tmp/portage used by package manager for caching and build files
mount -t tmpfs tmpfs /var/tmpPortage - Gentoo’s Package Manager¶
Here is how I understand it: instead of providing binaries or pre-packaged files, Portage deals in ebuilds, which are compilation scripts of different packages. Each ebuild (package) has:
0-? USE flags to configure the compilation,
a slot: in case we need different versions of the same package, they should use different slots,
keywords: the architecture of the
ebuild
To merge a package (install) you use emerge $PACKAGE. Each package belongs to a category that is useful to distinguish policy/configuration packages. We can see the use flags of a package via equery uses grub (included in gentoolkit), some are enabled by default (++ vs --).
To manipulate USE flags:
Set global USE flags via
/etc/portage/make.conf:USE="-gtk sensors"to disablegtkand enablesensorsfor all packages.Set per-package USE flags via
/etc/portage/package.use/*.conf.
Example: to compile a minimal libsndfile and disabled pulseaudio for mpg123:
#/etc/portage/package.use/media.conf
media-libs/libsndfile minimal
media-sound/mpg123 -pulseaudioWe start by refreshing the ebuild repo. This will download the ebuild into categories listed in /var/db/repos/gentoo:
# update ebuild repository
emerge --syncGentoo has a news medium to push critical messages. Use eselect news to manage it (list, then read 1 | less). After syncing the repo the previous command you might get news items need reading. I’m already loving this, it feels like Agent 47 getting new intel. It’s time to pick a profile (mission).
Portage configuration¶
The profile is the foundation of Gentoo’s USE flags, it sets the base USE and CFLAGS/CXXFLAGS (C/C++ compilation settings).
Select a profile using
eselect profile list. I’ll go for the default (OpenRC) KDE Plasma.
# default/linux/...desktop/plasma
eselect profile set 9We can see the default profile using
eselect profile show. It’s a symlink to your choice from the profiles database located at/var/db/repos/gentoo/profiles/and its files (plasma) at subfoldertargets/desktop/plasma. These are not to be edited.Use
portageq envvar USEto see the current list of use flags.Open
/mnt/gentoo/etc/portage/make.confand add-march=nativetoCOMMON_FLAGS. This is telling portage to use the native architecture.Add some optimization flags (recommended) as
CPU_FLAGS_X86usingapp-portage/cpuid2cpuflags. Before you go for the first merge, you might want to add some USE options to avoid re-merging.
#/etc/portage/make.conf
CPU_FLAGS_X86="...."
# set for your video card
VIDEO_CARDS="intel"
# Used by grub later
GRUB_PLATFORMS="efi-64"
# Accept all licenses.
ACCEPT_LICENSE="*"
# no pipewire or gnome stuff, these options are cummulative
USE="-gnome -gtk -systemd -pipewire bluetooth context jack lm-sensors networkmanager python sddm"
# languages
L10N="ar en fr ja ko la zh zh-CN zh-TW"Let’s start by installing all the system packages of this set, it might take a while... Welcome to Gentoo!
# first emerge
emerge --ask --verbose --update --deep --newuse @worldLocales and Time¶
Set locales:
# list timezones : ls /usr/share/zoneinfo
echo "Europe/Paris" > /etc/timezone
rm /etc/localtime
emerge --config sys-libs/timezone-data
# configure locale
nano -w /etc/locale.gen
locale-gen
# choose system wide locale
eselect locale list
eselect set 6
env-update && source /etc/profile && export PS1="(chroot) ${PS1}"Pause¶
This took a while. It’s quite stressful to go down a long path with no assurance of making it. I was rethinking my life choices when I’ve randomly stumbled upon the following comment on Reddit:
And with your skills forged by the flames, once you return to beginner pastures, you will find yourself confused by their simplicity. You will seek to dive into the guts of their tools and find all possible knobs and dials to adjust, simply because you are now able to guess how the system works from first sight alone, and you want to make sure that it works as predictably as you anticipate. And realizing how little control over your environment you have now, you may seek to return to the darkness once more.
Kernel¶
We need the source code of a kernel, we can use the official gentoo-sources package or any other repository. Gentoo will look for the sources at /usr/src/linux-?. We use eselect kernel to choose where the symlink /usr/src/linux points to, which will be used by default for the compilation.
# Install sources
emerge --ask sys-kernel/gentoo-sources
# Or alternative sources (e.g., Intel LTS)
# ...
# Select kernel
eselect kernel list
# Available kernel symlink targets:
# [1] linux-6.1.28-gentoo *
# [2] linux-intel-ltsThe Easy Way: Distribution Kernel¶
Using a generic kernel configuration. This provides a generic kernel configuration saved in /boot/config-*-gentoo-dist which we can start from for any subsequent customization.
# you need to add the corresponding license in /etc/portage/package.license
emerge --ask sys-kernel/linux-firmware
# install distribution kernel
emerge --ask sys-kernel/gentoo-kernelIn case we need to rebuild the initramfs:
# rebuild initramfs
emerge --ask @module-rebuild
# or reload specific modules
emerge --config sys-kernel/gentoo-kernelThe Serious Way: Genkernel or Manual¶
This is necessary to include RAID-1 in the kernel and not as a loadable module if initramfs is not used. Why?: because loadable modules are saved in the root partition and we need RAID to access the root... duh!
Genkernel¶
We’ll be using genkernel tool to manage the compilation of the kernel.
Configuring genkernel
The default genkernel config is at /etc/genkernel.conf.
INSTALL="no"not to install the files to/boot/install if told to do so.MENUCONFIG="yes"to display the configuration menu.SAVE_CONFIG="yes"to save the new configuration in /etc/kernels.BOOTLOADER="grub2".MAKEOPTS="$(portageq envvar MAKEOPTS)"(Genkernel does not useMAKEOPTSflags frommake.confautomatically).If using RAID:
MDADM="yes"andMDADM_CONFIG="/etc/mdadm.conf".
Using genkernel
Use ‘/’ to search and enable CONFIG_MD_RAID1 inside the menu if using RAID.
genkernel --kernel-config=/boot/config-* \
--kernel-append-localversion="tutorial" \
--install allUse-case: PulseAudio I want to add the settings for Pulseaudio, starting with the current kernel’s config.
genkernel --kernel-config=/boot/config-6.1.28-gentoo-framework11 \
--kernel-append-localversion="framework-pa" \
--install allWe need to enable:
Device Drivers -> Sound card support -> Advanced Linux Sound ArchitectureGeneral setup -> Timers subsystem -> High Resolution Timer Support
Use-case: KVM To enable KVM (Kernel Virtual Machines), we’ll switch to Intel’s sources: linux-intel-lts which enable SR-IOV for the iGPU.
eselect kernel set 2We need to enable Virtualization -> Kernel-based Virtual Machine (KVM) support, Host kernel accelerator, KVM for Intel, and the various Networking and Graphics support options detailed in the Gentoo wiki or Intel documentation.
Manual Compilation¶
When it comes to compiling your own kernel manually, you can make it.
From within
/usr/src/linux/, you can start with an initial config based on the current loaded kernel from the LiveUSB medium:
# enable modules from lsmod
make localmodconfigEdit the configuration:
make menuconfigYou do not want to change .config directly. Use “/” to start a search, “H” to see the documentation of each config, and check “DEPENDS”.
Compile and Install:
# choose a number of workers to use
make -j8
# install modules
make -j8 modules_install
# install kernel
make installBooting Gentoo¶
We’ll be using Grub 2. First, let’s create our fstab:
Dump all the UUIDs to
fstab:blkid > /etc/fstabClean and adjust the mounts:
# <device> <dir> <type> <options> <dump/pass> <fsck order>
# /dev/sda1
UUID=? /boot vfat defaults,noatime 0 2
# /dev/sda2
UUID=? / ext4 noatime 0 1
# /dev/sda3
UUID=? /home ext4 noatime 0 1
# /dev/sda4
UUID=? none swap sw 0 0
# TMPFS mounts
tmpfs /tmp tmpfs rw,nodev,nosuid 0 0
tmpfs /var/tmp tmpfs rw,nodev,nosuid 0 0
# In case you dual boot windows & you want to have a shared partititon
# Make sure to disable fast startup on Windows to avoid locking the partition
UUID=? /media/shared ntfs auto,user,rw,uid=1000,guid=1000 0 1Install GRUB (
sys-boot/grub) after addingGRUB_PLATFORMStomake.conf(see above) to ensure that it’s compiled with EFI support.If RAID: add
domdadmtoGRUB_CMDLINE_LINUXin/etc/default/grub.
grub-install --target=x86_64-efi --efi-directory=/bootGrub menu should be generated after the kernel installation, and is done via:
grub-mkconfig -o /boot/grub/grub.cfgNetworking & Finalizing¶
The next step is to set up networking packages before we reboot. I recommend you follow Gentoo’s official guide for that because it will depend on your configuration. For me, I use Ethernet... it’s simple:
echo ghriss > /etc/hostname
emerge --ask networkmanagerThe rest of the installation is up to you (Desktop environment, display manager...).
Portage tricks¶
We have the following cycle libsndfile -> mpg123 -> libpulse -> libsndfile.
To break the cycle we set the minimal use flag for libsndfile by adding
media-libs/libsndfile minimal to /etc/portage/package.use/media.conf.
Gentoo has its own “AUR” equivalent. You can also create your own repository of ebuilds.
Learn about portage “sets”. It’s helpful to keep track of world set for the packages that you’ve installed (excludes dependencies).
You can back up
/etc/to a GitHub repo.If you have a home server, you can set it up to compile packages for you to save time on your working PC.