Skip to content

Gentoo Stage3 Installation with Encrypted Root

Follow this detailed guide by wuseman to install Gentoo Linux with a Stage3 image, setting up encrypted root and swap partitions protected by a GPG key. This tutorial provides step-by-step instructions for configuring LUKS, creating LVM structures, and optimizing Portage for efficient package management.

Here the entire procedure is copied directly from history from 2023-05-09


HP EliteDesk 800 G3 DM 65W/829A, BIOS P21 Ver. 02.46 03/28/2023

* Manufacturer...: Hewlett Packard
* Model..........: Elitedesk 800 G3 DM 65W/829A
* CPU............: Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
* HDD............: KINGSTON SA400S37240G
* GPU............:`Intel Mesa Intel(R) HD Graphics 530 (SKL GT2) (0x1912)

Set scaling_governor to performance

echo "performance" > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

Create partitions

parted -a optimal /dev/sdX -s "mklabel gpt"
parted -a optimal /dev/sdX -s "mkpart 1 1 2"
parted -a optimal /dev/sdX -s "mkpart 2 2 1000"
parted -a optimal /dev/sdX -s "mkpart 3 1000 -1"
parted -a optimal /dev/sdX -s "set 1 bios_grub on"
parted -a optimal /dev/sdX -s "set 2 boot on"
parted -a optimal /dev/sdX -s "set 2 esp on"

Create folders for install/tmp

mkdir -v -p  /mnt/{gentoo,tmp}

Creating a Password-Protected Keyfile for LUKS

We will next create a (pseudo) random keyfile (for use with LUKS). This keyfile will be encrypted with GPG (using a typed-in passphrase) and then stored on the USB key.

The point of this is to establish dual-factor security - both the (encrypted) keyfile, and your passphrase (to decrypt it) will be required to access the LUKS data stored on the target machine's hard drive.

This means that even if a keylogger is present, should the machine be stolen - powered down but without the USB key - the LUKS data will still be safe (as the thief will not have your encrypted keyfile). Similarly, (assuming no keylogger!) if your machine were to be stolen powered down but with the USB key still in it, it will also not be possible to access your LUKS data (as in this case the thief will not know your passphrase).

We need to set the GPG_TTY variable here, otherwise gpg's pinentry password system may misbehave. If you are connecting over ssh, and your helper system has locale settings not available within the minimal install environment, you may get complaints about no LC_CTYPE known printed by pinentry; these can generally be ignored, and result from sshd on the target machine attempting to use the helper machine's environment

export GPG_TTY=$(tty)
dd if=/dev/urandom bs=8388607 count=1 \
 | gpg --symmetric --cipher-algo TWOFISH --output /mnt/tmp/rootfs_key-$(date +%Y%m%d).gpg

Example

gpg --decrypt /mnt/tmp/rootfs_key-$(date +%Y%m%d).gpg | cryptsetup --cipher twofish-xts-plain64 --key-size 512 \
    --hash sha512 --iter-time 5000 --use-random --type luks2 --key-file - luksFormat /dev/sda3 

Important: Create luksheader backup

If the LUKS header gets damaged, your encrypted data will be lost forever, even if you have a backup of the GPG key and passphrase. Therefore, you may wish to consider backing up this header to a separate device, and storing it securely.

cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file /mnt/tmp/elitedesk-header_backup-20230509.img

Create LVM Structure (PV->VG<-LVs)

A physical volume (PV) is an underlying storage device (for example, an actual disk partition or loopback file), which is managed by LVM. PVs have a special header, and are divided into physical extents.

A physical extent (PE) is the smallest allocatable unit of a PV. We will use the default PE size of 4MiB in this tutorial.

A logical volume (LV) is LVM's equivalent of a partition. It contains logical extents, which are mapped one-to-one onto the PEs of contributing physical volumes. Note - unlike a conventional partition, because of this architecture an LV can span multiple underlying physical volumes, and a physical volume can host multiple logical volumes, if desired. The LV appears as a standard block device, and so can be formatted with any normal Linux filesystem (e.g. ext4). We will create LVs for the root directory, the user home directory and swap in this tutorial.

A volume group (VG) is an administrative unit gathering together a collection of LVs and PVs. We will create a single VG containing a single PV, and (as just mentioned) three LVs. The main reason we're using LVM here is to provide a simple way to get three 'logical' partitions on top of a single underlying LUKS container (partition). LVM also provides a number of additional advantages when resizing, backing up, or moving partitions, in exchange for a little initial configuration overhead.

gpg --decrypt /mnt/tmp/rootfs_key-$(date +%Y%m%d).gpg | cryptsetup --key-file - luksOpen /dev/sda3 rootfs
  • Create an LVM physical volume (PV) on this partition
pvcreate /dev/mapper/rootfs 
  Physical volume "/dev/mapper/rootfs" successfully created.
  • Then, we create a volume group (VG) hosting this PV. We'll call the new VG "vg1".
vgcreate elitedesk /dev/mapper/rootfs
  Volume group "elitedesk" successfully created
  • To allow us to suspend to disk (which we'll setup later) we'll want a swap slightly larger than the size of our RAM. So first, find the size of RAM on your system with:
lvcreate --size 16G --name swap elitedesk
  Logical volume "swap" created.

Next, we'll create a relatively large LV to hold our root partition. This will eventually hold everything apart from the user home directories, nd, since this is Gentoo, we'll need a fair amount of room for portage files and so on. We'll allow 50GiB here - if you wish you can make this smaller or larger of course:

lvcreate -l100%FREE --name rootfs elitedesk
  Logical volume "rootfs" create

Display PV

pvdisplay
  --- Physical volume ---
  PV Name               /dev/mapper/rootfs
  VG Name               elitedesk
  PV Size               222.62 GiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              56991
  Free PE               0
  Allocated PE          56991
  PV UUID               tERcp7-uzb7-OJld-ohUf-oInq-HzVS-jCAlav

VG Display

vgdisplay
  --- Volume group ---
  VG Name               elitedesk
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               222.62 GiB
  PE Size               4.00 MiB
  Total PE              56991
  Alloc PE / Size       56991 / 222.62 GiB
  Free  PE / Size       0 / 0   
  VG UUID               P3QftG-dPon-p0MZ-nc56-7Zak-q9IS-xxqmLJ

LV Display

lvdisplay
  --- Logical volume ---
  LV Path                /dev/elitedesk/swap
  LV Name                swap
  VG Name                elitedesk
  LV UUID                i1ozxi-xy5B-pcag-4ALO-mqsa-btcf-n2TKP9
  LV Write Access        read/write
  LV Creation host, time livecd, 2023-05-09 14:39:26 +0000
  LV Status              available
  # open                 0
  LV Size                16.00 GiB
  Current LE             4096
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:2
   
  --- Logical volume ---
  LV Path                /dev/elitedesk/rootfs
  LV Name                rootfs
  VG Name                elitedesk
  LV UUID                MAHUP7-lTbl-hxuA-CxwL-ezRv-B2Et-4oFVCE
  LV Write Access        read/write
  LV Creation host, time livecd, 2023-05-09 14:39:49 +0000
  LV Status              available
  # open                 0
  LV Size                206.62 GiB
  Current LE             52895
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:3

Enable lvm volume

/sbin/lvm vgchange -a y elitedesk
  2 logical volume(s) in volume group "elitedesk" now active

Verify that our new lvm volume is created in /dev/mapper directory

  • You should have a new file that is named elitedesk-rootfs: /dev/mapper/elitedesk-rootfs
ls /dev/mapper

Formatting and Mounting the LVM Logical Volumes (LVs)

Create swap partitions

mkswap -L "swap" /dev/mapper/elitedesk-swap
Setting up swapspace version 1, size = 16 GiB (17179865088 bytes)
LABEL=swap, UUID=5363d720-bdbc-4a42-9ee8-3c745366e5fd

Create ext4 on rootfs

mkfs.ext4 -L "rootfs" /dev/mapper/elitedesk-rootfs

Enable swap

$ swapon -v /dev/mapper/elitedesk-swap
swapon: /dev/mapper/elitedesk-swap: found signature [pagesize=4096, signature=swap]
swapon: /dev/mapper/elitedesk-swap: pagesize=4096, swapsize=17179869184, devsize=17179869184
swapon /dev/mapper/elitedesk-swap

Mount root partition

mount -v -t ext4 /dev/mapper/elitedesk-rootfs /mnt/gentoo/
mount: /dev/mapper/elitedesk-rootfs mounted on /mnt/gentoo.

Create fat32 filesystem for our uefi partition

mkfs.vfat -F32 /dev/sdX2

Create boot partition

mkdir -v -p /mnt/gentoo/boot

Unmount boot partition with our key and mount it on boot

mount /dev/sdX2 /mnt/gentoo/boot/
  • Double-Check the Date and Time

Before downloading anything, double-check that you have the correct time and date on the target machine (you should do, as you set it up earlier, but since having an incorrect date can cause problems later, it's best to make sure now)

```bash
date 050914452023
Tue May  9 14:45:00 UTC 2023
```

Downloading, Verifying and Unpacking the Gentoo Stage 3 Tarball

  • Be sure that we really mounted /mnt/gentoo before downloading
livecd /mnt/gentoo # df
Filesystem                   1K-blocks    Used Available Use% Mounted on
none                          11932016    1428  11930588   1% /run
udev                             10240       0     10240   0% /dev
tmpfs                         11932016       0  11932016   0% /dev/shm
/dev/mapper/ventoy             3243550 3243550         0 100% /mnt/cdrom
overlay                       11932016  137204  11794812   2% /
none                          11932016  137204  11794812   2% /mnt/overlay
/dev/loop0                     3190272 3190272         0 100% /mnt/livecd
cgroup_root                      10240       0     10240   0% /sys/fs/cgroup
tmpfs                          2386400      24   2386376   1% /run/user/1000
/dev/mapper/elitedesk-rootfs 212147716      32 201298404   1% /mnt/gentoo
/dev/sda2                       972908   24604    948304   3% /mnt/gentoo/boot

Stage3 desktop

The 'Stage 3' file is a tarball containing a populated directory structure from a basic Gentoo system. Unlike the minimal installation image however, the stage 3 system contains no kernel, only binaries and libraries essential to bootstrapping.

As such, we will have to host it within a chroot from our existing (minimal install image) system, until we have recompiled all system files and libraries, built a fresh kernel, and the new system becomes self-hosting.

gentooURL=https://bouncer.gentoo.org/fetch/root/all/releases/amd64/autobuilds/
gentooURL2=20230507T164658Z/stage3-amd64-desktop-openrc-20230507T164658Z.tar.xz
gentoourl3="https://distfiles.gentoo.org/releases/amd64/autobuilds/20240728T170359Z/stage3-amd64-desktop-openrc-20240728T170359Z.tar.xz"
wget ${gentooURL}/${gentooURL3}

The last step in this stage is to unpack the tarball. Double check you are in the /mnt/gentoo directory, then issue:

tar xvJpf stage3-amd64-*.tar.xz --xattrs-include='*.*' --numeric-owner 
rm -v -f stage3-amd64-* 

Configuring /etc/portage/make.conf

cat << 'EOF' >> /mnt/gentoo/root/.bashrc
export NUMCPUS=$(nproc)
export NUMCPUSPLUSONE=$(( NUMCPUS + 1 ))
export MAKEOPTS="-j${NUMCPUSPLUSONE} -l${NUMCPUS}"
export EMERGE_DEFAULT_OPTS="--jobs=${NUMCPUSPLUSONE} --load-average=${NUMCPUS}"
EOF
cp -v /mnt/gentoo/etc/skel/.bash_profile /mnt/gentoo/root/ 
mv -v /mnt/gentoo/etc/portage/make.conf /mnt/gentoo/etc/portage/make.conf_default.bak

Configure make.conf

```bash
##################################################################################
# C, C++ and FORTRAN options for GCC.
##################################################################################
COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"

##################################################################################
# * will install any package no matter what license is being used
##################################################################################
ACCEPT_LICENSE="*"

##################################################################################
# WARNING: Changing your CHOST is not something that should be done lightly.
# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.
##################################################################################
CHOST="x86_64-pc-linux-gnu"

##################################################################################
# Use the 'stable' branch - 'testing' no longer required for Gnome 3.
# NB, amd64 is correct for both Intel and AMD 64-bit CPUs
##################################################################################
ACCEPT_KEYWORDS="~amd64"

##################################################################################
# Additional USE flags supplementary to those specified by the current profile
##################################################################################
USE="bluetooth rar zip screencast chromecast androiddump http2 \
     http3 sshdump wifi -systemd curl networkmanager pulseaudio"
CPU_FLAGS_X86="aes avx avx2 f16c fma3 mmx mmxext pclmul popcnt rdrand sse sse2 sse3 sse4_1 sse4_2 ssse3"

##################################################################################
# Important Portage directories
##################################################################################
PORTDIR="/var/db/repos/gentoo"
DISTDIR="/var/cache/distfiles"
PKGDIR="/var/cache/binpkgs"

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

##################################################################################
# Turn on logging - see http://gentoo-en.vfose.ru/wiki/Gentoo_maintenance.
##################################################################################
PORTAGE_ELOG_CLASSES="info warn error log qa"
PORTAGE_ELOG_SYSTEM="echo save"

##################################################################################
# Ensure elogs saved in category subdirectories.
# Build binary packages as a byproduct of each emerge, a useful backup.
##################################################################################
FEATURES="${FEATURES} split-elog parallel-fetch -ccache nodoc noinfo -buildpkg"

##################################################################################
# Settings for X11
# - mesa will choose the correct driver for us so we adding `iris` as well
# - Testing if iris is available: MESA_LOADER_DRIVER_OVERRIDE=iris glxinfo -B | grep -i "OpenGL renderer" 
# - If iris shows "mesa" rather then "intel" and things is broken fallback to i915 and i965
##################################################################################
VIDEO_CARDS="i915 i965 intel"
INPUT_DEVICES="libinput"

##################################################################################
# Gentoo Mirrors 
##################################################################################
GENTOO_MIRRORS="https://ftp.lysator.liu.se/gentoo/ http://ftp.lysator.liu.se/gentoo/"

##################################################################################
# QEMU Settings 
##################################################################################
QEMU_SOFTMMU_TARGETS='x86_64 aarch64 arm mips mips64 mipsel i386'
QEMU_USER_TARGETS='x86_64 aarch64 arm mips mips64 mipsel i386'

##################################################################################
# Local portage dir 
# - Since we do not use our own overlay anymore we can disable LOCAL_PORTDIR permanent
##################################################################################
# LOCAL_PORTDIR="/etc/portage/repos.conf/"

##################################################################################
# Perl features 
##################################################################################
PERL_FEATURES="ithreads"

##################################################################################
# Portage Tmpdir (this is on external drive on current setup only, avoid it on new installations) 
##################################################################################
PORTAGE_TMPDIR="/mnt/usb/.gentoo.tmp"
#PORTAGE_TMPDIR="/tmp/portage"

##################################################################################
# ccache directory 
# - Set ccache to 5G as default by: ccache -M 5G
# - Confirm that ccache is really used: emerge --info | grep -i ccache
# - emerge dev-util/ccache is required for `ccache`
# - When using ccache its powerful to set: CCACHE_DIR="/tmp/ccache" (use ramdisk for faster speeds)
# - When using ramdisk on 12GB in total size we can se ccache to 3G: 
# - Set CCACHE_DIR to 3G: CCACHE_DIR=/tmp/ccache ccache -M 3G
##################################################################################
CCACHE_DIR="/tmp/ccache"

##################################################################################
# sys-boot/grub:2 tips and tricks
# - GRUB_PLATFORMS=efi-64 // Since we run efi-64 we add GRUB_PLATFORM to `efi-64` permanent
##################################################################################
GRUB_PLATFORMS=efi-64
EOF
```

Copy resolv.conf to /etc/ (needed for get internet access)

livecd /mnt/gentoo # cp -v -L /etc/resolv.conf /mnt/gentoo/etc/ 
'/etc/resolv.conf' -> '/mnt/gentoo/etc/resolv.conf'

Create folders for portage

livecd /mnt/gentoo # 
mkdir -p -v /mnt/gentoo/etc/portage/package.{use,mask,unmask,license,accept_keywords}
mkdir: created directory '/mnt/gentoo/etc/portage/package.unmask'
mkdir: created directory '/mnt/gentoo/etc/portage/package.license'

Prepare for configuring timezone-data

rm -v /mnt/gentoo/etc/localtime

Configure keymap

sed -i 's/us/sv-latin1/g' /mnt/gentoo/etc/conf.d/keymaps

Prepare kernel, initramfs and bootloader install

cat << "EOF" > /mnt/gentoo/etc/portage/package.use/use
#################################
##  useFlags                  ###
#################################
sys-kernel/gentoo-sources symlink
sys-kernel/genkernel cryptsetup
# sys-boot/grub:2 device-mapper # Grub
app-portage/eix doc
EOF

Configure source mirrors

mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf 

Next, setup a */mnt/gentoo/etc/portage/repos.conf/gentoo.conf file (this specifies information about repositories in the system to Portage; see the earlier overview for a brief primer on the concepts involved). Issue:

```bash
mkdir -p -v /mnt/gentoo/etc/portage/repos.conf
cp -v /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf

```

Mounting necessary the chroot

After this is done, although we will still be running the minimal install kernel pro tem, commands issued from within the chroot-ed shell will only be able to 'see' and use files (including, but not limited to, executables, libraries, and configuration files) that lie within the stage 3 file struc ure we just unpacked (except for the special /proc, /sys and /dev directories, of course).

Enter the chroot, using bash as the shell; Reload some settings, using source; and Redefine the console prompt (to remind us we are in a chroot).

mount --rbind /dev /mnt/gentoo/dev; sleep 0.5
mount --make-rslave /mnt/gentoo/dev; sleep 0.5
mount -t proc /proc /mnt/gentoo/proc; sleep 0.5
mount --rbind /sys /mnt/gentoo/sys; sleep 0.5
mount --make-rslave /mnt/gentoo/sys; sleep 0.5
mount --rbind /tmp /mnt/gentoo/tmp; sleep 0.5
mount --bind /run /mnt/gentoo/run; sleep 0.5

Entering the chroot

We're now ready to change root (chroot), thereby entering our new system. After this is done, although we will still be running the minimal install kernel pro tem, commands issued from within the chroot-ed shell will only be able to 'see' and use files (including, but not limited to, executables, libraries, and configuration files) that lie within the stage 3 file structure we just unpacked (except for the special /proc, /sys and /dev directories, of course).

```bash
chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) $PS1"
```

Sync portage tree

emerge-webrsync

Configure timezone

emerge --config timezone-data
echo "Europe/Stockholm" > /etc/timezone 

Upgrade portage

emerge --ask --verbose --oneshot portage

Install kernel/initramfs and bootloader

echo "GRUB_PLATFORMS=efi-64" >> /etc/portage/make.conf
emerge --ask sys-kernel/gentoo-sources sys-kernel/genkernel sys-boot/grub:2

Create backup of default genkernel.conf

mv -v /etc/genkernel.conf /etc/genkernel.conf.bak

Genkernel

Create genkernel.conf

cat << "EOF" > /etc/genkernel.conf
# =========Common Command Line Option Defaults=========

INSTALL="yes"
OLDCONFIG="yes"
MENUCONFIG="yes"
MRPROPER="yes"
CLEAN="yes"
MOUNTBOOT="yes"
SYMLINK="no"
SAVE_CONFIG="yes"
NOCOLOR="false"
CLEAR_CACHEDIR="no"
POSTCLEAR="no"
CHECK_FREE_DISK_SPACE_BOOTDIR=0
CHECK_FREE_DISK_SPACE_KERNELOUTPUTDIR=0
MAKEOPTS="$(portageq envvar MAKEOPTS)"
#NICE=10
BCACHE="no"
LVM="yes"
LUKS="yes"
GPG="yes"
KEYCTL="no"
MICROCODE="intel"
MICROCODE_INITRAMFS="no"
NFS="no"
DMRAID="no"
SSH="no"
B2SUM="no"
BUSYBOX="yes"
MDADM="no"
#MDADM_CONFIG="/etc/mdadm.conf"
MULTIPATH="no"
ISCSI="no"
E2FSPROGS="no"
UNIONFS="no"
ZFS="no"
BTRFS="no"
XFSPROGS="no"
FIRMWARE="yes"
FIRMWARE_INSTALL="yes"
FIRMWARE_DIR="/lib/firmware/"
FIRMWARE_FILES="rtlwifi/rtl8192eu_nic.bin,i915/skl_dmc_ver1_27.bin,regulatory.db,regulatory.db.p7s"
BOOTLOADER="grub2"
#SANDBOX="yes"
#BOOTFONT="none"
SPLASH="no"
SPLASH_THEME="gentoo"
#MODULEREBUILD="yes"
#CMD_CALLBACK=""

# =========Keymap Settings=========

DOKEYMAPAUTO="no"
KEYMAP="no"

# =========Low Level Compile Settings=========

#KERNEL_AS="as"
#KERNEL_AR="ar"
#KERNEL_CC="gcc"
#KERNEL_LD="ld"
#KERNEL_NM="nm"
#KERNEL_MAKE="make"
#UTILS_AS="as"
#UTILS_AR="ar"
#UTILS_CC="gcc"
#UTILS_CXX="g++"
#UTILS_LD="ld"
#UTILS_NM="nm"
#UTILS_MAKE="make"
#CROSS_COMPILE=""
#KERNEL_MAKE_DIRECTIVE_OVERRIDE="fooImage"
#KERNEL_BINARY_OVERRIDE="arch/foo/boot/bar"

# =========GENKERNEL LOCATION CONFIGURATION============

# Default
# -----------------------------------------------------
# TMPDIR="/var/tmp/genkernel"
# Since we use tmpfs on /tmp lets use /tmp instead
# -----------------------------------------------------
TMPDIR="/tmp/genkernel"

# -----------------------------------------------------
# Keep cache dir on our main drive to avoid compiling each time
# -----------------------------------------------------
CACHE_DIR="/var/cache/genkernel"
BOOTDIR="/boot"
GK_SHARE="${GK_SHARE:-/usr/share/genkernel}"
DISTDIR="${GK_SHARE}/distfiles"
LOGFILE="/var/log/genkernel.log"
LOGLEVEL=2

# =========COMPILED UTILS CONFIGURATION============

DEFAULT_KERNEL_SOURCE="/usr/src/linux"
DEFAULT_KERNEL_CONFIG="/usr/src/linux/.config"
#BUSYBOX_CONFIG="/path/to/file"

# =========MISC KERNEL CONFIGURATION============

#KERNEL_FILENAME="vmlinuz-%%KV%%"
#KERNEL_SYMLINK_NAME="kernel"
#KERNEL_LOCALVERSION="-%%ARCH%%"
#KERNEL_SOURCES="yes"
#BUILD_STATIC="no"
#GENZIMAGE="no"
#KERNCACHE="/path/to/file.tar.xz"
#KERNEL_MODULES_PREFIX=""

# =========MISC INITRAMFS CONFIGURATION============

#INITRAMFS_FILENAME="initramfs-%%KV%%.img"
#INITRAMFS_SYMLINK_NAME="initramfs"
#ALLRAMDISKMODULES="no"
RAMDISKMODULES="yes"
#MINKERNPACKAGE="/path/to/file.tar.xz"
#AMODULES_group="module-to-include another-module"
#MODULES_group1="some-module"
#MODULES_group2="" 
#LINUXRC="/path/to/custom/linuxrc"
#MODULESPACKAGE=""
#INITRAMFS_OVERLAY=""
#INTEGRATED_INITRAMFS="no"
COMPRESS_INITRD="yes"
COMPRESS_INITRD_TYPE="fastest"
#WRAP_INITRD=no
#NETBOOT="no"

# =========MISC BOOT CONFIGURATION============

REAL_ROOT="/dev/mapper/elitedesk-rootfs"

Kernel

Manually build the kernel

make -j$(nproc)
make modules_install
make install

Create kernel with genkernel

  • Create only Initramfs (when building kernel manually)
genkernel --config=/etc/genkernel.conf --kernel-config=/usr/src/linux/.config --no-clean --lvm --luks --loglevel=2 initramfs
  • Initramfs and Kernel
genkernel --config=/etc/genkernel.conf --kernel-config=/usr/src/linux/.config --no-clean --lvm --luks --loglevel=2 all
  • It is possible to use different themes, here is previews for menuconfig
make MENUCONFIG_COLOR=blackbg menuconfig
  • Available themes by default
* mono       => Selects colors suitable for monochrome displays
* blackbg    => Selects a color scheme with black background 
* classic    => Theme with blue background. The classic look
* bluetitle  => A LCD friendly version of classic. (default) 

Configure Kernel and Grub / Tips and Tricks

  • Find the right usb driver for usb bluetooth if used

Find the right drivers to configure for usb drives

awk -vRS= '/Vendor=0a12/{print $0,"\n"}' /sys/kernel/debug/usb/devices

Configure /etc/default/grub

Use no quotes in EOF to configure grub by copy and paste, differnet method to show alternatives how to grab uuid is used in this part

# Get UUIDs
cryptUUID="$(find /dev/disk/by-uuid -lname '*/sda3' -printf %f)"
bootUUID="$(find /dev/disk/by-uuid -lname '*/sda2' -printf %f)"
realRootUUID="$(blkid -o value -s UUID /dev/mapper/elitedesk-rootfs)"
#swapUUID="$(blkid -o value -s UUID /dev/mapper/elitedesk-swap)"

# Check if variables are set properly
if [[ -z "$cryptUUID" || -z "$bootUUID" || -z "$realRootUUID" ]]; then
    echo "Error: Failed to get one or more UUIDs."
    exit 1
fi

Backup existing grub file

  • Do not forget to install sys-boot/os-prober
cp /etc/default/grub /etc/default/grub.backup.$(date +%Y%m%d)

Update /etc/default/grub

cat << "EOF" > /etc/default/grub
# Set by distributors of GRUB to their identifying name. This is used to generate more informative menu entry titles.
GRUB_DISTRIBUTOR="Gentoo"

# The default menu entry. This may be a number, in which case it identifies the Nth entry in the generated menu counted from zero, or the title of a menu entry, or the special string ‘saved’. Using the id may be useful if you want to set a menu entry as the default even though there may be a variable number of entries before it.
GRUB_DEFAULT=0

# Boot the default entry this many seconds after the menu is displayed, unless a key is pressed. The default is ‘5’. Set to ‘0’ to boot immediately without displaying the menu, or to ‘-1’ to wait indefinitely.
GRUB_TIMEOUT=10

# List of space-separated early initrd images to be loaded from ‘/boot’. This is for loading things like CPU microcode, firmware, ACPI tables, crypto keys, and so on. These early images will be loaded in the order declared, and all will be loaded before the actual functional initrd image.
GRUB_EARLY_INITRD="/intel-ucode.cpio"

# This option is unset by default, and is deprecated in favour of the less confusing ‘GRUB_TIMEOUT_STYLE=countdown’ or ‘GRUB_TIMEOUT_STYLE=hidden’.
GRUB_TIMEOUT_STYLE=menu

# Command-line arguments to add to menu entries for the Linux kernel.
# When we run main drive on USB and get the errors below we need to add
# ---------------------------------------------------------------------
#
# Error from dmesg:
#
# hostbyte=DID_ERROR
# cmd_age=50s
# I/O error, dev sdb, sector ...
#
# ---------------------------------------------------------------------
#
# Description:
#
# usb-storage.quirks=152d:0578:u to kernel commandline 
# wich tells the Linux kernel, at boot time, to apply 
# a special compatibility rule (“quirk”) to a specific USB device
# ---------------------------------------------------------------------
#
# Description:
#
# `rootdelay=10`
#
# Error booting correctly with Gentoo Linux on usb drive
# so it ends up in a failure to find the luks/lvm package
# so it fails booting and rebooting or unplugging AC is required
# but the rootdelay=10 fixing this by waiting on luks/lvm at boot
# for my usb drive
#
# ---------------------------------------------------------------------
#
# Description
#
# HP Bios have disable all settings and for get highest perfomance
# we must set "/sys/module/pcie_aspm/parameters/policy"
# to perfomance since we dont want to use default seting
#
# $ cat /sys/module/pcie_aspm/parameters/policy
#   [default] performance powersave powersupersave
#
# To force performance to be enable we need to set below in cmd line
# pcie_aspm=performance
# 
# - How the kernel treats these parameters
#
# pcie_aspm=performance
# 
#       * Keeps ASPM enabled
#       * Forces the least aggressive power-saving state
#       *Slightly lower latency than default
#       *Still allows firmware/driver involvement
#
# -
# 
# pcie_aspm=off
# 
# * Disables ASPM completely
# * Maximum stability and predictability
# * Zero PCIe power transitions
# 
#  If you specify both options above, the last one wins, 
#  but it’s confusing and bad practice.
#
# ---------------------------------------------------------------------
#
# Description
# 
# To get no suspend on USB devices and highest perfomance 
# we has to set "cat /sys/module/usbcore/parameters/autosuspend"
# to value "-1". Default is set to "2", for fix this we
# have to add the below to kernel command line
#
# usbcore.autosuspend=-1
#
# ---------------------------------------------------------------------
#grub_cmdline_linux_default="crypt_root=uuid=6917c185-a82f-42a8-b4a1-9a62902a7f19 real_root=uuid=7b0ac473-3049-4731-b7db-4ef667cfa5a1 rootfstype=ext4 dolvm loglevel=3 cpufreq.default_governor=performance usb-storage.quirks=152d:0578:u"
#grub_cmdline_linux_default="crypt_root=uuid=6917c185-a82f-42a8-b4a1-9a62902a7f19 real_root=uuid=7b0ac473-3049-4731-b7db-4ef667cfa5a1 dolvm quiet rootfstype=ext4 loglevel=3 cpufreq.default_governor=performance"

# Kernel Commandline from ChatGPT
GRUB_CMDLINE_LINUX_DEFAULT="crypt_root=UUID=6917c185-a82f-42a8-b4a1-9a62902a7f19 dolvm rd.lvm.vg=rootfs root=/dev/mapper/elitedesk-rootfs rootfstype=ext4 rootwait loglevel=3 pcie_aspm=off usbcore.autosuspend=-1 cpufreq.default_governor=performance ipv6.disable=1 energy_perf_bias=performance"

# If this option is set, it overrides both ‘GRUB_TERMINAL_INPUT’ and ‘GRUB_TERMINAL_OUTPUT’ to the same value.
#GRUB_TERMINAL=console

# Set the resolution used on the ‘gfxterm’ graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be available. The default is ‘auto’, which tries to select a preferred resolution. See gfxmode.
GRUB_GFXMODE=1920x1080

# Set to ‘text’ to force the Linux kernel to boot in normal text mode, ‘keep’ to preserve the graphics mode set using ‘GRUB_GFXMODE’, ‘widthxheight’[‘xdepth’] to set a particular graphics mode, or a sequence of these separated by commas or semicolons to try several modes in sequence. See gfxpayload.
#GRUB_GFXPAYLOAD_LINUX=

# Set a theme for use with the ‘gfxterm’ graphical terminal.
GRUB_THEME="/boot/grub/themes/gentoo_glass/theme.txt"

# Set a background image for use with the ‘gfxterm’ graphical terminal. The value of this option must be a file readable by GRUB at boot time, and it must end with .png, .tga, .jpg, or .jpeg. The image will be scaled if necessary to fit the screen. Image height and width will be restricted by an artificial limit of 16384.
#GRUB_BACKGROUND="/boot/grub/mybackground.png"

# Normally, grub-mkconfig will generate menu entries that use universally-unique identifiers (UUIDs) to identify the root filesystem to the Linux kernel, using a ‘root=UUID=...’ kernel parameter. This is usually more reliable, but in some cases it may not be appropriate. To disable the use of UUIDs, set this option to ‘true’.
#GRUB_DISABLE_LINUX_UUID=true

# If grub-mkconfig cannot identify the root filesystem via its universally-unique indentifier (UUID), grub-mkconfig can use the UUID of the partition containing the filesystem to identify the root filesystem to the Linux kernel via a ‘root=PARTUUID=...’ kernel parameter. This is not as reliable as using the filesystem UUID, but is more reliable than using the Linux device names. When ‘GRUB_DISABLE_LINUX_PARTUUID’ is set to ‘false’, the Linux kernel version must be 2.6.37 (3.10 for systems using the MSDOS partition scheme) or newer. This option defaults to ‘true’. To enable the use of partition UUIDs, set this option to ‘false’.
GRUB_DISABLE_LINUX_PARTUUID=false

# Normally, grub-mkconfig will generate top level menu entry for the kernel with highest version number and put all other found kernels or alternative menu entries for recovery mode in submenu. For entries returned by os-prober first entry will be put on top level and all others in submenu. If this option is set to ‘true’, flat menu with all entries on top level will be generated instead. Changing this option will require changing existing values of ‘GRUB_DEFAULT’, ‘fallback’ (see fallback) and ‘default’ (see default) environment variables as well as saved default entry using grub-set-default and value used with grub-reboot.
#GRUB_DISABLE_SUBMENU=y

# Play a tune on the speaker when GRUB starts. This is particularly useful for users unable to see the screen. The value of this option is passed directly to play.
#GRUB_INIT_TUNE="60 800 1"

# Unless ‘GRUB_DISABLE_RECOVERY’ is set to ‘true’, two menu entries will be generated for each Linux kernel: one default entry and one entry for recovery mode. This option lists command-line arguments to add only to the recovery menu entry, before those listed in ‘GRUB_CMDLINE_LINUX’. The default is ‘single’.
GRUB_DISABLE_RECOVERY=false

# The grub-mkconfig has a feature to use the external os-prober program to discover other operating systems installed on the same machine and generate appropriate menu entries for them. It is disabled by default since automatic and silent execution of os-prober, and creating boot entries based on that data, is a potential attack vector. Set this option to ‘false’ to enable this feature in the grub-mkconfig command.
GRUB_DISABLE_OS_PROBER=false

# If set to ‘y’, grub-mkconfig and grub-install will check for encrypted disks and generate additional commands needed to access them during boot. Note that in this case unattended boot is not possible because GRUB will wait for passphrase to unlock encrypted container.
GRUB_ENABLE_CRYPTODISK=false
EOF

Check if grub was written successfully

if [[ $? -ne 0 ]]; then
    echo "Error: Failed to write to /etc/default/grub."
    exit 1
fi

echo "GRUB configuration updated successfully."

Create a backup of default fstab

mv -v /etc/fstab /etc/fstab.bak

Setup /etc/fstab

#!/bin/bash

realRootUUID="$(blkid -o value -s UUID /dev/mapper/elitedesk-rootfs)"
bootUUID="$(find /dev/disk/by-uuid -lname '*/sda2' -printf %f)"
swapUUID="$(blkid -o value -s UUID /dev/mapper/elitedesk-swap)"

cat << EOF > /etc/fstab
UUID=${bootUUID}                 /boot           vfat            noauto,noatime                     1 2
UUID=${realRootUUID}             /               ext4            noatime                            0 1
UUID=${swapUUID}                 none            swap            sw                                 0 0
tmpfs                            /tmp            tmpfs           rw,nosuid,nodev,size=12G,mode=1777 0 0
EOF

Install & Configure bootloader (sys-boot/grub:2)

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id="Gentoo Linux"

Configure grub

$ grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.3.1-gentoo-x86_64
Found initrd image: /boot/initramfs-6.3.1-gentoo-x86_64.img
Found linux image: /boot/vmlinuz-6.3.1-gentoo
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

Remove enforcment of an complex password

sed -i 's/enforce=everyone/enforce=none/g' /etc/security/passwdqc.conf

Set root password

passwd root

Install prefered applications

emerge --ask app-editors/vim

Setup network for our first boot

# Find default network interface
nicInUse="net.$(ip route show default | awk '/default/ {print $5}')"

# Check if the interface is detected
if [[ -z "$nicInUse" ]]; then
    echo "Error: Could not determine default network interface."
    exit 1
fi

# Change to the target directory and check
cd /etc/init.d
if [[ $? -ne 0 ]]; then
    echo "Error: Failed to change to /etc/init.d directory."
    exit 1
fi

# Create symlink if it doesn't exist
if [[ ! -L "net.${nicInUse}" ]]; then
    ln -s net.lo "net.${nicInUse}"
    if [[ $? -ne 0 ]]; then
        echo "Error: Failed to create symlink for net.${nicInUse}."
        exit 1
    fi
fi

Emerge required packages

emerge --ask dhcpcd net-dns/bind-tools
if [[ $? -ne 0 ]]; then
    echo "Error: Failed to emerge required packages."
    exit 1
fi

Add service to default runlevel

rc-update add "net.${nicInUse}"
if [[ $? -ne 0 ]]; then
    echo "Error: Failed to add net.${nicInUse} to default runlevel."
    exit 1
fi

echo "Configuration completed successfully."

Generate all with genkernel

genkernel --lvm --luks --loglevel=3 --install --config=/etc/genkernel.conf --kernel-config=/usr/src/linux/.config all

Cryptsetup

Create LUKS 2 container on block device /dev/sdX.

cryptsetup --type luks2 luksFormat /dev/sdX

Add an additional passphrase to key slot 5.

cryptsetup luksAddKey --key-slot 5 /dev/sdX

Create LUKS header backup and save it to file.

cryptsetup luksHeaderBackup /dev/sdX --header-backup-file /var/tmp/NameOfBackupFile

Open LUKS container on /dev/sdX and map it to sdX_crypt.

 cryptsetup open /dev/sdX sdX_crypt

WARNING: The command in example 5 will erase all key slots. Your cannot use your LUKS container afterward anymore unless you have a backup to restore

Example 5: Erase all key slots on /dev/sdX.

cryptsetup erase /dev/sdX

Restore LUKS header from backup file.

cryptsetup luksHeaderRestore /dev/sdX --header-backup-file /var/tmp/NameOfBackupFile