![Powered by Gentoo Linux](https://www.gentoo.org/assets/img/badges/powered-small.png) This installation guide is still a massive work in progress. I'd recommend that you follow the Gentoo AMD64 Handbook alongside this guide. This guide is essentially my way of documenting how I installed and configured my own Gentoo installation. Feedback is appreciated as I would hate to be misinformed and then spread that misinformation. If you want to provide feedback about this guide, email me at [email protected]. # My Three Goals ## Efficiency I wanted my Gentoo installation to be simple and efficient. Efficiency, to me, is the essence of great computing. I've been plagued with slow software, bloat, and unnecessary features for far too long. I just want a simple system with everything I *need* as my foundation, and some things I *really want* on top of that. ## Security and Safety I wanted my Gentoo installation to be secure. My previous Arch Linux laptop was only secured with my user password and nothing else. It used the legacy boot option and there was no disk encryption of any kind. I also never backed up any of my data on my old system. If the data stored on the laptop ever got corrupted, I would have no way of recovering that data. I changed that with this installation by putting in place periodic backups to ensure I always have another copy of my data. ## Experimentation I wanted to try out and learn about new features which Linux has to offer. You don't realize how much you truly don't know until you start a process like this where almost everything has to be configured from scratch. But, it also gives you the opportunity to experiment and try new things. If it doesn't work, you can figure it out or try something different. Installing Arch Linux was just as eye-opening as installing Gentoo for those exact reasons. Although you can follow everything I did exactly, I'd also encourage you to try out different options. # My Design Choices ## Partitioning Here is how I designed my partitioning scheme: 1. An EFI System Partition (ESP) for storing the files to boot the system. 2. A partition for the root filesystem (rootfs). 3. A partition for the home filesystem. Why did I separate my rootfs and home filesystems into their own separate partitions? I'm mainly doing this because I want to experiment with using a different, potentially unstable file system: F2FS. I also like the idea of there being some separation. ## Filesystems ### ESP - VFAT The UEFI firmware on most motherboards can only read the ESP if it's formatted as a VFAT filesystem. ### Rootfs - XFS I decided to format my rootfs as an XFS filesystem. All of the other Linux distributions I have used previously have used ext4 and I've had no problems with it. I just want to experiment with a different stable filesystem. The most apparent drawback with XFS from my research is that it doesn't support shrinking, or making the partition that it is formatted with smaller. It can only grow in size. I've never had to shrink a partition before, and especially for the rootfs I don't believe I'll need to. In fact, I'll more than likely need to *expand* it. However, it is something to consider if you think you'll need to do that in the future. ### Home - F2FS F2FS, from what I've researched online, can either be really stable or really unstable. Despite that, it can have potential improvements to performance over the very stable and traditional filesystems that a lot of Linux distributions use by default. Since it's been designed for flash-based storage devices, it could lead to better performance on my hardware. I figured that the easiest way to gain my own experience with it is to use it in some part of my system. After all, the only way to know for sure is to try it for yourself. Of all of the places I'd want to use it, the home directory makes the most sense to me because: 1. If I'm primarily going to work within my home directory, creating a lot of reads and writes to disk, it makes sense to me to have the file system with the potential advantage in speed be used for it. 2. Since I'm planning on periodically backing up my home directory already, then the potential for F2FS to corrupt my data due to a power failure is mitigated. Additionally, I've been reading posts from several people who say that they've experienced power failures on their systems and have had no issues with F2FS corrupting their data. I suppose the only way to know for sure is to do it! ### Swap? I decided to not create a swap partition. Instead, I am going to use zswap and a swapfile. I'll explain what both of those things are and how I set them up on my system. ### Encryption The rootfs partition, home partition, and swapfile are encrypted with Linux Unified Key Setup (LUKS). Encryption is especially important on a device like a laptop where it is vulnerable to theft. Any device you own which you frequently use is going to have sensitive information on it. Therefore, it's imperative that you make some attempt at protecting that data. Even if I was installing Gentoo on a desktop, I would still consider using LUKS. Even if I wasn't using Gentoo, I would still consider using LUKS. Even if I wasn't using LUKS, I would consider using LUKS. ## Stage 3 and Profile I decided to install the hardened Stage 3 tarball. ## Booting I originally decided to boot from a Unified Kernel Image (UKI) via an EFI stub. After kernel version 6.6.62, all of the images had a common problem where OpenRC would never enter the default runlevel after going through the sysinit and boot runlevels. It would go straight from booting to shutting down. There were no reports of errors or crashes in any of the logs I checked. I thoroughly examined the configuration files for Dracut and OpenRC. I was stumped as to what could have been causing it. After a couple of months of frustration, I switched to using rEFInd as my boot manager and URGD as the initramfs generator. This setup is very easy to manage and, importantly, it works! ## Networking The only two utilities I need for networking on my Gentoo installation are ConnMan and `wpa_supplicant`. ConnMan is a network manager which runs as a daemon in the background, and `wpa_supplicant` allows ConnMan to use the wireless network interfaces. ## Window Manager I went with X.org as my display server and Openbox as my window manager. I've used dwm and awesomewm before and I really liked both. Openbox, though, has been a great window manager. I wrote some keybindings to imitate some of the behavior of dwm and awesomewm, like moving and resizing windows automatically. The tiling window managers, I feel, are too restrictive in their layouts sometimes. Openbox with dwm-like keybindings provides a nice balance between rigidity and flexibility. # Preparation ## Downloading the Minimal Installation CD The *Minimal Installation CD* is the default method of installing Gentoo. The Minimal Installation CD is an ISO file that contains a minimal Gentoo environment which we can work within to install Gentoo. You can download it by going to [gentoo.org/downloads](https://www.gentoo.org/downloads). Download the Minimal Installation CD which is compatible with the architecture of the system you are installing it to. This guide assumes you will be installing Gentoo on a machine that is 64-bit, which most computers are. If you aren't sure what architecture your target computer is, follow these steps for the operating system which is currently installed on it: * For Windows, press the Windows key and R, type *msinfo32*, press enter, and find where it says *System Type*. If it says *x64-based PC*, that means the system is 64-bit. * For MacOS, click on the Apple logo at the top left, then *About This Mac*, and find where it shows the processor. If the processor isn't an Intel Core Solo or Intel Core Duo, the system is 64-bit. Otherwise, it's 32-bit. * For Linux, run `uname -a`. If the output of the command contains *x86_64*, that means the system is 64-bit. For 64-bit machines, you'll want to download the Minimal Installation CD for *amd64.* > [!note] > If you've ever wondered why operating systems are distributed as ISO files (which are meant for optical media like discs), I found [this post from a Rufus developer](https://superuser.com/questions/1170832/why-are-there-different-options-for-creating-bootable-usb-compared-to-a-cd) which was very insightful. ## Burning the Minimal Installation CD Once the Minimal Installation CD is downloaded (which shouldn't take too long) it will need to be burned onto a removable medium like a CD or a USB drive. By burning it to a removable medium, we can boot into the Minimal Installation CD's environment and install Gentoo on our target system. The program you will use to do this depends on what operating system you used to download the ISO file and what type of removable media you are going to burn the ISO file to. ### Method 1 - If you're using a USB device For Windows, MacOS, and Linux, you can download and run a program called [balenaEtcher](https://etcher.balena.io/). The process for flashing an ISO file with this program is very simple. If you're using Linux and don't want to install an extra program you'll only use once, you also have the option of using `dd` by running: ```bash $ dd if=install-amd64-minimal-<release timestamp>.iso of=/dev/<drive name> bs=4096 status=progress && sync ``` If the `dd` command looks like it isn't doing anything, just leave it alone for a few more minutes. I promise that it is. ### Method 2 - If you're using a CD For Windows 7 and older, you can burn an ISO file to a CD by right clicking on the drive in Explorer and clicking *Burn disk image.* For MacOS, you can use the Disc Utility that's built into the operating system. For Linux, you can use `cdrecord` to burn an ISO file to a CD like so: ```bash $ cdrecord dev=/dev/sr0 install-amd64-minimal-<release timestamp>.iso ``` > [!note] > There are many programs which can burn ISO files to removable drives. I chose balenaEtcher because it has the simplest user interface. Rufus is another alternative if you're on Windows and you're burning the ISO file to a USB drive. If you're already using Linux, then you should be familiar with executing commands like `dd` in the terminal and so it would be redundant to install another program. If the process was successful, you should now have a USB drive or CD that has the official Gentoo installation media ready to use. > [!warning] > Operating systems treat USB drives and CDs differently. Make sure you're not trying to use a program meant for USB devices with a CD, and vice versa. # Booting into the Minimal Installation CD After the installation media has been created, you need to insert it into the target machine and either power it on (if it was turned off), or reboot it (if it was already running). When you see the splash screen for the manufacturer of the computer or the motherboard in the computer, you need to press a specific key or key combination to enter the motherboard's firmware user interface. Within that firmware user interface, you need to find the option that allows you to change the device that is booted from first. On most motherboards, the way you do this is by changing the boot order so that the USB device is attempted first before the internal drives of the computer. On some machines, you can actually pick the specific device to boot from temporarily. > [!example] > On my Lenovo Thinkpad, the boot process can be interrupted by pressing F12 or Enter. Once interrupted, I can press F12 to choose a specific device to boot from. # Setting Up Internet If the target machine is connected to the network via Ethernet, it should automatically configure the connection. If you want to connect your device to the network via Wi-Fi, the easiest way to set it up is to run the `net-setup` command. This is a terminal program which will ask you for the network interface you're configuring, the type of network, the SSID, and the passphrase in order to connect the machine to that network. ## Testing the Connection To verify that you have an Internet connection and that DNS is working, run the `ping` command targeted at some website like so: ``` $ ping -c 3 google.com ``` > [!success] > If it works, you'll see the responses from Google's server. > [!failure] > If it doesn't work, you'll see an error like: > ``` > ping: google.com: Temporary failure in name resolution > ``` > > This could either mean that there's no access to the Internet or that the domain names can't be resolved to IP addresses. # Partitioning Partitioning is the process of separating the continuous block of storage that makes up a storage device into discrete sections that can store a particular part of a Linux system. For instance, the EFI System Partition (ESP) is a partition designed to store the necessary files for booting with a motherboard's Unified Extensible Firmware Interface (UEFI) (like our Unified Kernel Image (UKI) which will be generated automatically later). If there are already partitions with data on the drive, you should back up anything want to keep and then run this command to wipe all file system signatures: ```bash $ sudo wipefs -a /dev/<drive name> ``` After the storage device's filesystem is wiped with `wipefs`, you can use `fdisk`, `cfdisk`, or other similar tools to partition the disk. If you prefer a terminal user interface rather than the interactive prompt that `fdisk` uses, I recommend using `cfdisk`. Once you create the partitions within the partitioning tool of your choice, remember to write the changes to the disk before you exit. > [!example] > On my system, I created three partitions with `cfdisk`: > 1. EFI System 2G in size. > 2. Linux root (x86-64) 80G in size. > 3. Linux home which is the rest of the disk. # Formatting After the disk is partitioned, each partition needs to be formatted with a filesystem. The filesystem is the scheme for how data is going to be stored on a partition. In the beginning, I explained my rationale behind my choices for the filesystems for my rootfs and home partitions. This is where the filesystems are actually being implemented. > [!warning] > These commands for formatting the disk partitions, as well as every other command in this guide, is with my specific setup in mind. Be sure to change the commands to fit what your setup is. The reason why the block device for my drive is called *nvme0n...p...* is because my drive is an NVMe SSD. If your drive was a regular SSD or hard disk drive, it would likely be called something like *sd...* followed by a letter. ## Setting Up LUKS Before we format each of the partitions with a filesystem, we have to set up LUKS on each partition first. This is because setting up LUKS wipes the existing data on the partition. First, make sure the `dm_crypt` kernel module is loaded in the live environment by running: ```bash $ modprobe dm_crypt ``` We're going to use the `cryptsetup` command to set up LUKS for the two partitions. To do so, run these commands: ```bash $ cryptsetup luksFormat /dev/nvme0n1p2 $ cryptsetup luksFormat /dev/nvme0n1p3 ``` For each command, they're going to ask for you to enter a password. This password is used to encrypt the LUKS header for that partition. To open the encrypted partitions and have them mounted for us to be able to write to them, we need to use the `cryptsetup luksOpen` command: ```bash $ cryptsetup luksOpen /dev/nvme0n1p2 root $ cryptsetup luksOpen /dev/nvme0n1p3 home ``` ### Backing Up the LUKS Headers As mentioned on the Gentoo Wiki, the keys or passwords used to set up LUKS are thereafter used to decrypt the LUKS header. The LUKS header is the only thing that can decrypt the data on a LUKS-formatted partition. So, you should back up the LUKS header on another device so that you can recover your data. During my installation, I used `rsync` to copy the headers to my own server. You can also mount a USB drive and copy the headers to them. ```bash $ cryptsetup luksHeaderBackup /dev/nvme0n1p2 --header-backup-file root_headers.img $ cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file home_headers.img $ rsync *.img [email protected]:/home/nate/ ``` ## Making the Filesystems ### ESP The first filesystem, the ESP, needs to be formatted as a VFAT filesystem so it can be read by the UEFI of the motherboard. To do that, you just run: ```bash $ mkfs.vfat -F32 /dev/nvme0n1p1 ``` ### Root Filesystem The two other partitions can be formatted to whichever filesystem you want. I chose XFS and F2FS for my rootfs and home partitions respectively. I'll start with the command I ran to format my rootfs partition as an XFS filesystem: ```bash $ mkfs.xfs -L rootfs /dev/mapper/root ``` Here are the flags and what they mean: * `-L rootfs` - This flag gives the partition a label. The label for my partition is `rootfs`. * `/dev/mapper/root` - This block device represents the unencrypted rootfs partition. ### Home Filesystem Here is the command I ran to format my home partition as an F2FS filesystem: ```bash $ mkfs.f2fs -l homefs -t 1 -o 10 -O extra_attr,compression,encrypt /dev/mapper/home ``` Here are the flags and what they mean: * `-l homefs` - This gives the partition a label. The label for my home partition is `homefs`. * `-t 1` - This turns on trim at the filesystem level for the partition. Trim is an important feature, especially for SSDs (did I mention that this filesystem was created with SSDs in mind?). * `-o 10` - This flag manually sets a percentage of the drive to be used for what is called overprovisioning. Overprovisioning creates a space on the drive for the filesystem to do optimizations and wear-leveling. * `-O extra_attr,compression,encrypt` - The `-O` flag allows you to enable additional features which F2FS supports. * `extra_attr` is a required feature to be able to use the `compression` feature. * `compression` enables you to use a compression algorithm to save on the amount of data being written to the disk. It doesn't change the amount of disk capacity that a file takes, but it does reduce the number of bits that have to be written to the disk. So theoretically, it increases the lifespan of the disk. * `encrypt` enables filesystem-level encryption, which is a nice feature to have enabled just in case. > [!note] > You can read more about these commands here: > * [mkfs.vfat(8) - Linux manual pages](https://www.man7.org/linux/man-pages/man8/mkfs.vfat.8.html) > * [mkfs.xfs(8) - Linux manual pages](https://www.man7.org/linux/man-pages/man8/mkfs.xfs.8.html) > * [mkfs.f2fs(8) - Arch manual pages](https://man.archlinux.org/man/mkfs.f2fs.8) # Mounting Now that the filesystems are prepared to have data written to them, we can mount them. The Minimal Installation CD should already have a directory created at `/mnt/gentoo`. This is the mountpoint where you will mount the block device for the rootfs. Then, you will create the other mountpoints within the rootfs and mount every other block device to them. To do all of this, I ran these commands: ``` $ mkdir --parents /mnt/gentoo $ mount /dev/mapper/root /mnt/gentoo $ mkdir --parents /mnt/gentoo/boot $ mount /dev/nvme0n1p1 /mnt/gentoo/boot $ mkdir --parents /mnt/gentoo/home $ mount -o compress_algorithm=zstd /dev/mapper/home /mnt/gentoo/home ``` > [!warning] > If you enabled any filesystem features when you formatted the block device with the filesystem, like compression for example, be sure to include that feature in the mount command. For instance, since I enabled `compression` on the F2FS for my home directory, I included the option `-o compress_algorithm=zstd` in the mount command. # Stage 3 ## What is a Stage 3 archive? Much like what Arch Linux's `pacstrap` command does, you will download what is called a Stage 3 archive and extract it to the rootfs. This Stage 3 has the directory structure and files needed to get started with the installation process. There are many Stage 3 archive files you can download which all have different features or goals. I decided to download the hardened Gentoo Stage 3 archive with the OpenRC init system. But, you can pick a different Stage 3 archive that aligns with the goals for your system. > [!warning] > These Stage 3 files are regularly released. You should make sure to download the latest version from Gentoo's website and not the version in the command above. I will not be updating that URL when new versions of the hardened Stage 3 are released. ## Downloading the Stage 3 Archive ### Method 1: Use a web browser on another computer Go to https://gentoo.org/downloads on another computer and get the URL for a Stage 3 download. You can use `wget` to download the archive from the URL: ```bash $ wget https://distfiles.gentoo.org/releases/amd64/autobuilds/20241124T163746Z/stage3-amd64-hardened-openrc-20241124T163746Z.tar.xz ``` ### Method 2: Use `links` The Minimal Installation CD comes with a terminal-based browser called `links`. You can navigate a text-only version of the Gentoo website, select a Stage 3 archive download link using the arrow keys, and download one of them by pressing enter. ```bash $ links https://gentoo.org/downloads ``` ### Optional: Verify the Stage 3 archive download If you'd like, you can verify the integrity of the Stage 3 archive using [the steps outlined in the handbook](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Stage#Verifying_and_validating). ## Extracting the Stage 3 Archive This is the command to extract the Stage 3 archive to the rootfs mountpoint at `/mnt/gentoo`: ```bash $ tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt/gentoo ``` Here are the flags and what they mean: * `xpvf` * `x` - Extract the contents of an archive. * `p` - Preserve the permissions within the archive. * `v` - Output verbosely. * `f` - Extract from the archive saved at the file path specified immediately after this flag. * `--xattrs-include='*.*'` - Preserve the extended attributes in all namespaces stored in the archive. * `--numeric-owner` - Preserve the user and group IDs of the files being extracted. * `-C /mnt/gentoo` - Extract the files to the mount point for our rootfs regardless of our current working directory. # Chroot Once the tarball has been extracted, we can switch our root from the root of the Minimal Installation CD to that of our roofs partition (which is currently mounted at `/mnt/gentoo`). ## Ensuring Internet Access To ensure that you will still have a connection to the Internet when you chroot to `/mnt/gentoo`, you should copy the `/etc/resolv.conf` file from the Live CD environment to `/mnt/gentoo/etc/resolv.conf`. The handbook recommends passing the `--dereference` flag in case `/etc/resolv.conf` is a symbolic link. ```bash $ cp --dereference /etc/resolv.conf /mnt/gentoo/etc/resolv.conf ``` ## Chrooting to the Root Filesystem Once the file is copied over, you can use the `arch-chroot` command to chroot to `/mnt/gentoo`, which is where the rootfs is mounted. ```bash $ arch-chroot /mnt/gentoo ``` ### Optional: Change the primary prompt If it helps, you can change the primary prompt to remind you that you're in the chroot environment and not the Live CD environment. However, this is not required. ```bash $ export PS1="(chroot) ${PS1}" ``` # Portage Once we are in our new root environment, we can begin the process of configuring and installing packages to our system. Before we can use Portage however, we need to do some setup for it. ## Syncing Portage comes with a script called `emerge-webrsync`. This script downloads the entire ebuild repository as a snapshot and installs it on the system. The ebuild repository snapshot is released daily, so it should be up to date. ```bash $ emerge-webrsync ``` ## Mirrors To ensure that you're downloading from the fastest (and/or geographically closest) mirrors possible, you can use a tool called `mirrorselect` to select which mirrors you want to download from and automatically configure Portage to use them. ```bash $ emerge --ask --verbose --oneshot app-portage/mirrorselect $ mirrorselect -i -o >> /etc/portage/make.conf ``` ## What is `make.conf`? `make.conf` is the main configuration file for Portage on the global level. Portage uses the settings in this file for every package which is emerged. You can see my `make.conf` file [here](https://natewilliams.xyz/formulations/gentoo/make.conf.html) as an example. You should tweak this file over time as you use your system to find the best settings for your setup. ### Accept License The `ACCEPT_LICENSE` variable in `make.conf` is used to allow or disallow packages with certain software licenses from being installed. To install any package regardless of its license, add the following line to your `make.conf`: ```bash # /etc/portage/make.conf ACCEPT_LICENSE="*" ``` ### Common/C/CXX/FC/FF Flags The Common/C/CXX/FC/FF flag variables are used for adding flags to the compilers for C, C++, and Fortran respectively. Since all packages are built from source code (unless you specifically download a binary version of a package), you have the opportunity to define optimization flags which maximize the performance of the compiled program. These three flags would be added to the `COMMON_FLAGS` variable so that they're used for all compilations. The three flags that you should have at least are: 1. `-O2` - Set the optimization class to level 2. The handbook cautions against setting an optimization class that's higher than level 2 system-wide because it can cause instability and potential issues. 2. `-pipe` - Use pipes for communicating between the different stages of compilation instead of files. 3. `-march=native` - Automatically detect the architecture of the CPU and compile with optimizations for that architecture in mind. > [!example] > The only change I made to my setup was to set the `-march` flag to `znver2` because I know that the AMD Ryzen 5 PRO 4650U, which is the CPU in my Thinkpad, has the Zen 2 microarchitecture. > ```bash > # /etc/portage/make.conf > > # === System-wide compiler flags. === # > COMMON_FLAGS="-O2 -pipe -march=znver2" > > # C/C++. > CFLAGS="${COMMON_FLAGS}" > CXXFLAGS="${COMMON_FLAGS}" > > # Fortran. > FCFLAGS="${COMMON_FLAGS}" > FFLAGS="${COMMON_FLAGS}" > ``` ### Global USE Flags The global USE flags are set via the `USE` variable in `make.conf`. USE flags determine which features in Gentoo are enabled or disabled. The USE flags set in `make.conf` are applied to every package that's emerged. ```bash USE="acpi alsa -apm connman dbus elogind emoji git hardened -iwd jumbo-build udisks unicode strip vaapi vim-syntax vulkan wifi X" ``` Here are the USE flags I have set on my system and why I set them: * `acpi` - Enables support for the Advanced Configuration and Power Interface (ACPI), which is what my system uses. * `alsa` - Enables support for the Advanced Linux Sound Architecture (ALSA). * `-apm` - Disables support for Advanced Power Management (APM), since most systems including mine use ACPI. * `connman` - Enables support for `connman`, which is the network manager I'm using for my system. * `dbus` - Enables `dbus` support for any packages that require it. * `elogind` - Enables session tracking with `elogind`. If you're using Xorg, you need this USE flag enabled so that the server can control the framebuffer when running it as a regular user. * `emoji` - Enables emoji support for any packages that can support it. * `git` - Enables support for `git`. * `hardened` - Enables the default security enhancements for the toolchain. * `-iwd` - Disables the `iwd` wireless daemon. I won't need any support for `iwd` since I'm using `wpa_supplicant`. * `jumbo-build` - When installing `qtwebengine`, `icinga2`, `webkit-gtk`, or `firefox`, combine source files to speed up the build process. This requires more memory, which can be handled by adding another swapfile if necessary. I tried to enable this USE flag because the build for `qtwebengine` kept crashing my system. In the end, however, I opted to install `firefox-bin`. * `unicode` - Enables support for unicode. * `strip` - Allow symbol stripping to be performed by the ebuild for special files. * `vaapi` - Enables the Video Acceleration API for hardware decoding. * `vim-syntax` - When installing a package, add any related VIM syntax scripts. * `vulkan` - Enables support for Vulkan. * `wifi` - Enables wireless network functions. * `X` - Enables support for X11. You can see the full list of every USE flag available on Gentoo in [the Gentoo USE flag index](https://www.gentoo.org/support/use-flags/). ### Makeopts The `MAKEOPTS` variable in `make.conf` is used to set the `-j` (jobs) and `-l` (load average) flags which determine how many compilations should happen in parallel. The handbook recommends setting `-j` to the lesser of two numbers, either: * The number of threads the CPU has. * The total amount of RAM in GB divided by 2. The value for `-l` can be slightly above the value set for `-j`. > [!example] > ```bash > MAKEOPTS="-j6 -l7" > ``` ### Rust Flags Packages written in Rust are already set to use level 3 optimization by default according to the handbook. What the handbook says you can do as well is add the `-C target-cpu=native` codegen flag to the `RUSTFLAGS` variable so that `rustc` will generate code specifically for the architecture of your machine's CPU. > [!example] > ```bash > RUSTFLAGS="${RUSTFLAGS} -C target-cpu=znver2" > ``` ### Video Cards > [!warning] > As of the time I'm writing this part (December 17, 2024), the `VIDEO_CARDS` variable is now deprecated due to [this bug](https://bugs.gentoo.org/922307). The handbook now says to set the video card USE flags within `/etc/portage/package.use`. That will be shown in the next section. ## Per-Package USE Flags USE flags can also be set per package. By setting per-package USE flags, you can enable or disable features in certain packages as needed without affecting the other packages you want to emerge. In certain situations, you have to enable package-specific USE flags in order to satisfy dependencies. Per-package USE flags are defined by adding files to the `/etc/portage/package.use/` directory. ### All Instead of having my package-specific USE flags spread across multiple files, I decided to just add them to a single file saved at `/etc/portage/package.use/all`. The reason I prefer this is just because it makes it easier to navigate. I feel like if everything is spread across multiple files, it's harder to see at a glance what I have enabled or disabled. ### CPU Flags CPU flags are USE flags that enable specific code when set or unset on a package. The specific code that's enabled is compiled into the binary. This is different from the compiler outputting code optimized for a certain CPU feature. > [!example] > The `CPU_FLAGS_X86_SSE2` USE flag would enable handwritten ASM in a package if the package supports it. The best way to define the CPU flags is with the `cpuid2cpuflags` program, provided by the `app-portage/cpuid2cpuflags` package. This program returns a `USE_EXPAND` containing USE flags that enable specific options which are meant for the build system. ``` $ emerge --ask --oneshot app-portage/cpuid2cpuflags $ echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpu-flags ``` ### Video Card [This section of the handbook](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Base#VIDEO_CARDS) has a table for determining how you should set the `package.use` USE flags for a given machine and video card. > [!example] > My Lenovo Thinkpad L15 has an integrated Radeon Vega Series GPU, so these are the USE flags I set: > ```bash > # /etc/portage/package.use/00video_cards > > */* VIDEO_CARDS: amdgpu radeonsi > ``` # Time Zone Assuming that you want the time on your system to match the time for where you live, you'll have to set the time zone. You do this by creating a symbolic link from one of the available time zone data files (tzfiles) in `/usr/share/zoneinfo` to `/etc/localtime`. ```bash $ ls -l /usr/share/zoneinfo $ ls -l /usr/share/zoneinfo/America $ ln -sf /usr/share/zoneinfo/America/<city> /etc/localtime ``` If you want to test if a particular time zone data file is the correct one, you can use the `zdump` command followed by the path to the time zone data file. ```bash $ zdump /usr/share/zoneinfo/America/Los_Angeles /usr/share/zoneinfo/America/Los_Angeles Mon Dec 16 22:29:26 2024 PST ``` > [!warning] > `/etc/localtime` has to be a symbolic link because the time zone identifier is extracted from the symbolic link's target name. It will not work if you copy a file from `/usr/share/zoneinfo` and replace `/etc/localtime` with it. # Locale > [!warning] > This is only applicable if you're not using musl libc. If you're using musl libc, just skip this section. Locales are a collection of specifications which determine character set handling, number formatting, calendar formatting, the language for messages, the language for yes-or-no questions, and many more things. > [!quote] Quote from Chapter 7 of The GNU C Library Reference Manual [(1)](https://www.gnu.org/software/libc/manual/html_node/Locales.html#Locales) > In ISO C, internationalization works by means of *locales.* Each locale specifies a collection of conventions, one convention for each purpose. The user chooses a set of conventions by specifying a locale (via environment variables). > > All programs inherit the chosen locale as part of their environment. Provided the programs are written to obey the choice of locale, they will follow the conventions preferred by the user. To enable certain locales for the system, you need to edit the `/etc/locale.gen` file. Acceptable values to include in this file can be found in the `/usr/share/i18n/SUPPORTED` file. If you're in the United States, the two locales you'd probably want to be enabled are: ```Locale en_US ISO-8859-1 en_US.UTF-8 UTF-8 ``` Regardless, you should have at least one UTF-8 locale enabled because many applications require it to build properly. After the `/etc/locale.gen` file is modified, you'll need to run the `locale-gen` script. The `locale-gen` script reads the `/etc/locale.gen` file and compiles every enabled locale into the binary locale format for us with `localedef`. ```bash $ locale-gen ``` To verify that the locale is now available, check the output of this command: ```bash $ locale -a ``` To set the system-wide locale, use `eselect`: ```bash $ eselect locale list Available targets for the LANG variable: [1] C [2] C.utf8 [3] POSIX [4] en_US [5] en_US.iso88591 [6] en_US.utf8 [7] C.UTF8 * [ ] (free form) $ eselect locale set 2 $ env-update && source /etc/profile ``` # Microcode For Intel processors, you can install microcode updates by emerging the `sys-firmware/intel-microcode`. For AMD processors, microcode updates are included in the `sys-kernel/linux-firmware` package. # Bootloader > [!example] > These are the USE flags for setting up rEFInd as the bootloader and ugRD as the initramfs generator. > ```bash > # /etc/portage/package.use/all > > # Booting. > sys-kernel/gentoo-kernel savedconfig > sys-kernel/installkernel -dracut -generic-uki -grub -systemd-boot ugrd -uki -ukify refind > ``` # Preparing Filesystems ## Setting Up the Filesystem Table (`/etc/fstab`) ```bash # /etc/fstab # <fs> <mountpoint> <type> <opts> <dump> <pass> UUID=10E9-C784 /boot vfat umask=0077 0 0 UUID=4cdce20b-71c8-4977-8b00-d4856b19e47c / xfs defaults,noatime 0 1 UUID=8bc48213-b4c9-4e97-8722-5ea843bc35ee /home f2fs compress_algorithm=zstd,defaults,noatime 0 2 ``` ## Setting Up DM-Crypt ```bash # /etc/conf.d/dmcrypt target=home source=UUID=<UUID of LUKS home partition> [key=...] ``` ```bash $ rc-update add dmcrypt boot $ dmsetup mknodes ``` # Sound ```bash $ sudo emerge -av media-sound/alsa-utils ``` ```bash # /etc/asound.conf defaults.pcm.!card 1 defaults.pcm.!device 0 defaults.ctl.!card 1 ``` # Emojis ```bash $ sudo emerge -av media-fonts/fonts-meta app-i18n/unicode-emoji ``` # Application-Specific ## Obsidian The easiest way to download Obsidian on Linux is to download the AppImage from the website. There are four libraries to install before you can use the AppImage, however: ```bash $ emerge --ask dev-libs/nss x11-libs/gtk+ net-print/cups $ emerge --oneshot sys-fs/fuse:0 ``` # Work In Progress Below! `emerge --ask sys-kernel/linux-firmware` -march=native -march=znver2 `/etc/portage/package.use/uki` ``` sys-apps/systemd-utils boot kernel-install ``` `emerge --ask sys-apps/systemd-utils` `/etc/dracut.conf.d/uki.conf` ``` uefi="yes" ``` `emerge --ask sys-kernel/installkernel` Configuring the installkernel with those flags will automatically also emerge the packages. Install ``` emerge --ask sys-boot/shim sys-boot/efibootmgr sys-boot/uefi-mkconfig sys-fs/cryptsetup sys-kernel/dracut sys-kernel/installkernel emerge --ask --config sys-kernel/gentoo-kernel ``` Copying the shim EFI files to our ESP partition so that `uefi-mkconfig` can boot from them, allowing Secure Boot. ``` cp /usr/share/shim/BOOTX64.efi ${ESP}/EFI/Gentoo/shimx64.efi cp /usr/share/shim/mmx64.efi ${ESP}/EFI/Gentoo/mmx64.efi ``` `/etc/dracut.conf` Adding lz4hc allows for zswap to be used in the system. ``` hostonly="yes" add_drivers+=" lz4hc lz4hc_compress " ``` Add to Dracut's configuration for luks `/etc/dracut.conf.d/luks.conf` ``` add_dracutmodules+=" crypt " kernel_cmdline+=" root=UUID=<LUKS UUID of root partition> rd.luks.uuid=<UUID of root partition> rd.luks.uuid=<UUID of home partition> rd.luks.allow-discards zswap.enabled=1 zswap.compressor=lz4 " ``` I had to add more options to my `/etc/dracut.conf`, create a `/etc/fstab`, and add the options to `/etc/conf.d/dmcrypt` to open my encrypted partitions. `/etc/conf.d/dmcrypt` ``` target=home source=UUID=... [key=...] ``` [dm-crypt - Gentoo wiki](https://wiki.gentoo.org/wiki/Dm-crypt#Configuring_fstab) ``` rc-update add dmcrypt boot dmsetup mknodes ``` Basically, I'm pretty sure that Dracut can only use LUKS to decrypt the root partition if it is encrypted, it can't do the other partitions. So, you can define the root partition in the dracut.conf file, then you have to use the unencrypted UUID in fstab, the encrypted file in crypttab, and define it in conf.d/dmcrypt `/etc/local.d/zram.start` ``` #!/bin/bash modprobe zram SIZE=6144 echo $(($SIZE*1024*1024)) > /sys/block/zram0/disksize mkswap /dev/zram0 swapon /dev/zram0 -p 10 ``` `/etc/local.d/zram.stop` ``` #!/bin/bash swapoff /dev/zram0 echo 1 > /sys/block/zram0/reset modprobe -r zram ``` `chmod +x /etc/local.d/zram.start /etc/local.d/zram.stop` Installing connman, you need to add the connman use flag at the beginning. That would have made it so much easier. If you don't, you have to add connman -iwd to the USE flags variable in make.conf and then run `emerge -a`. Just by installing connman and wpa_supplicant, WiFi worked when I used connmanctl to connect. I got zswap to work by enabling it with an OpenRC script at boot, ``` cd /opt fallocate -l 10GiB swapfile chmod 600 swapfile cryptsetup --type plain -d /dev/urandom open swapfile swap mkswap /dev/mapper/swap swapon /dev/mapper/swap ``` Add this line to `/etc/conf.d/dmcrypt` ``` swap=swap source=/opt/swapfile options='--type plain --key-file /dev/urandom' ``` `rc-update add dmcrypt boot` `emerge --ask x11-wm/openbox` # BIG FUCKING BREAKTHROUGH If dracut keeps on using the /dev/mapper/root to try and boot from, you should add this setting to the dracut.conf: ``` persistent_policy="by-uuid" ``` This changes it so that dracut uses the UUID of the device and not the mapped name for root, which it uses by default. ALSO: `uefi-mkconfig` will only use the shim file if the filename contains the substring `shim`. So, you should copy it like this into your EFI directory: ``` cp /usr/share/shim/BOOTX64.EFI /efi/EFI/systemd/shimx64.efi ``` # I GOT THE SOUND TO WORK I had to add these lines to `/etc/asound.conf`: ``` defaults.pcm.!card 1 defaults.pcm.!device 0 defaults.ctl.!card 1 ``` To get emojis and other symbols to work in the terminal, I installed these packages: In kitty, I set the symbol_map setting to be th * Building using saved configfile "/etc/portage/savedconfig/sys-kernel/gentoo-kernel-6.12.25" * Your configuration for sys-kernel/gentoo-kernel-6.12.25 has been saved in * "/etc/portage/savedconfig/sys-kernel/gentoo-kernel-6.12.25" for your editing pleasure. * You can edit these files by hand and remerge this package with * USE=savedconfig to customise the configuration. * You can rename this file/directory to one of the following for * its configuration to apply to multiple versions: * ${PORTAGE_CONFIGROOT}/etc/portage/savedconfig/ * [${CTARGET}|${CHOST}|""]/${CATEGORY}/[${PF}|${P}|${PN}] ```bash $ dd if=/dev/urandom of=/home.key bs=1 count=64 $ chmod 0400 /home.key $ cryptsetup luksAddKey /dev/sda3 /home.key ``` # Packages These are the packages I installed: * Administration. * `app-admin/sudo`. * Booting. * `sys-fs/cryptsetup`. * `sys-kernel/ugrd`. * `sys-boot/refind`. * `sys-boot/efibootmgr`. * Display (X11). * `x11-base/xorg-server`. * `x11-apps/xinit`. * `x11-apps/xrandr`. * `x11-wm/openbox` - This is my preferred window manager. * Drivers. * `sys-kernel/linux-firmware`. * `x11-drivers/nvidia-drivers`. * Gentoo. * `app-eselect/eselect-repository`. * Graphical programs (X11). * `media-fonts/fonts-meta`. * `appi18n/unicode-emoji`. * `x11-terms/kitty` - This is my preferred graphical terminal. * `www-client/firefox-bin` - This is my preferred web browser. I know that Firefox is somewhat controversial nowadays. * Kernel. * `sys-kernel/installkernel`. * `sys-kernel/gentoo-sources`. * `sys-kernel/gentoo-kernel`. * Networking. * `net-wireless/wpa_supplicant`. * `net-misc/connman`. * Tools. * `dev-vcs/git`. `x11-misc/xdg-user-dirs` # Users It's not recommended to use your computer with just the root user on a daily basis. You should create a user account for yourself. ## XDG Base Directory Specification The XDG Base Directory Specification is a specification which defines base directories, or directories which should be searched for particular files, that hold user-specific files. ```bash # /etc/profile.d/xdg.sh export PATH="${PATH}:${HOME}/.local/bin" export LD_LIBRARY_PATH="${HOME}/.local/lib:${LD_LIBRARY_PATH}" export XDG_CACHE_HOME="${HOME}/.cache" export XDG_CONFIG_HOME="${HOME}/.config" export XDG_DATA_HOME="${HOME}/.local/share" export XDG_STATE_HOME="${HOME}/.local/state" export XDG_DATA_DIRS="/usr/local/share:/usr/share" export XDG_CONFIG_DIRS="/etc/xdg" ``` To ensure that the directories defined by the XDG Base Directory Specification are available for every user, you can create them in the `/etc/skel/` directory. This directory is copied to create the home directory for new users. ```bash $ mkdir -p /etc/skel/.config /etc/skel/.cache /etc/skel/.local/share /etc/skel/.local/state ``` ## Creating Your User `useradd -m -G video,wheel <username>` * `-m` - This creates a home directory in the `/home/` directory for the new user. * `-G video,wheel` - This adds the new user to the `video` and `wheel` groups. * `video` - Members of the `video` group can draw in the framebuffer without elevated privileges. * `wheel` - Members of the `wheel` group can be configured to run commands with elevated privileges given certain conditions (like entering their password).