Gentoo with LVM in LUKs

My installation notes

Introduction

This org file describes how I get Gentoo up and running. My latest run-through of this document was on a virtual machine, though I have run through the same process — with some minor config changes — to put Gentoo on an old laptop than is now serving as my home network's DNS and DHCP.

To give an upfront overview of what kind of setup these steps result in:

Table 1: UEFI with GPT
Mount Point Partition Partition type Size
/boot /dev/efi_system_partition EFI system partition 1 GiB
[SWAP] /dev/swap_partition Linux swap 4 Gib
/ /dev/root_partition Linux x86-64 root (/) Remainder of device
bootloader
grub
networking
NetworkManager will be used for the networking
hibernation
to the encrypted swap partition
encryption

The root and swap The partition mounted at root (/) will be encrypted with LUKS. That partition will then be further divided with LVM to create two virtual partitions within the encrypted LUKS partition. One of those will be the file system root, the other will be used for swap.

Since hibernation will use the swap, I want the swap to be encrypted.

login greeter
none
WM
sway / wayland

Regardless of the distribution, there are common post-installation steps that often need to be done, such as setting up the firewall, configuring web browsers, etc. As these steps aren't really Gentoo-specific, I have separate notes for that.

Prerequisites

There are a couple of things that would be nice to have out of the way up front.

  1. Disable SecureBoot on the installation target.

    There are guides on setting up secure boot both on the gentoo wiki and the arch wiki. It does seem like you can set up secure boot to work without phoning home to microsoft, but I haven't figured out how to do this yet.
  2. Peruse the official installation guide.
  3. Import the signing keys

    There are various ways to do this, which you can see listed on the gentoo signatures page.

    Using the 3rd method listed on the bottom of that page:

    wget -q -O - https://qa-reports.gentoo.org/output/service-keys.gpg | gpg --import
    gpg --textmode --with-colons --list-keys gentoo.org | grep -Eo '<.*@gentoo.org>'
    
    <releng@gentoo.org>
    <openpgp-auth+l2-srv@gentoo.org>
    <openpgp-auth+l2-dev@gentoo.org>
    <infra+finch@gentoo.org>
    <infra+petrel@gentoo.org>
    <openpgp-auth+l2-infra@gentoo.org>
    <openpgp-auth+l1@gentoo.org>
    <glsamaker@gentoo.org>
    <releng@gentoo.org>
    <infrastructure@gentoo.org>
    <repomirrorci@gentoo.org>
    

Preparing a bootable USB

These steps all occur on a separate, already working, machine. I assume Linux and bash. Roughly the process is:

  1. obtain an .iso image along with verification hashes
  2. verify the .iso matches the provided verification hashes
  3. make a bootable USB drive from the .iso

Obtaining an OS image

Downloading and verifying the image is something that can be scripted. So the below steps are all wrapped in a bash script I can run whenever I need to pull a new .iso.

First, I make a working directory to provide a stable path. I didn't put it in /tmp because I'd like to keep .iso files around until I am sure I am ready to delete them.

note: it is assumed the signing keys were already imported as mentioned in Prerequisites.

function error() {
    echo "ERROR: ${1}"
    exit 1
}

ISO_RELEASE_URL='https://distfiles-cdn-origin.gentoo.org/releases/amd64/autobuilds/current-install-amd64-minimal'
ISO_INFO='latest-install-amd64-minimal.txt'

# verify the signed latest-install-amd64-minimal.txt is valid, exit
# with error if not
curl --silent -o /tmp/"$ISO_INFO" "$ISO_RELEASE_URL/$ISO_INFO"
# <(cat /tmp/latest-install-amd64-minimal.txt | sed -E 's/\.iso/\.fake/')
gpg --no-utf8-strings --textmode --verify < /tmp/"$ISO_INFO" || error "ISO info file signature is corrupt!"
echo "$ISO_INFO signature is valid"

ISO_AT="${ISO_AT:=$(grep -o '^install-amd64-minimal-\(.*\)\.iso .*' /tmp/"$ISO_INFO" | sed -E 's/^install-amd64-minimal-(.*)\.iso .*/\1/' )}"
ISO_CURRENT="install-amd64-minimal-${ISO_AT}.iso"

function create_working_dir() {
    local dir=${dir:="$HOME/gentoo/gentoo-install-${ISO_AT}"}
    export gentoo_working_dir="${dir}"
    mkdir -p "${dir}"
}

create_working_dir
echo "working dir: $gentoo_working_dir" | sed -e "s/$USER/a-user/"
cd "${gentoo_working_dir}"
gpg: Signature made Sun 13 Sep 2026 11:41:05 PM +07
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: Signature notation: manu=2,2.5+1.12,2,2
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 13EB BDBE DE7A 1277 5DFD  B1BA BB57 2E0E 2D18 2910
     Subkey fingerprint: 534E 4209 AB49 EEE1 C19D  9616 2C44 695D B9F6 043D
latest-install-amd64-minimal.txt signature is valid
working dir: /home/a-user/gentoo/gentoo-install-20260906T170102Z

The next thing to do is download the .iso, and the associated signatures and hashes, from the downloads page into the working directory.

 1: # https://www.gentoo.org/downloads/mirrors/
 2: GENTOO_MIRRORS=(
 3:     https://ftp.lanet.kr/pub/gentoo/releases/amd64/autobuilds/current-install-amd64-minimal
 4:     https://hk.mirrors.cicku.me/gentoo/releases/amd64/autobuilds/current-install-amd64-minimal
 5:     https://ftp.iij.ad.jp/pub/linux/gentoo/releases/amd64/autobuilds/current-install-amd64-minimal
 6:     https://metis.au.ext.planetunix.net/pub/gentoo/releases/amd64/autobuilds/current-install-amd64-minimal
 7: )
 8: 
 9: 
10: function fetch_latest_iso() {
11:     local dir=${dir:="$HOME/gentoo/gentoo-install-${ISO_AT}"}
12: 
13:     for file in "$ISO_CURRENT" "$ISO_CURRENT".{CONTENTS.gz,DIGESTS,asc,sha256}; do
14:         curl --skip-existing --silent -o "$dir/$file" "$ISO_RELEASE_URL/$file"
15:         printf 'Downloaded %s\n' "$file"
16:     done
17: }
18: 
19: function fetch_latest_iso_aria2() {
20:     local dir=${dir:="$HOME/gentoo/gentoo-install-${ISO_AT}"}
21: 
22:     for file in "$ISO_CURRENT" "$ISO_CURRENT".{CONTENTS.gz,DIGESTS,asc,sha256}; do
23:         declare -a mirrors
24:         local file_fmt="%s/$file"
25:         mapfile -t mirrors < <(printf "$file_fmt\n" "${GENTOO_MIRRORS[@]}")
26: 
27:         aria2c --quiet --timeout=20 --lowest-speed-limit=100K -x2 -c -l ariadl.log -d "$dir" -o "$file" "$ISO_RELEASE_URL/$file" "${mirrors[@]}"
28:         printf 'Downloaded %s\n' "$file"
29:     done
30: }
31: 
32: 
33: time fetch_latest_iso_aria2
34: #fetch_latest_iso

If aria2 is available, using that can provide a quicker ISO download:

Downloaded install-amd64-minimal-20260906T170102Z.iso
Downloaded install-amd64-minimal-20260906T170102Z.iso.CONTENTS.gz
Downloaded install-amd64-minimal-20260906T170102Z.iso.DIGESTS
Downloaded install-amd64-minimal-20260906T170102Z.iso.asc
Downloaded install-amd64-minimal-20260906T170102Z.iso.sha256

real	0m57.833s
user	0m5.832s
sys	0m3.916s

Before making the bootable USB from these files, I'll do my best to verify their authenticity using gpg and the provided checksums.

First verifying that the .iso file's signature matches one of the gpg keys I imported:

cd "$HOME/gentoo/gentoo-install-${ISO_AT}" 
printf 'Verifying the iso file: %s\n\n' "$ISO_CURRENT" && gpg --no-utf8-strings --textmode --verify "$ISO_CURRENT".asc "$ISO_CURRENT"
Verifying the iso file: install-amd64-minimal-20260906T170102Z.iso

gpg: Signature made Mon 07 Sep 2026 09:41:08 AM +07
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: Signature notation: manu=2,2.5+1.12,2,2
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 13EB BDBE DE7A 1277 5DFD  B1BA BB57 2E0E 2D18 2910
     Subkey fingerprint: 534E 4209 AB49 EEE1 C19D  9616 2C44 695D B9F6 043D

The Gentoo Release Team also signs the checksum files, so I will also verify the DIGESTS and sha256 files, creatings verified copies which strip the wrapping gpg signature block in the process:

rm -f "$ISO_CURRENT".{DIGESTS.verified, sha256.verified}
gpg --no-utf8-strings --textmode --output "$ISO_CURRENT".DIGESTS.verified --verify "$ISO_CURRENT".DIGESTS
gpg --no-utf8-strings --textmode --output "$ISO_CURRENT".sha256.verified --verify "$ISO_CURRENT".sha256
gpg: Signature made Mon 07 Sep 2026 09:41:08 AM +07
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: Signature notation: manu=2,2.5+1.12,2,2
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 13EB BDBE DE7A 1277 5DFD  B1BA BB57 2E0E 2D18 2910
     Subkey fingerprint: 534E 4209 AB49 EEE1 C19D  9616 2C44 695D B9F6 043D
gpg: Signature made Mon 07 Sep 2026 09:41:08 AM +07
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: Signature notation: manu=2,2.5+1.12,2,2
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 13EB BDBE DE7A 1277 5DFD  B1BA BB57 2E0E 2D18 2910
     Subkey fingerprint: 534E 4209 AB49 EEE1 C19D  9616 2C44 695D B9F6 043D

Because Gentoo has all of the hashed in one file, I grep for the specific algorithm to cut down on noise in the output:

cksum -a blake2b -c <(grep -A1 '# BLAKE2B HASH' "$ISO_CURRENT".DIGESTS.verified | grep iso)
cksum -a sha512 -c <(grep -A1 '# SHA512 HASH' "$ISO_CURRENT".DIGESTS.verified | grep iso)
cksum -a sha256 -c "$ISO_CURRENT".sha256.verified
install-amd64-minimal-20260906T170102Z.iso: OK
install-amd64-minimal-20260906T170102Z.iso.CONTENTS.gz: OK
install-amd64-minimal-20260906T170102Z.iso: OK
install-amd64-minimal-20260906T170102Z.iso.CONTENTS.gz: OK
install-amd64-minimal-20260906T170102Z.iso: OK

Now that I have confirmed that the .iso is signed by the Gentoo Release Team, and that the checksums provided match up with the downloaded .iso file, a bootable USB can be made.

Applying the image to a USB drive

The Gentoo wiki describes how to put the .iso on a USB drive. I am just using cat.

Because I need to run this as root and I am running these commands from an org file, I've written the full path to the .iso to a temp file in order to make it easy to work with org. [ If just running in the terminal, the path can be passed directly to sudo with the --preserve-env=list flag. ]

echo export ISO_FULL_PATH="$HOME/gentoo/gentoo-install-${ISO_AT}/${ISO_CURRENT}" > /tmp/gentoo-iso-path

Then as root I can use cat to write the .iso to the USB drive.

source /tmp/gentoo-iso-path

THIS_DRIVE_WILL_BE_WIPED='/dev/sda'

echo "the iso to be written: $ISO_FULL_PATH" | sed -e "s/home\/.*\//home\/a-user\//"
echo "the drive to be wiped: $THIS_DRIVE_WILL_BE_WIPED"

cat "${ISO_FULL_PATH}" > /dev/sda
the iso to be written: /home/a-user/install-amd64-minimal-20260906T170102Z.iso
the drive to be wiped: /dev/sda

The USB is now ready to be plugged into the machine I'm installing arch on an booted to.

Prepare the installation target

After booting to the installation media, there is one interactive prompt to choose the keyboard layout before being logged into a root shell and greeted by the welcome message:

Welcome to the Gentoo Linux Minimal Installation CD!

The root password on this system has been auto-scrambled for security.

If any ethernet adapters were detected at boot, they should be auto-configured
if DHCP is available on your network.  Type "net-setup eth0" to specify eth0 IP
address settings by hand.

Check /etc/kernels/kernel-config-* for kernel configuration(s).
The latest version of the Handbook is always available from the Gentoo web
site by typing "links https://wiki.gentoo.org/wiki/Handbook".

To start an ssh server on this system, type "/etc/init.d/sshd start".  If you
need to log in remotely as root, type "passwd root" to reset root's password
to a known value.

Please report any bugs you find to https://bugs.gentoo.org. Be sure to include
detailed information about how to reproduce the bug you are reporting.

Thank you for using Gentoo Linux!
Last login: Mon Sep  7 18:56:10 UTC 2026 on tty4
livecd ~ # 

This explains how to set the root password, how to start sshd, provides a link to the wiki, as well as some guidance on networking. The install image comes with NetworkManager, so nmtui and nmcli are available to connect to wifi if needed.

the terminal font size can be increased:

setfont -d

In practice, I don't usually do this as I ssh into the machine to run through the installation. So, assuming there is a network connection [ e.g. ping -c3 gentoo.org works ], I am just going to enable ssh and set a root password so that I can complete the installation from a separate machine:

# set a root password
echo -n 1234 | passwd

# start ssh
/etc/init.d/sshd start

# print ip addr to use to ssh
ip addr | grep inet | grep -v '[_ ]lo'

The root password of 1234 can be replaced if needed. [ If this is an install on a machince on a local network and not exposed to the internet (e.g. a laptop or PC), then don't sweat this password. This is the password for root on the live cd, not on the target machine. It doesn't persist across live CD boots, so I usually go with 1234. If this install is on a machine that will need to be connected to the internet in order to get ssh access (or even a large intranet) then you will still want this password to be secure… but I'm not and if you're reading this you likely aren't either. ]

Now from another machine I can src_sh[:exports code :eval never :results none] { ssh root@the_ip_from_above }

Troubleshooting network connection issue

I've encountered a few issues with getting a network connection.

  1. When installing in a VM, DNS from the VM was blocked by my host's firewall

    The fix was to allow VM dhcp/dns requests to host. The Arch wiki has the needed nftable config in "Libvirt: Using nftables" and then after the new config is loaded on the host, restart libvirtd on the host, and finally restart DHCP on the guest with rc-service dhcpcd restart

  2. When installing on a VPS, static networking needed to be set up

    The Gentoo welcome message explains how to set up the connection by hand.

  3. When installing directly on a laptop, WiFi must be configured

    This hasn't actually been an issue on Gentoo. On Arch I've had to restart the WiFi daemon on occasion.

Sync the system clock

Now on a separate machine — either in a terminal ssh session or, more likely, running these commands directly from the org document containing these notes — I sync the clock:

# The output redirection isn't needed in a terminal. It is there to
# display nicely with org-mode.
chronyd -q 2>&1
2026-09-13T19:40:12Z chronyd version 4.8 starting (+CMDMON +REFCLOCK +RTC +PRIVDROP +SCFILTER -SIGND +NTS +SECHASH +IPV6 -DEBUG)
2026-09-13T19:40:12Z Wrong owner of /run/chrony (UID != 0)
2026-09-13T19:40:12Z Disabled command socket /run/chrony/chronyd.sock
2026-09-13T19:40:12Z Running with root privileges
2026-09-13T19:40:17Z System clock wrong by 0.911853 seconds (step)
2026-09-13T19:40:18Z chronyd exiting

Disks and File systems

Overview

For these notes, I am running on a virtual machine which has a disk layout like this:

lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0    7:0    0 837.9M  1 loop /run/rootfsbase
sda      8:0    1 238.5G  0 disk 
├─sda1   8:1    1   278K  0 part 
├─sda2   8:2    1   2.8M  0 part 
├─sda3   8:3    1 958.5M  0 part /run/initramfs/live
└─sda4   8:4    1   300K  0 part 
vda    253:0    0    50G  0 disk

The vda drive is what I am using for this example. When installing on a laptop the drive will likely be something like nvme0n1.

I like to set up some variables ahead of time, so I can keep the majority of the guide unchanged regardless of the disk:

# For laptop
# ════════════════════
# DISK=/dev/nvme0n1
# BOOT_PART=/dev/nvme0n1p1
# LUKS_PART=/dev/nvme0n1p2

# For VM
# ════════════════════
DISK=/dev/vda
BOOT_PART=/dev/vda1
LUKS_PART=/dev/vda2

# LVM setup
# ════════════════════
VOLUME_GROUP=vgGentoo

The Gentoo installation wiki is open ended for this section, which makes sense as disk partitioning is going to be very dependent on what you're ultimately trying to do and what kind of hardware you have.

For me, I have laptops with very similar setups, so I am targeting an LVM on LUKS setup.

This means I will have 2 partitions on my drive.

  1. An unencrypted 1G boot partition
  2. The rest of the space is an encrypted LUKS partition

During installation, I will open the LUKS partition and set up LVM within it. I will then create a swap partition and a root partition within that.[ Most commands support non-interative/script modes. I should look into the cryptsetup manual to see if it does. It would be nice to be able to do this all from org-mode. ]

This allows me to easily have hibernation with and encrypted swap.

The end result looks something like:

NAME                 SIZE TYPE  MOUNTPOINTS PARTTYPENAME
vda                   50G disk              
├─vda1                 1G part  /mnt/boot   EFI System
└─vda2                49G part              Linux filesystem
  └─cryptlvm          49G crypt             
    ├─vgGentoo-swap    8G lvm   [SWAP]      
    └─vgGentoo-root   41G lvm   /mnt

The name "cryptlvm" is arbitrary here, but the nomenclature seems common and it is descriptive, so I stick with it.

  • note on The boot partition
    • The boot partition must be mounted at /boot. Previously I had been mounting it at /efi, but that requires a slightly more complicated 3 partition LUKS setup.[ A small bios partition, an unencrypted EFI partition and the LUKS partition. ] I've got it working, but I'm not comfortable enough yet to make it my default setup.

      I couldn't get this working with an encrypted setup. I believe grub requires using /boot in this scenario.

Disk Partitions

For partitionig the disk, I like using cfdisk. Since it is a TUI, I run the following in a terminal.[ As opposed to most of these commands which are directly run from my org file in Emacs. ]

cfdisk $DISK
  • 1G for boot
  • rest of space for LUKS
  • I've set the partition type labels. Things will mostly work without them, however tools (for example fwupd) may expect them to be set. Doing so now is kind to our future selves.

After partitioning the layout is:

lsblk -o name,size,type,parttypename $DISK
NAME    SIZE TYPE PARTTYPENAME
vda      50G disk 
├─vda1    1G part EFI System
└─vda2   49G part Linux filesystem

LUKS Setup

The encrypted root partition is interactive, so I also run these commands in a terminal.[ Most commands support non-interative/script modes. I should look into the cryptsetup manual to see if it does. It would be nice to be able to do this all from org-mode. ]

cryptsetup luksFormat $LUKS_PART

# follow the prompts, after that run
cryptsetup open $LUKS_PART cryptlvm

After the above cyptsetup commands, the layout is:

lsblk $DISK
NAME         MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
vda          253:0    0   50G  0 disk  
├─vda1       253:1    0    1G  0 part  
└─vda2       253:2    0   49G  0 part  
  └─cryptlvm 252:0    0   49G  0 crypt

Boot partition/EFI setup

mkfs.vfat -F 32 $BOOT_PART
mkfs.fat 4.2 (2021-01-31)

LVM (in LUKS) Setup

Now that the LUKS partition is set up, I can create an LVM physical volume, encompassing the whole LUKS drive. Then create a virtual group, call vgArch below.[ Don't use hypens in the name, it turns out weird ]

pvcreate /dev/mapper/cryptlvm
vgcreate "$VOLUME_GROUP" /dev/mapper/cryptlvm
Physical volume "/dev/mapper/cryptlvm" successfully created.
Volume group "vgGentoo" successfully created

Then make the logical volumes

lvcreate -L 8G -n swap $VOLUME_GROUP
lvcreate -l 100%FREE -n root $VOLUME_GROUP
Logical volume "swap" created.
Logical volume "root" created.

Since the recommended filesystem for Gentoo is xfs, There is no need to shrink the root partion as I do when using the ext4 file system.

Then make the root file system and the swap:

mkfs.xfs -c options=/usr/share/xfsprogs/mkfs/lts_6.18.conf "/dev/${VOLUME_GROUP}/root"
mkswap "/dev/$VOLUME_GROUP/swap"
Parameters parsed from config file /usr/share/xfsprogs/mkfs/lts_6.18.conf successfully
meta-data=/dev/vgGentoo/root     isize=512    agcount=4, agsize=2685696 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=1
         =                       reflink=1    bigtime=1 inobtcount=1 nrext64=1
         =                       exchange=1   metadir=0
data     =                       bsize=4096   blocks=10742784, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1, parent=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
         =                       rgcount=0    rgsize=0 extents
         =                       zoned=0      start=0 reserved=0
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=6fce7652-5137-4050-abf5-b170171b7801

Finally, get everything mounted [ Here I diverge from the guide for the mount points. The guide recommends /mnt/gentoo/efi, however I will be using grub as the bootloader, which expects the efi files to be in /boot. I also use /mnt directly (as opposed to /mnt/gentoo). ]:

mount "/dev/$VOLUME_GROUP/root" /mnt
mount --mkdir "$BOOT_PART" /mnt/boot

swapon "/dev/$VOLUME_GROUP/swap"

After all of that, the layout looks like:

lsblk $DISK
NAME                MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
vda                 253:0    0   50G  0 disk  
├─vda1              253:1    0    1G  0 part  /mnt/boot
└─vda2              253:2    0   49G  0 part  
  └─cryptlvm        252:0    0   49G  0 crypt 
    ├─vgGentoo-swap 252:1    0    8G  0 lvm   [SWAP]
    └─vgGentoo-root 252:2    0   41G  0 lvm   /mnt

Stage file installation

Prerequisites

  1. cd into the mount before moving onto installing the stage file:

    cd /mnt && pwd
    
  2. Time check: sync the clock again

    I going to be making a lot of https requests from this point on, so I need to correct any clock skew. I'll handle this in an automated way once the system is set up.

    chronyd -q 2>&1
    
  3. Import gpg keys

    Similiar to how the .iso files were checked, the stage files should be checked. The signing keys can be imported from the install image:

    gpg --import /usr/share/openpgp-keys/gentoo-release.asc &&
        gpg --textmode --with-colons --list-keys gentoo.org | grep -Eo '<.*@gentoo.org>'
    
    gpg: directory '/root/.gnupg' created
    gpg: key A13D0EF1914E7A72: 1 signature not checked due to a missing key
    gpg: /root/.gnupg/trustdb.gpg: trustdb created
    gpg: key A13D0EF1914E7A72: public key "Gentoo repository mirrors (automated git signing key) <repomirrorci@gentoo.org>" imported
    gpg: key DB6B8C1F96D8BF6D: 2 signatures not checked due to missing keys
    gpg: key DB6B8C1F96D8BF6D: public key "Gentoo ebuild repository signing key (Automated Signing Key) <infrastructure@gentoo.org>" imported
    gpg: key 9E6438C817072058: 1 signature not checked due to a missing key
    gpg: key 9E6438C817072058: public key "Gentoo Linux Release Engineering (Gentoo Linux Release Signing Key) <releng@gentoo.org>" imported
    gpg: key BB572E0E2D182910: 1 signature not checked due to a missing key
    gpg: key BB572E0E2D182910: public key "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" imported
    gpg: Total number processed: 4
    gpg:               imported: 4
    gpg: no ultimately trusted keys found
    <releng@gentoo.org>
    <releng@gentoo.org>
    <infrastructure@gentoo.org>
    <repomirrorci@gentoo.org>
    

Obtaining the stage file

This is essentially the same process I went through with the .iso, but with slightly different URLs. Rather than go through it step by step, I've just copied the script from the usb section and modified the urls. The working directory in this case is the mount point of the root filesystem, /mnt for my setup, /mnt/gentoo in the official guide:

note: it is assumed the signing keys were already imported as mentioned in Prerequisites.

function error() {
    echo "ERROR: ${1}"
    exit 1
}

ISO_RELEASE_URL='https://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-openrc'
ISO_INFO='latest-stage3-amd64-openrc.txt'

# verify the signed $ISO_INFO is valid, exit with error if not
curl --skip-existing --silent -o /tmp/"$ISO_INFO" "$ISO_RELEASE_URL/$ISO_INFO"
rm -f /tmp/"$ISO_INFO".verified
gpg --output /tmp/"$ISO_INFO".verified --verify /tmp/"$ISO_INFO"  || error "INFO file signature is corrupt!"
echo "$ISO_INFO signature is valid"
gpg: Signature made Sun 13 Sep 2026 09:01:05 PM UTC
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
      13EBBDBEDE7A12775DFDB1BABB572E0E2D182910
      534E4209AB49EEE1C19D96162C44695DB9F6043D
latest-stage3-amd64-openrc.txt signature is valid
ISO_AT="${ISO_AT:=$(grep -o '^stage3-amd64-openrc-\(.*\)\.xz .*' /tmp/"${ISO_INFO}.verified" | sed -E 's/^stage3-amd64-openrc-(.*)\.tar\.xz .*/\1/' )}"
ISO_CURRENT="stage3-amd64-openrc-${ISO_AT}.tar.xz"

function fetch_latest_iso() {
    local dir="."

    for file in "$ISO_CURRENT" "$ISO_CURRENT".{CONTENTS.gz,DIGESTS,asc,sha256}; do
        curl --skip-existing --silent -o "$dir/$file" "$ISO_RELEASE_URL/$file"
        printf 'Downloaded %s\n' "$file"
    done
}

fetch_latest_iso 
echo "Verifying the stage file: ${ISO_CURRENT}" && gpg --textmode --verify "$ISO_CURRENT".asc "$ISO_CURRENT" 2> /dev/null
Downloaded stage3-amd64-openrc-20260906T170102Z.tar.xz
Downloaded stage3-amd64-openrc-20260906T170102Z.tar.xz.CONTENTS.gz
Downloaded stage3-amd64-openrc-20260906T170102Z.tar.xz.DIGESTS
Downloaded stage3-amd64-openrc-20260906T170102Z.tar.xz.asc
Downloaded stage3-amd64-openrc-20260906T170102Z.tar.xz.sha256
Verifying the stage file: stage3-amd64-openrc-20260906T170102Z.tar.xz
rm -f "$ISO_CURRENT".{DIGESTS.verified,sha256.verified}
gpg --textmode --output "$ISO_CURRENT".DIGESTS.verified --verify "$ISO_CURRENT".DIGESTS
gpg --textmode --output "$ISO_CURRENT".sha256.verified --verify "$ISO_CURRENT".sha256

cksum -a blake2b -c <(grep -A1 '# BLAKE2B HASH' "$ISO_CURRENT".DIGESTS.verified | grep tar)
cksum -a sha512 -c <(grep -A1 '# SHA512 HASH' "$ISO_CURRENT".DIGESTS.verified | grep tar)
cksum -a sha256 -c "$ISO_CURRENT".sha256.verified
gpg: Signature made Sun 06 Sep 2026 06:01:05 PM UTC
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
      13EBBDBEDE7A12775DFDB1BABB572E0E2D182910
      534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Signature made Sun 06 Sep 2026 06:01:05 PM UTC
gpg:                using RSA key 534E4209AB49EEE1C19D96162C44695DB9F6043D
gpg: Good signature from "Gentoo Linux Release Engineering (Automated Weekly Release Key) <releng@gentoo.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
      13EBBDBEDE7A12775DFDB1BABB572E0E2D182910
      534E4209AB49EEE1C19D96162C44695DB9F6043D
stage3-amd64-openrc-20260906T170102Z.tar.xz: OK
stage3-amd64-openrc-20260906T170102Z.tar.xz.CONTENTS.gz: OK
stage3-amd64-openrc-20260906T170102Z.tar.xz: OK
stage3-amd64-openrc-20260906T170102Z.tar.xz.CONTENTS.gz: OK
stage3-amd64-openrc-20260906T170102Z.tar.xz: OK

If everything looks good, the checksum files can be removed and I can move on to installing the stage file.

rm -f stage3-amd64-openrc-20260823T153057Z.tar.xz.DIGESTS.verified \
   stage3-amd64-openrc-20260823T153057Z.tar.xz.asc \
   stage3-amd64-openrc-20260823T153057Z.tar.xz.sha256 \
   stage3-amd64-openrc-20260823T153057Z.tar.xz.DIGESTS \
   stage3-amd64-openrc-20260823T153057Z.tar.xz.sha256.verified

Installing the stage file

Installing gentoo from a stage file is a matter of unpacking the .tar.gz into the root and making sure the file permissions all look correct. The command comes from the guide, with the one modification being that I have a different root directory

# the official guide uses "-C /mnt/gentoo"
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt
ls -l -I 'stage3-amd64-openrc*' -I 'DIGESTS.generated'
total 8
lrwxrwxrwx  1 root root    7 Sep  6 17:07 bin -> usr/bin
drwxr-xr-x  2 root root 4096 Jan  1  1970 boot
drwxr-xr-x  2 root root   33 Sep  6 17:07 dev
drwxr-xr-x 31 root root 4096 Sep  6 17:28 etc
drwxr-xr-x  2 root root    6 Sep  6 17:07 home
lrwxrwxrwx  1 root root    7 Sep  6 17:07 lib -> usr/lib
lrwxrwxrwx  1 root root    9 Sep  6 17:07 lib64 -> usr/lib64
drwxr-xr-x  2 root root    6 Sep  6 17:07 media
drwxr-xr-x  2 root root    6 Sep  6 17:07 mnt
drwxr-xr-x  2 root root    6 Sep  6 17:07 opt
drwxr-xr-x  2 root root    6 Sep  6 17:07 proc
drwx------  2 root root   36 Sep  6 17:13 root
drwxr-xr-x  2 root root    6 Sep  6 17:07 run
lrwxrwxrwx  1 root root    7 Sep  6 17:07 sbin -> usr/bin
drwxr-xr-x  2 root root    6 Sep  6 17:07 sys
drwxrwxrwt  2 root root    6 Sep  6 17:28 tmp
drwxr-xr-x 11 root root  147 Sep  6 17:09 usr
drwxr-xr-x  9 root root  123 Sep  6 17:24 var

Operating System

Gentoo is a source based distribution. This means I'll be doing a lot of compiling.

This laptop has 4 cores and 4GB of RAM, so I don't want to be compiling things more than I have to. So, I will puting as many configuration files in place as I can before emerging anything.

COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
RUSTFLAGS="${RUSTFLAGS} -C target-cpu=native"
MAKEOPTS="-j2 -l4"
USE="-systemd -secureboot -kde -gnome -bluetooth -X dist-kernel wayland elogind udisks lvm heif alsa acl pipewire networkmanager"
ACCEPT_LICENSE="-* @FREE @BINARY-REDISTRIBUTABLE"
GRUB_PLATFORMS="efi-64"

LC_MESSAGES=C.UTF-8

GENTOO_MIRRORS="https://metis.au.ext.planetunix.net/pub/gentoo/ \
http://ftp.swin.edu.au/gentoo \
https://jp.mirrors.cicku.me/gentoo/ \
https://kale.jp.ext.planetunix.net/pub/gentoo/ \
https://mirror.freedif.org/gentoo \
https://dione.th.ext.planetunix.net/pub/gentoo/ \
https://mirror.meowsmp.net/gentoo/"

Because my source of truth for my USE flags is this org file, I prefer to have all of the flags be in a single file:

rm -rf ./etc/portage/package.use/ && touch ./etc/portage/package.use

# accept_keywords can be used to install things still in testing (like newer kernel versions)
rm -rf ./etc/portage/package.accept_keywords/ && touch ./etc/portage/package.accept_keywords
# For my laptop
# */* CPU_FLAGS_X86: aes mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 ssse3
# */* VIDEO_CARDS: -* intel

# For Virtual machine
*/* CPU_FLAGS_X86: aes avx avx2 avx512_bitalg avx512_vbmi2 avx512_vnni avx512_vp2intersect avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 ssse3 vpclmulqdq
*/* VIDEO_CARDS: -* virgl

# needed at install
sys-fs/cryptsetup -ssh
sys-fs/lvm2 lvm nvme xfs
sys-boot/grub device-mapper -libzfs
sys-fs/genfstab -test
sys-kernel/installkernel -systemd -dracut -efistub -systemd-boot -generic-uki -uki -ukify grub ugrd

# networking
net-firewall/nftables doc xtables
net-firewall/iptables nftables # for podmani
net-wireless/wpa_supplicant dbus
net-misc/networkmanager nftables -concheck -modemmanager

# system/firmware
sys-apps/fwupd bash-completion gnutls lzma nvme spi synaptics uefi tpm policykit

# image libs
media-libs/libavif dav1d gdk-pixbuf libyuv
media-libs/libheif dav1d gdk-pixbuf 
media-libs/imlib2 avif jpegxl raw svg heif mp3 -shm
media-libs/dav1d
media-gfx/graphicsmagick heif openmp zlib imagemagick jpeg jpegxl lcms png postscript tiff truetype webp

# window manager
sys-apps/dbus elogind -systemd
x11-base/xwayland
media-libs/libepoxy X
media-libs/libglvnd X
gui-libs/wlroots X lcms vulkan
media-libs/mesa wayland lm-sensors vulkan X
media-libs/freetype harfbuzz svg png cleartype-hinting brotli
gui-apps/foot grapheme-clustering
gui-apps/swaylock gdk-pixbuf
gui-apps/swaybg gdk-pixbuf
gui-wm/sway -wallpapers X tray swaybar swaynag

# defaults: gui-apps/swayidle
# defaults gui-apps/wmenu

# emacs
dev-libs/libusb udev
virtual/libusb udev
gui-libs/gtk colord vulkan
sys-devel/gcc pgo hardened jit
app-editors/emacs -X -alsa -games -gfile -gpm -gsettings -gtk -gui -gzip-el -imagemagick -inotify -libxml2 -m17n-lib -mailutils -motif -sound -sqlite -xft -xpm acl cairo gif gmp harfbuzz jit jpeg lcms png source ssl svg threads tiff tree-sitter webp xattr zlib

# containers
app-containers/podman wrapper

# firefox
x11-libs/cairo X
x11-libs/gtk+ X
media-plugins/alsa-plugins pulseaudio

# sys/admin

With a base configuration in place, I can move on to exiting the livecd environment and entering the in-progress install.

chroot

It is now time to chroot into the in-progress install. Before actually running chroot, I need to copy the network config and the vi binary, so I still have access to both in the chroot:

cp --dereference /etc/resolv.conf ./etc/
cp --dereference /usr/bin/vi ./usr/bin/

I can now chroot. Since I am using the gentoo livecd — as opposed to something like mint — I can just use the included arch-chroot tool:

arch-chroot /mnt

bash: warning: setlocale: LC_ALL: cannot change locale (en_US.utf8): No such file or directory

Initial emerge

The /boot directory is already mounted, so I should be good to set up the ebuilds repository. This is the database of all packages available to portage. The emerge-webrsync will rsync over a snapshot of the database (usually at most a day old) to bootstrap portage. Going forward we will just update portage via emerge --sync (which is sort of like pacman -S or apt update).

emerge-webrsync

Once the snapshot is pulled down, I can run a regular emerge --sync to make sure the database is completely up to date. It isn't required to get the system running, but I'm not in a rush so I will just do it:

emerge --sync --quiet

The profile I want should already be selected, but if I want to change profiles now is the time to do it.

eselect profile list | head
/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.utf8): No such file or directory
Available profile symlink targets:
  [1]   default/linux/amd64/23.0 (stable) *
  [2]   default/linux/amd64/23.0/systemd (stable)
  [3]   default/linux/amd64/23.0/desktop (stable)
  [4]   default/linux/amd64/23.0/desktop/systemd (stable)
  [5]   default/linux/amd64/23.0/desktop/gnome (stable)
  [6]   default/linux/amd64/23.0/desktop/gnome/systemd (stable)
  [7]   default/linux/amd64/23.0/desktop/plasma (stable)
  [8]   default/linux/amd64/23.0/desktop/plasma/systemd (stable)
  [9]   default/linux/amd64/23.0/no-multilib (stable)

After the database is synced, I am going to update the @world. While this isn't strictly necessary at this point, I do already have several USE flags added in my initial config, and I want to make sure everything is already respecting those options before moving on.

emerge --ask --verbose --update --deep --changed-use @world

In general, after an emerge @world, obsolete packages should be cleaned up. This will likely be a no-op in this stage of a fresh installation:

emerge --ask --pretend --depclean

Timezones and locales

Link in the relevant timezone. The guide mentions that the .. in the target command is relative to the link, not the directory where the command is executed.

ln -sf ../usr/share/zoneinfo/Asia/Bangkok /etc/localtime

I like to set the locale variables in /etc/env.d/02locale.

LANG="en_US.UTF-8"
LC_COLLATE="C.UTF-8"

Then I uncomment the desired locales in the generation script. This can be done with sed. [ So that I can run the command from org-mode in Emacs. ] As a fallback, I use -i.original to make a backup.

sed -i.original -E 's/# en_US/en_US/ ; s/# th_TH/th_TH/' /etc/locale.gen

and then run the generation script:

locale-gen
Found 2 locale declarations in '/etc/locale.gen'.
Compiling 3 locales with 3 workers ...
[1/3] Compiling locale: C.UTF-8
[2/3] Compiling locale: en_US.UTF-8
[3/3] Compiling locale: th_TH.UTF-8
Waiting for active workers to finish their jobs ...
The location of the archive shall be '/usr/lib/locale/locale-archive'.
Adding 3 locales to the locale archive ...
Successfully installed an archive containing 3 locales, of 5.4 MiB in size.

Finally, reload the environment before moving on to the kernel:

env-update && source /etc/profile && export PS1="(chroot) ${PS1}"
Regenerating /etc/ld.so.cache...

Configuring the kernel

For the kernel, there are several different ways to proceed. My go-to for an install on real hardware is a distribution kernel with modprobed-db, which can then be used to do a semi-manual kernel config at a later date.[ For a throwaway VM, I will do a pre-compiled distribution kernel. ]

I already put all of the configs in place previously, so now we just need to install some utilities to prepare for compiling the kernel.

I want to make sure cryptsetup and lvm2 are installed in the chroot, so I emerge those first along with the filesystems and bootloader I am using. I'm also going to add in screen as the kernel stuff is going to take a long time on my machine:

emerge --ask --verbose net-firewall/nftables    \
       net-wireless/wpa_supplicant              \
       net-misc/networkmanager

I can now install all of the firmware, the kernel (with gentoo patches) [ On a VM, unless I am specifically making the VM to mess with the kernel, I will use sys-kernel/gentoo-kernel-bin ], and installkernel [ installkernel is a collection of scripts that help with installing a kernel after I compile it with make. ]. I do this all in one emerge invocations so I get the final set of dependencies I want.[ For an example of what I mean. If I am on a VM I will likely install gentoo-kernel-bin, but the dist-kernel USE flag will pull in gentoo-kernel by default as a dependency if I just emerged the firmware packages alone. ]

My laptops are intel, so I am installing intel microcode. sof-firmware is only needed for audio support, so it can be left out of a VM install (as can the microcode package).

emerge --ask --verbose sys-kernel/modprobed-db  \
       sys-kernel/gentoo-kernel                 \
       sys-kernel/linux-firmware                \
       sys-firmware/sof-firmware                \
       sys-firmware/intel-microcode             \
       sys-kernel/installkernel

Once the kernel is emerged to /usr/src, I can use eselect to create a symlink to the current kernel:

eselect kernel list
Available kernel symlink targets:
  [1]   linux-6.18.48-gentoo-dist-bin *

There should only be one option, the kernel I just emerged. It must be symlinked as the active kernel, which can be done with:

# actually set the current kernel and create the symlink with:
eselect kernel set 1

Depending on what kernel was installed, I may need to cd to the kernel and configure the modules. I like using make localmodconfig to help autodetect the needed modules. However, above I installed the bin kernel since this run-through is on a VM, so I skip this step:

cd /usr/src/linux && make localmodconfig

My machines have intel graphics, so outside of a VM I want to make sure the intel Direct Rendering Manager (DRM) is enabled in the kernel. The kernel section of the gentoo Intel wiki has the specifics.[ If I forget to check this, it isn't the end of the world. I have done this before and it prevented me from starting sway. However the fix was straightfoward enough: ssh in, modify the kernel config to enable intel DRM, recompile/reinstall, and reboot. ]

Generate fstab

In that initial emerge I ran, I included sys-fs/genfstab from Arch, so I can use that to make the /etc/fstab file from the current mountpoints:

genfstab -U / >> /etc/fstab

Hostname and networking

I need to set up the /etc/hostname and /etc/hosts files:

echo  "vm-gentoo" >> /etc/hostname
# The current system
127.0.0.1     vm-gentoo.homenetwork vm-gentoo localhost
::1           vm-gentoo.homenetwork vm-gentoo localhost

# Other systems on the network
# 192.168.1.xx  foo.homenetwork foo
# 192.168.1.yy  bar.homenetwork bar

On arch I used networkmanager with iwd as the wireless daemon. On my Gentoo host, iwd was not working. I think the issue was laptop-specific, however I wasn't interested in looking into this, so I use net-wireless/wpa_supplicant for wifi on Gentoo.

ssh is included in the base gentoo @system set, so it does not need to be emerged.

NetworkManager pulls in a alot of stuff. It is worth taking a moment to customize the package.use to exlude uneeded modules. If this is a VM or a wired-connection-only setup, then skipping NetworkManager altogether and using something like net-misc/dhcpcd might be preferred. The handbook entry "AMD64/Installation/System: Network" is a good starting reference for this step.

GRUB for bootloader

This is another spot that differs a bit due to LVM on LUKS. The UUID of the encrypted partition (or label, if there is one) needs to be set as a crypdevice in the grub commandline.

With the following layout, the UUID I need is 43338968-f2f4-4e1f-a376-4828bc72bc83

# Encrypted partition is: vda2
vda2              43338968-f2f4-4e1f-a376-4828bc72bc83
└─cryptlvm        hvDksv-tgEt-CDDG-TIoY-8J3e-69ld-C6YE93
  ├─vgGentoo-swap 6fce7652-5137-4050-abf5-b170171b7801
  └─vgGentoo-root 8941bc3b-004b-42a8-81e3-ce7ce2762a00

The desired GRUB_CMDLINE_LINUX look like:

GRUB_CMDLINE_LINUX="cryptdevice=UUID=43338968-f2f4-4e1f-a376-4828bc72bc83:cryptlvm root=/dev/vgGentoo/root rootfstype=xfs resume=/dev/vgGentoo/swap"

I use sed to modify /etc/default/grub.

crypt_uuid=43338968-f2f4-4e1f-a376-4828bc72bc83
current_grub_cmdline='^#GRUB_CMDLINE_LINUX=\"\"'
new_grub_cmdline="cryptdevice=UUID=${crypt_uuid}:cryptlvm root=\/dev\/vgGentoo\/root rootfstype=xfs resume=\/dev\/vgGentoo\/swap"

sed -i.original -E "s/${current_grub_cmdline}/GRUB_CMDLINE_LINUX=\"${new_grub_cmdline}\"/" /etc/default/grub

grep '^GRUB_CMD' /etc/default/grub
GRUB_CMDLINE_LINUX="cryptdevice=UUID=43338968-f2f4-4e1f-a376-4828bc72bc83:cryptlvm root=/dev/vgGentoo/root rootfstype=xfs resume=/dev/vgGentoo/swap"

Assuming the above diff looks correct, the backup file can be removed:

rm /etc/default/grub.original

Install grub and generate the config using the new default file:

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
Installing for x86_64-efi platform.
Installation finished. No error reported.
Generating grub configuration file ...
Found theme: /boot/grub/themes/gentoo_glass/theme.txt
Found linux image: /boot/vmlinuz-6.18.48-gentoo-dist-bin
Found initrd image: /boot/amd-uc.img /boot/initramfs-6.18.48-gentoo-dist-bin.img
Found linux image: /boot/vmlinuz-6.18.48-gentoo-dist-bin.old
Found initrd image: /boot/amd-uc.img /boot/initramfs-6.18.48-gentoo-dist-bin.img.old
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
Adding boot menu entry for UEFI Firmware Settings ...
done

Set up system services

Before rebooting, I want to make sure some basic programs are in place and make sure certain services (such as networking and ssh) are set to autostart. udisks will pull in dev-lang/rust-bin, which can take quite a while to emerge, so if this is a VM where using fwupd won't be needed, I will strip out udisks, fwupd, and maybe even ncurses if I am feeling impatient[ I am pulling in ncurses here to get the terminfo database. ].

emerge --ask --verbose sys-libs/ncurses         \
       sys-apps/dmidecode                       \
       sys-apps/pciutils                        \
       sys-apps/usbutils                        \
       app-portage/cpuid2cpuflags               \
       app-admin/sysklogd                       \
       net-misc/chrony                          \
       sys-process/cronie                       \
       sys-block/io-scheduler-udev-rules        \
       sys-fs/udisks                            \
       sys-apps/fwupd                           \
       app-admin/sudo                           \
       app-shells/bash-completion

And autostarting some services:

rc-update add NetworkManager default  # networking
rc-update add sysklogd default        # logging
rc-update add cronie default          # cron jobs
rc-update add sshd default            # ssh
rc-update add chronyd default         # ntpd
* service NetworkManager added to runlevel default
* service sysklogd added to runlevel default
* service cronie added to runlevel default
* service sshd added to runlevel default
* service chronyd added to runlevel default

Set up users and reboot

  • First, a root password: passwd
  • Then create my user: useradd -m -G wheel -s /bin/bash a-user
  • Then a user password: passwd a-user
  • Then edit the sudo file to make wheel group sudo: EDITOR=vi visudo

While editing the sudoers file with visudo, I also tweak the sudo config to personal preference:

Defaults pwfeedback
Defaults passwd_tries=15
Defaults passwd_timeout=2.5
Defaults timestamp_timeout=10
Defaults insults

If needed, add a few more groups as mention on "AMD64/Installation/Finalizing: Adding a user for daily use".

usermod -aG cron,audio,video,usb,plugdev a-user

After that I can exit the chroot and close out any additional ssh sessions that are open.[ As I run install via my org document in emacs, I need to clean up all of the tramp connections before trying a umount. ]

Then unmount everything and reboot:

umount -l /mnt/dev{/shm,/pts,}
umount -R /mnt/
reboot

Footnotes:

[1]

If just running in the terminal, the path can be passed directly to sudo with the --preserve-env=list flag.

[2]

e.g. ping -c3 gentoo.org works

[3]

If this is an install on a machince on a local network and not exposed to the internet (e.g. a laptop or PC), then don't sweat this password. This is the password for root on the live cd, not on the target machine. It doesn't persist across live CD boots, so I usually go with 1234. If this install is on a machine that will need to be connected to the internet in order to get ssh access (or even a large intranet) then you will still want this password to be secure… but I'm not and if you're reading this you likely aren't either.

[4]

Most commands support non-interative/script modes. I should look into the cryptsetup manual to see if it does. It would be nice to be able to do this all from org-mode.

[5]

A small bios partition, an unencrypted EFI partition and the LUKS partition.

[6]

As opposed to most of these commands which are directly run from my org file in Emacs.

[7]

Don't use hypens in the name, it turns out weird

[8]

Here I diverge from the guide for the mount points. The guide recommends /mnt/gentoo/efi, however I will be using grub as the bootloader, which expects the efi files to be in /boot. I also use /mnt directly (as opposed to /mnt/gentoo).

[9]

So that I can run the command from org-mode in Emacs.

[10]

For a throwaway VM, I will do a pre-compiled distribution kernel.

[11]

On a VM, unless I am specifically making the VM to mess with the kernel, I will use sys-kernel/gentoo-kernel-bin

[12]

installkernel is a collection of scripts that help with installing a kernel after I compile it with make.

[13]

For an example of what I mean. If I am on a VM I will likely install gentoo-kernel-bin, but the dist-kernel USE flag will pull in gentoo-kernel by default as a dependency if I just emerged the firmware packages alone.

[14]

If I forget to check this, it isn't the end of the world. I have done this before and it prevented me from starting sway. However the fix was straightfoward enough: ssh in, modify the kernel config to enable intel DRM, recompile/reinstall, and reboot.

[15]

I am pulling in ncurses here to get the terminfo database.

[16]

As I run install via my org document in emacs, I need to clean up all of the tramp connections before trying a umount.