Gentoo Linux Setup Guide¶
This is to document my way of installing Gentoo Linux.
Fresh Installation¶
Some useful information:
- Gentoo Handbook
- Rootfs Encryption
- Full Disk Encryption From Scratch
- SSD LUKS
- dm-crypt
- systemd/systemd-boot
Prepare partition(s) and create file systems¶
The partition layout is as follows:
/dev/nvme0n1
├── /dev/nvme0n1p1 [EFI] /efi 1 GB fat32 Bootloader
└── /dev/nvme0n1p2 [ROOT] (root) ->END luks encrypted root partition
└── rootfs / ->END btrfs root filesystem
Partition the disk as follows:
livecd ~ # fdisk /dev/nvme0n1
Welcome to fdisk (util-linux 2.41.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): g
Created a new GPT disklabel (GUID: CC35EF1A-FB56-4854-9E38-813D07344959).
Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-4000797326, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-4000797326, default 4000796671): +1G
Created a new partition 1 of type 'Linux filesystem' and of size 1 GiB.
Partition #1 contains a vfat signature.
Command (m for help): t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.
Command (m for help): n
Partition number (2-128, default 2):
First sector (2099200-4000797326, default 2099200):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2099200-4000797326, default 4000796671):
Created a new partition 2 of type 'Linux filesystem' and of size 1.9 TiB.
Command (m for help): t
Partition number (1,2, default 2):
Partition type or alias (type L to list all): 23
Changed type of partition 'Linux filesystem' to 'Linux root (x86-64)'.
Command (m for help): p
Disk /dev/nvme0n1: 1.86 TiB, 2048408248320 bytes, 4000797360 sectors
Disk model: SAMSUNG MZVLC2T0HBLD-00BLL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: CC35EF1A-FB56-4854-9E38-813D07344959
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 2099199 2097152 1G EFI System
/dev/nvme0n1p2 2099200 4000796671 3998697472 1.9T Linux root (x86-64)
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Format the EFI partition:
livecd ~ # mkfs.vfat -F 32 -n EFI /dev/nvme0n1p1
mkfs.fat 4.2 (2021-01-31)
Initialize and open the LUKS partition:
livecd ~ # cryptsetup luksFormat /dev/nvme0n1p2
WARNING!
========
This will overwrite data on /dev/nvme0n1p2 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/nvme0n1p2:
Verify passphrase:
livecd ~ # cryptsetup luksOpen /dev/nvme0n1p2 root
Enter passphrase for /dev/nvme0n1p2:
livecd ~ # cryptsetup refresh --persistent --allow-discards root
Enter passphrase for /dev/nvme0n1p2:
[!INFO] The last commant to make the
discardoption persistent. Uselsblk -Dto print information about the discarding capabilities (SSD).
Format the LUKS root partition:
livecd ~ # mkfs.btrfs -L ROOT /dev/mapper/root
btrfs-progs v6.17.1
See https://btrfs.readthedocs.io for more information.
Performing full device TRIM /dev/mapper/root (1.86TiB) ...
Label: ROOT
UUID: 4845dc3a-07fc-48df-a631-9b285d8822bb
Node size: 16384
Sector size: 4096 (CPU page size: 4096)
Filesystem size: 1.86TiB
Block group profiles:
Data: single 8.00MiB
Metadata: DUP 1.00GiB
System: DUP 8.00MiB
SSD detected: yes
Zoned device: no
Features: extref, skinny-metadata, no-holes, free-space-tree
Checksum: crc32c
Number of devices: 1
Devices:
ID SIZE PATH
1 1.86TiB /dev/mapper/root
Mount the root partition and create subvolumes:
livecd ~ # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=/ -L ROOT /mnt/gentoo
livecd ~ # mount
/dev/mapper/root on /mnt/gentoo type btrfs (rw,relatime,compress=zstd,subvolid=5,subvol=/)
livecd ~ # cd /mnt/gentoo/
livecd /mnt/gentoo # btrfs sub cr @
Create subvolume './@'
livecd /mnt/gentoo # btrfs sub cr @root
Create subvolume './@root'
livecd /mnt/gentoo # btrfs sub cr @home
Create subvolume './@home'
livecd /mnt/gentoo # btrfs sub cr @swap
Create subvolume './@swap'
livecd /mnt/gentoo # btrfs sub cr @usr_local
Create subvolume './@usr_local'
livecd /mnt/gentoo # btrfs sub cr @snapshots
Create subvolume './@snapshots'
livecd /mnt/gentoo # cd
livecd ~ # umount /mnt/gentoo
Mount the root and all other subvolumes and create the swap file:
livecd ~ # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@ -L ROOT /mnt/gentoo
livecd ~ # mkdir --parents /mnt/gentoo/efi
livecd ~ # mount -L EFI /mnt/gentoo/efi
livecd ~ # cd /mnt/gentoo/
livecd /mnt/gentoo # mkdir -p root home swap snapshots usr/local
livecd /mnt/gentoo # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@root -L ROOT /mnt/gentoo/root/
livecd /mnt/gentoo # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@home -L ROOT /mnt/gentoo/home/
livecd /mnt/gentoo # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@swap -L ROOT /mnt/gentoo/swap/
livecd /mnt/gentoo # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@usr_local -L ROOT /mnt/gentoo/usr/local/
livecd /mnt/gentoo # mount -t btrfs -o noatime,compress=zstd,ssd,subvol=@snapshots -L ROOT /mnt/gentoo/snapshots/
livecd /mnt/gentoo # lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 3.7G 1 loop /run/rootfsbase
sda 8:0 1 119.5G 0 disk
├─sda1 8:1 1 119.5G 0 part
│ ├─ventoy 253:0 0 3.8G 1 dm /run/initramfs/live
│ └─sda1 253:1 0 119.5G 0 dm
└─sda2 8:2 1 32M 0 part
nvme0n1 259:0 0 1.9T 0 disk
├─nvme0n1p1 259:6 0 1G 0 part /mnt/gentoo/efi
└─nvme0n1p2 259:7 0 1.9T 0 part
└─root 253:2 0 1.9T 0 crypt /mnt/gentoo/snapshots
/mnt/gentoo/usr/local
/mnt/gentoo/swap
/mnt/gentoo/root
/mnt/gentoo/home
/mnt/gentoo
livecd /mnt/gentoo # btrfs fi mkswapfile -s 8g swap/swapfile
create swapfile swap/swapfile size 8.00GiB (8589934592)
livecd /mnt/gentoo # swapon !$
swapon swap/swapfile
livecd /mnt/gentoo # free
total used free shared buff/cache available
Mem: 65233972 4431536 59317876 1668348 3781696 60802436
Swap: 8388604 0 8388604
Download the stage file and configure portage¶
Download the stage file (update the url):
livecd /mnt/gentoo # wget https://distfiles.gentoo.org/releases/amd64/autobuilds/20251221T154556Z/stage3-amd64-desktop-systemd-20251221T154556Z.tar.xz
livecd /mnt/gentoo # tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner -C /mnt/gentoo
Edit /mnt/gentoo/etc/portage/make.conf to include
...
COMMON_FLAGS="-march=native -O3 -pipe"
...
RUSTFLAGS="${RUSTFLAGS} -C target-cpu=native"
...
MAKEOPTS="-j8 -l10"
...
ACCEPT_LICENSE="-* @FREE @BINARY-REDISTRIBUTABLE"
...
ACCEPT_KEYWORDS="~amd64"
...
Copy DNS info and mounting the necessary filesystems:
livecd /mnt/gentoo # cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
livecd /mnt/gentoo # mount --types proc /proc /mnt/gentoo/proc
livecd /mnt/gentoo # mount --rbind /sys /mnt/gentoo/sys
livecd /mnt/gentoo # mount --make-rslave /mnt/gentoo/sys
livecd /mnt/gentoo # mount --rbind /dev /mnt/gentoo/dev
livecd /mnt/gentoo # mount --make-rslave /mnt/gentoo/dev
livecd /mnt/gentoo # mount --bind /run /mnt/gentoo/run
livecd /mnt/gentoo # mount --make-slave /mnt/gentoo/run
Chroot:
livecd /mnt/gentoo # chroot /mnt/gentoo /bin/bash
livecd / # source /etc/profile && export PS1="(chroot) ${PS1}"
Fetch the latest snapshot and choose the profile:
(chroot) / # emerge-webrsync
(chroot) / # eselect news read
(chroot) / # eselect profile list
Configuring the USE variables and updating the @world set:
(chroot) / # emerge -a1 app-portage/cpuid2cpuflags
(chroot) / # mkdir -p /etc/portage/package.{accept_keywords,license,mask,unmask,use}
(chroot) / # echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00-cpu-flags
(chroot) / # echo "*/* VIDEO_CARDS: nvidia" > /etc/portage/package.use/00-video_cards
(chroot) / # echo "*/* INPUT_DEVICES: libinput" > /etc/portage/package.use/00-input_devices
(chroot) / # emerge -avuDN @world
(chroot) / # emerge -ac
Install logv:
(chroot) / # echo app-portage/elogv | tee -a /etc/portage/package.use/elogv
(chroot) / # emerge -a --norep app-portage/elogv
and edit /etc/portage/make.conf to include
PORTAGE_ELOG_CLASSES="info log warn error"
PORTAGE_ELOG_SYSTEM="echo save"
FEATURES="... clean-logs"
Install gentoolkit, eclean-kernel, vim, and nano:
(chroot) / # echo app-portage/gentoolkit | tee -a /etc/portage/package.use/gentoolkit
(chroot) / # emerge -a --norep app-portage/gentoolkit
(chroot) / # echo app-admin/eclean-kernel | tee -a /etc/portage/package.use/eclean-kernel
(chroot) / # emerge -a --norep app-admin/eclean-kernel
(chroot) / # echo app-editors/nano | tee -a /etc/portage/package.use/nano
(chroot) / # emerge -a --norep app-editors/nano
(chroot) / # echo app-editors/vim | tee -a /etc/portage/package.use/vim
(chroot) / # emerge -a --norep app-editors/vim
(chroot) / # cat << EOF | tee -a ~/.vimrc
syntax on
filetype plugin on
filetype indent on
set noswapfile
set number
set relativenumber
EOF
Switch the default editor to vim:
(chroot) / # eselect editor list
(chroot) / # eselect editor set vim
(chroot) / # eselect vi list
(chroot) / # eselect vi set vim
Set the timezone:
(chroot) / # ln -sf ../usr/share/zoneinfo/Asia/Seoul /etc/localtime
Set the locale:
(chroot) / # vi /etc/locale.gen
(chroot) / # locale-gen
(chroot) / # eselect locale list
(chroot) / # eselect locale set en_US.utf8
(chroot) / # env-update && source /etc/profile && export PS1="(chroot) ${PS1}"
Install kernel¶
Install firmware and microcode:
(chroot) / # echo sys-kernel/linux-firmware | tee -a /etc/portage/package.use/linux-firmware
(chroot) / # emerge -a --norep sys-kernel/linux-firmware
(chroot) / # echo sys-firmware/sof-firmware | tee -a /etc/portage/package.use/sof-firmware
(chroot) / # emerge -a --norep sys-firmware/sof-firmware
(chroot) / # echo sys-firmware/intel-microcode | tee -a /etc/portage/package.use/intel-microcode
(chroot) / # emerge -a --norep sys-firmware/intel-microcode
Install the bootloader (systemd-boot):
(chroot) / # echo "sys-apps/systemd boot cryptsetup ukify" | tee -a /etc/portage/package.use/systemd
(chroot) / # emerge -a1N sys-apps/systemd
(chroot) / # bootctl install
(chroot) / # systemctl enable systemd-boot-update.service
(chroot) / # LUKS_VOLUME_UUID=<LUKS_VOLUME_UUID>
(chroot) / # cat << EOF > /etc/kernel/cmdline
init=/usr/lib/systemd/systemd
rd.luks.name="${LUKS_VOLUME_UUID}"=root
rd.luks.options=discard
root=/dev/mapper/root
rootflags=compress=zstd,subvol=/@
EOF
Edit /efi/loader/loader.conf to comment out timeout (and set it to 3, if not done so).
Install installkernel:
(chroot) / # echo sys-kernel/installkernel systemd systemd-boot dracut uki ukify | tee -a /etc/portage/package.use/installkernel
(chroot) / # emerge -a --norep sys-kernel/installkernel
(chroot) / # mkdir -p /etc/cmdline.d
(chroot) / # ln -s ../kernel/cmdline /etc/cmdline.d/00-installkernel.conf
(chroot) / # mkdir -p /etc/dracut.conf.d
(chroot) / # cat << EOF > /etc/dracut.conf.d/crypto_luks.conf
add_dracutmodules+=" crypt dm rootfs-block "
EOF
[!NOTE] To disable generating a unified kernel, remove the
uki ukifyUSE flags fromsys-apps/systemdandsys-kernel/installkernel.
This command may be needed for distribution kernel configuration (by dracut):
$ echo net-nds/rpcbind | tee -a /etc/portage/package.use/rpcbind
$ emerge -a --norep net-nds/rpcbind
Install the distribution kernel (either the binary or source variant):
(chroot) / # echo sys-kernel/gentoo-kernel-bin | tee -a /etc/portage/package.mask/dist-kernel
(chroot) / # cat << EOF | tee -a /etc/portage/package.use/dist-kernel
sys-kernel/gentoo-kernel
*/* dist-kernel
EOF
(chroot) / # emerge -a1 virtual/dist-kernel
Update the @world set to apply the new use variable:
(chroot) / # emerge -avuDN @world
Configure the system¶
Edit /etc/fstab to include:
...
LABEL="EFI" /efi vfat defaults,noatime,umask=0077,tz=UTC 1 2
LABEL="ROOT" / btrfs defaults,noatime,compress=zstd,subvol=/@ 0 1
LABEL="ROOT" /root btrfs defaults,noatime,compress=zstd,subvol=/@root 0 1
LABEL="ROOT" /home btrfs defaults,noatime,compress=zstd,subvol=/@home 0 1
LABEL="ROOT" /usr/local btrfs defaults,noatime,compress=zstd,subvol=/@usr_local 0 1
LABEL="ROOT" /snapshots btrfs defaults,noatime,compress=zstd,subvol=/@snapshots 0 1
LABEL="ROOT" /swap btrfs defaults,noatime,compress=zstd,subvol=/@swap 0 1
/swap/swapfile none swap sw
Schedule periodic fstrim run:
(chroot) / # systemctl enable fstrim.timer
Set the hostname:
(chroot) / # echo thinkpad > /etc/hostname
Install NetworkManager:
(chroot) / # cat << EOF | tee -a /etc/portage/package.use/networkmanager
net-misc/networkmanager -wext -ppp
*/* networkmanager
EOF
(chroot) / # emerge -a net-misc/networkmanager
(chroot) / # systemctl enable NetworkManager.service
Set the root password, time sync daemon, and first system setup:
(chroot) / # passwd
(chroot) / # systemd-machine-id-setup
(chroot) / # systemd-firstboot --prompt
(chroot) / # systemctl enable systemd-timesyncd.service
Install filesystem userspace programs:
(chroot) / # echo sys-block/io-scheduler-udev-rules | tee -a /etc/portage/package.use/io-scheduler-udev-rules
(chroot) / # emerge -a --norep sys-block/io-scheduler-udev-rules
(chroot) / # echo sys-fs/xfsprogs | tee -a /etc/portage/package.use/xfsprogs
(chroot) / # emerge -a --norep sys-fs/xfsprogs
(chroot) / # echo sys-fs/e2fsprogs | tee -a /etc/portage/package.use/e2fsprogs
(chroot) / # emerge -a --norep sys-fs/e2fsprogs
(chroot) / # echo sys-fs/dosfstools | tee -a /etc/portage/package.use/dosfstools
(chroot) / # emerge -a --norep sys-fs/dosfstools
(chroot) / # echo sys-fs/btrfs-progs | tee -a /etc/portage/package.use/btrfs-progs
(chroot) / # emerge -a --norep sys-fs/btrfs-progs
(chroot) / # echo sys-fs/lvm2 lvm | tee -a /etc/portage/package.use/lvm2
(chroot) / # emerge -a1N --norep sys-fs/lvm2
Install some miscellaneous programs:
(chroot) / # echo sys-apps/mlocate | tee -a /etc/portage/package.use/mlocate
(chroot) / # emerge -a sys-apps/mlocate
(chroot) / # systemctl enable updatedb.timer
(chroot) / # echo app-shells/bash-completion | tee -a /etc/portage/package.use/bash-completion
(chroot) / # emerge -a app-shells/bash-completion
Post-installation Configuration¶
Check make.conf and make adjustment¶
For example, Localization
$ cat << EOF | sudo tee -a /etc/portage/package.use/00-localization
*/* LINGUAS: en ko
*/* L10N: en ko
EOF
Considerations for minimizing SSD wear¶
[!INFO] See SSD and Portage TMPDIR on tmpfs.
-
Edit
/etc/portage/make.confto include# https://wiki.gentoo.org/wiki/SSD#Portage_TMPDIR_on_tmpfs # https://wiki.gentoo.org/wiki/Portage_TMPDIR_on_tmpfs#fstab # It is confirmed that the system reserves 32G of the /tmp storage. PORTAGE_TMPDIR=/tmpOptionally, packages that require large disk space can be built outside of the tmpfs space by following the guide and also this. For example, edit
/etc/portage/env/00-notmpfs.confto includePORTAGE_TMPDIR="/var/tmp/notmpfs"and add large packages to
/etc/portage/package.env/00-notmpfs-large_pkgs:app-office/libreoffice 00-notmpfs.conf dev-lang/rust 00-notmpfs.conf sys-devel/gcc 00-notmpfs.conf llvm-core/clang 00-notmpfs.conf llvm-core/llvm 00-notmpfs.conf www-client/firefox 00-notmpfs.conf mail-client/thunderbird 00-notmpfs.conf dev-qt/qtwebengine 00-notmpfs.conf sci-libs/tensorflow 00-notmpfs.conf -
To remap the cache directory location, create
/etc/profile.d/50-xdg_cache_home.sh:if [ ${LOGNAME} ]; then export XDG_CACHE_HOME="/run/user/${UID}/cache" fi -
Web browser profile(s) and cache on tmpfs
Install the browser component relocator:
$ echo www-misc/profile-sync-daemon | sudo tee -a /etc/portage/package.use/profile-sync-daemon $ sudo emerge -a www-misc/profile-sync-daemonClose all the browsers, start and enable the daemon:
$ systemctl --user enable --now psd $ psd p -
Userspace tool:
$ echo sys-apps/nvme-cli | sudo tee -a /etc/portage/package.use/nvme-cli $ sudo emerge -a sys-apps/nvme-cliI/O testing:
$ # if not installed $ echo sys-apps/hdparm | sudo tee -a /etc/portage/package.use/hdparm $ sudo emerge -a sys-apps/hdparm $ # end of installation $ sudo hdparm -tT --direct /dev/nvme0n1Use the simple kernel I/O scheduler: Create NVMe I/O scheduler rules file at
/etc/udev/rules.d/60-ioschedulers.rules:# Set scheduler for NVMe devices ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"
Disable btrfs quota¶
This can really slow down the filesystem performance when many snapshots are taken.
Check if its enabled:
$ sudo btrfs qgroup show /
If enabled, disable the quota function:
$ sudo btrfs quota disable /
Enable guru repository¶
Install eselect-repository and sync the repo:
$ echo app-eselect/eselect-repository | sudo tee -a /etc/portage/package.use/eselect-repository
$ sudo emerge -a app-eselect/eselect-repository
$ sudo eselect-repository enable guru
$ sudo emaint -r guru sync
Edit /etc/portage/package.mask/guru to automatically mask all packages under this repo:
*/*::guru
sshd¶
Edit /etc/ssh/sshd_config.d/50-authentication.conf to include
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication yes
dev-vcs/git¶
This may already been pulled as a dependency of other packages. This adds an extra USE flag:
$ echo dev-vcs/git keyring | sudo tee -a /etc/portage/package.use/git
$ sudo emerge -aN --norep dev-vcs/git
sudo¶
$ echo app-admin/sudo | sudo tee -a /etc/portage/package.use/sudo
$ sudo emerge -a --norep app-admin/sudo
$ sudo visudo
and edit visudo to grant the users in the wheel group the sudoer priviliage.
System monitoring programs¶
$ echo sys-process/procps modern-top | sudo tee -a /etc/portage/package.use/procps
$ sudo emerge -a1N sys-process/procps
$
$ cat << EOF | sudo tee -a /etc/portage/package.use/htop
sys-process/htop delayacct hwloc lm-sensors
# dependencies
sys-apps/lm-sensors contrib sensord
EOF
$ sudo emerge -a --norep sys-process/htop
$
$ echo sys-process/iotop | sudo tee -a /etc/portage/package.use/iotop
$ sudo emerge -a --norep sys-process/iotop
$
$ sudo mkdir -p /etc/sysctl.d
$ echo "kernel.task_delayacct = 1" | sudo tee -a /etc/sysctl.d/50-task_delayacct.conf
Reboot the system for the new kernel config to take effect.
snapper¶
$ echo app-backup/snapper | sudo tee -a /etc/portage/package.use/snapper
$ sudo emerge -a --norep app-backup/snapper
$ sudo systemctl enable --now snapper-cleanup.timer
Follow Configuration to setup new snapper configurations.
[!NOTE] Comment out the
QGROUPsetting from all configuration files at/etc/snapper/configs/<for_each_config>.If the btrfs quota is enabled (check with
sudo btrfs qgroup show /), then disable it usingsudo btrfs quota disable /.
Follow Rollback to add the snapshot rollback support.
Follow Tips and tricks for automatic snapshoting during installations by portage.
systemd-homed¶
[!NOTE] See systemd-homed.service regarding migration to another host.
Add USE flags (the newline is intentional), update the @world set, and reload the systemd process:
$ cat << EOF | sudo tee -a /etc/portage/package.use/systemd
# systemd-homed
sys-auth/pambase homed
sys-apps/systemd cryptsetup homed
EOF
$ sudo emerge -avuDN @world
$ systemctl daemon-reexec # or systemctl soft-reboot
Enable the systemd-homed service:
$ sudo systemctl enable --now systemd-homed
The Name Service Switch needs to be imformed to use systemd for authenticating users.
Confirm that /etc/nsswitch.conf contains something like this
passwd: files systemd
shadow: files systemd
group: files systemd
See the homectl and userdbctl manpages for reference.
Create a new user:
$ sudo homectl create UNAME --alias=ALIAS \
-c "Real Name" --email-address=EMAIL \
--uid=1000 -G audio,input,video,wheel \
--ssh-authorized-keys="@$HOME/.ssh/authorized_keys" \
--recovery-key=on --storage=subvolume
Or, with a luks-based storage combined with a btrfs filesystem type:
$ sudo homectl create UNAME --alias=ALIAS \
-c "Real Name" --email-address=EMAIL \
--uid=1000 -G audio,input,video,wheel \
--ssh-authorized-keys="@$HOME/.ssh/authorized_keys" \
--recovery-key=on --storage=luks --fs-type=btrfs \
--luks-extra-mount-options=noatime
Set the keymap options:
$ localectl set-x11-keymap us "" "" caps:ctrl_modifier
Generate the ssh key:
$ ssh-keygen -t ed25519 -C "your_email@example.com"
Google authenticator PAM module¶
Following the instruction, install the necessary packages:
$ echo sys-auth/google-authenticator | sudo tee -a /etc/portage/package.use/google-authenticator
$ sudo emerge -a --norep sys-auth/google-authenticator
$ echo media-gfx/qrencode | sudo tee -a /etc/portage/package.use/qrencode
$ sudo emerge -a --norep media-gfx/qrencode
The second package is optional.
Edit /etc/ssh/sshd_config.d/50-authentication.conf to include
UsePAM yes
And, add the following line to /etc/pam.d/sshd (to the front):
auth required pam_google_authenticator.so
Generate the secret by following this.
firewalld¶
$ cat << EOF | sudo tee -a /etc/portage/package.use/firewalld
net-firewall/firewalld -gui
# required by net-firewall/firewalld-2.4.0::gentoo[python_single_target_python3_13]
# required by net-firewall/firewalld (argument)
>=net-firewall/nftables-1.1.6 json python xtables
EOF
$ sudo emerge -a net-firewall/firewalld
$ sudo systemctl enable --now firewalld
docker¶
-
Install
dockerand cli programs:$ cat << EOF | sudo tee -a /etc/portage/package.use/docker # installed app-containers/docker-cli app-containers/docker-compose app-containers/docker btrfs cuda # depencencies app-containers/containerd btrfs device-mapper EOFBecause of circular dependencies, these packages may need to be emerged first by temporarily turning off USE flags and the second time after enabling the USE flags.
$ # disable USE flags $ sudo emerge -a --norep app-containers/docker $ # re-enable USE flags $ sudo emerge -a1N app-containers/docker $ sudo emerge -a --norep app-containers/docker-cli app-containers/docker-compose -
Add relevant users to the
dockergroup:$ sudo homectl update $USER -G $(groups | sed -e "s/${USER}/docker/" -e 's/ \+/,/g')[!INFO] The shenanigan at the
-Gargument is because there is no "append" option and as such thehomectl updateis destructive. The hack is using the fact thatgroupsreturns the current groups which$USERis a member of including the group with the same name as$USER. It appears that the$USERneeds not be explicitly added to the list. -
Set the docker storage driver to use btrfs:
$ sudo mkdir -p /etc/docker/ $ cat << EOF | sudo tee -a /etc/docker/daemon.json { "storage-driver": "btrfs" } EOF -
Enable ip forwarding persistently:
$ sudo mkdir -p /etc/sysctl.d $ echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.d/50-ip_forward.conf -
Run the docker daemon:
$ sudo systemctl enable --now docker.service
See Usage for general use.
GNU Stow¶
$ echo app-admin/stow | sudo tee -a /etc/portage/package.use/stow
# sudo emerge -a app-admin/stow
Brandon Invergo thumbs its usage up well in this blog.
pass¶
Additional Info: GnuPG
-
Install
pass$ echo app-admin/pass importers | sudo tee -a /etc/portage/package.use/pass # sudo emerge -a app-admin/passAdditional supporting programs are also available.
-
Initialize password store
$ # create GPG key pair if not done so $ gpg --full-generate-key # answer a few basic questions $ gpg --list-keys # check which key to use $ pass init <gpg_key_id> -
Optionally, sync with a git repo
$ pass git init $ pass git remote add origin <git-repo> $ pass git push -u origin <default-branch>Also see the Setting it up section of this article for syncing using git.
Hardware detection¶
-
$ echo sys-apps/dmidecode | sudo tee -a /etc/portage/package.use/dmidecode $ sudo emerge -a sys-apps/dmidecode -
$ echo sys-apps/hwinfo | sudo tee -a /etc/portage/package.use/hwinfo $ sudo emerge -a sys-apps/hwinfo -
$ echo sys-apps/hdparm | sudo tee -a /etc/portage/package.use/hdparm $ sudo emerge -a sys-apps/hdparm -
$ echo sys-apps/lshw | sudo tee -a /etc/portage/package.use/lshw $ sudo emerge -a sys-apps/lshw -
$ cat << EOF | sudo tee -a /etc/portage/package.use/pciutils sys-apps/pciutils sys-apps/hwdata EOF $ sudo emerge -a sys-apps/pciutils sys-apps/hwdata -
$ echo sys-apps/usbutils | sudo tee -a /etc/portage/package.use/usbutils $ sudo emerge -a sys-apps/usbutils -
$ echo sys-apps/lm-sensors | sudo tee -a /etc/portage/package.use/lm-sensors $ sudo emerge -a sys-apps/lm-sensors -
$ echo sys-apps/i2c-tools | sudo tee -a /etc/portage/package.use/i2c-tools $ sudo emerge -a sys-apps/i2c-tools -
Userspace system daemon to enable security levels for Thunderbolt 3
$ echo sys-apps/bolt | sudo tee -a /etc/portage/package.use/bolt $ sudo emerge -a sys-apps/bolt
Power management¶
See Power management/Guide, Power management, Power management/Processor, and Power management/Soundcard.
To make use of Intel's Linux thermal daemon you first need to emerge sys-power/thermald:
$ echo sys-power/thermald | sudo tee -a /etc/portage/package.use/thermald
$ sudo emerge -a --norep sys-power/thermald
$ sudo systemctl enable --now thermald
Power management daemons
For detailed settings, see the relevant guides here.
-
TLP is similar to
laptop-mode-toolsbut aims to work out of the box with safe, modern defaults.$ echo sys-power/tlp | sudo tee -a /etc/portage/package.use/tlp $ sudo emerge -a --norep sys-power/tlp # sudo systemctl enable --now tlp -
Using Laptop Mode Tools
$ echo app-laptop/laptop-mode-tools | sudo tee -a /etc/portage/package.use/laptop-mode-tools $ sudo emerge -a --norep app-laptop/laptop-mode-tools $ sudo systemctl enable --now laptop-mode.serviceINFO: Users should distinguish laptop_mode, a kernel feature and laptop-mode-tools, a package.
-
power-profiles-daemonmodify system behavior using profiles. There are 3 different power profiles, "balanced", "power-saver", and "performance".$ echo sys-power/power-profiles-daemon | sudo tee -a /etc/portage/package.use/power-profiles-daemon $ sudo emerge -a --norep sys-power/power-profiles-daemon $ sudo systemctl enable --now power-profiles-daemon
Window Managers¶
Pipewire and Wireplumber¶
Note:
- Ensure
media-sound/pulseaudio-daemonis not installed. This is necessary to avoid issues resulting from running more than one sound server. - Ensure
media-libs/libpulseis installed, which will allow PipeWire to emulate a PulseAudio sound server. Not many applications currently support PipeWire's native API. - Ensure the
pulseaudioUSE flag is still set globally.
Set pulseaudio globally, set the package USE flags, and
emerge the @world set (these new USE flags pull automatically the needed packages):
$ cat << EOF | sudo tee -a /etc/portage/package.use/pipewire
media-video/pipewire echo-cancel extra ffmpeg flatpak man pipewire-alsa sound-server
*/* pulseaudio
EOF
$ sudo emerge -avuDN @world
Now, set the pipewire USE flag globally and re-emerge the @world set.
This is due to avoid circular dependency.
Enable services and sockets:
$ systemctl --user enable --now pipewire-pulse.socket
$ systemctl --user enable --now pipewire.service
$ systemctl --user enable --now wireplumber.service
Add the user to the pipewire group:
$ sudo homectl update $USER -G $(groups | sed -e "s/audio//" -e "s/${USER}/pipewire/" -e 's/ \+/,/g')
[!INFO] For the best experience with fast user switching, it is recommended that you remove your user from the
audiogroup.
Bluetooth¶
See Bluetooth, Bluetooth input devices, and Bluetooth headset.
[!INFO] Bluetooth support can be enabled system-wide by setting the USE variable to
bluetooth.
Install BlueZ (should have already been pulled by pipewire) and
start the daemon:
$ cat << EOF | sudo tee -a /etc/portage/package.use/bluez
net-wireless/bluez man experimental
*/* bluetooth
EOF
$ sudo emerge -a1N --norep net-wireless/bluez
$ sudo emerge -avuDN @world # to apply the global bluetooth USE flag
$ sudo systemctl enable --now bluetooth
Enabling battery reporting
- The
experimentalUSE flag needs to be enabled innet-wireless/bluez. -
Edit
/etc/bluetooth/main.confto include[General] Experimental=true -
Restart the daemon
$ sudo systemctl restart bluetooth
Device pairing
See Device pairing.
Wake from suspend
See Wake from suspend.
Utilities
$ echo net-wireless/bluez-tools | sudo tee -a /etc/portage/package.use/bluez
$ sudo emerge -a --norep net-wireless/bluez-tools
Nvidia¶
See NVIDIA and NVIDIA/nvidia-drivers.
Edit /etc/portage/package.use/00-video_cards to include:
*/* VIDEO_CARDS: -* nvidia
Install NVIDIA drivers:
$ echo x11-drivers/nvidia-drivers kernel-open | sudo tee -a /etc/portage/package.use/nvidia-drivers
$ sudo emerge -a --norep x11-drivers/nvidia-drivers
Enable the nvidia USE flag globally and emerge the @world set:
$ echo "*/* nvidia" | sudo tee -a /etc/portage/package.use/nvidia-drivers
$ sudo emerge -avuDN @world
The user(s) needing to access the video card will need to be added to the video group:
$ sudo homectl update $USER -G $(groups | sed -e "s/video//" -e "s/${USER}/video/" -e 's/ \+/,/g')
Note that users will be able to run X without permission to the DRI subsystem, but hardware acceleration will be disabled. For Wayland sessions not setting this may result in a very low FPS.
Optional: Dracut configuration
[!INFO] When using Dracut, it may be worthwhile to ensure that the NVIDIA modules are not bundled in the generated ramdisk (initramfs) image. Otherwise, every update may require regeneration of the image.
Edit /etc/dracut.conf.d/nvidia_omit_modules.conf to include
# Omit the nvidia driver from the ramdisk, to avoid needing to regenerate
# the ramdisk on updates.
omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm "
Optional: PCI-Express Runtime D3 (RTD3) Power Management
Edit /etc/udev/rules.d/80-nvidia-pm.rules to include:
# Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
# Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
And edit /etc/modprobe.d/nvidia-pm.conf to include:
# Enable RTD3
options nvidia NVreg_DynamicPowerManagement=0x02
Flatpak¶
Install flatpak:
$ cat << EOF | sudo tee -a /etc/portage/package.use/flatpak
sys-apps/flatpak
*/* flatpak
EOF
$ sudo sudo emerge -a --norep sys-apps/flatpak
Add the flathub repo:
$ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
Install Flatseal:
$ sudo flatpak install com.github.tchx84.Flatseal
Enable flatpak update timer:
$ sudo systemctl enable --now flatpak-update.timer
For theming, see Theming and Flatpak documentiation.
Also, when certain flatpak applications fail to access proper cursor, see this guide.
See below for installing portals.
XDG Desktop Portals¶
$ cat << EOF | sudo tee -a /etc/portage/package.use/xdg-desktop-portal
gui-libs/xdg-desktop-portal-wlr
sys-apps/xdg-desktop-portal-gtk
EOF
$ sudo emerge -a --norep gui-libs/xdg-desktop-portal-wlr sys-apps/xdg-desktop-portal-gtk
Fonts¶
A variety of fonts are provided by the media-fonts package category.
In particular,
$ echo media-fonts/fonts-meta cjk ms | sudo tee -a /etc/portage/package.use/fonts-meta
$ cat << EOF | sudo tee -a /etc/portage/package.license/fonts-meta
media-fonts/mikachan-font-otf free-noncomm
media-fonts/corefonts MSttfEULA
EOF
$ sudo emerge -a --norep media-fonts/fonts-meta
Google's "Noto" typeface family for fallback (it appears that these are automatically pulled by fonts-meta):
$ cat << EOF | sudo tee -a /etc/portage/package.use/noto
media-fonts/noto
media-fonts/noto-cjk
media-fonts/noto-emoji
EOF
$ sudo emerge -a --norep media-fonts/noto media-fonts/noto-cjk media-fonts/noto-emoji
$ sudo eselect fontconfig enable 75-noto-emoji-fallback.conf
Symbola:
$ echo media-fonts/ttf-ancient-fonts::guru | sudo tee -a /etc/portage/package.{unmask,use}/ttf-ancient-fonts
$ sudo emerge -a --norep media-fonts/ttf-ancient-fonts
Nerd font symbols:
$ echo media-fonts/symbols-nerd-font | sudo tee -a /etc/portage/package.use/symbols-nerd-font
$ sudo emerge -a --norep media-fonts/symbols-nerd-font
Nerd fonts:
$ echo media-fonts/nerdfonts::guru | sudo tee -a /etc/portage/package.unmask/nerdfonts
$ cat << EOF | sudo tee -a /etc/portage/package.use/nerdfonts
media-fonts/nerdfonts::guru 0xproto 3270 adwaitamono agave anonymouspro arimo atkinsonhyperlegiblemono aurulentsansmono bigblueterminal bitstreamverasansmono cascadiacode cascadiamono codenewroman comicshannsmono commitmono cousine d2coding daddytimemono dejavusansmono departuremono droidsansmono envycoder fantasquesansmono firacode firamono geistmono gohu gomono hack hasklig heavydata hermit iawriter ibmplexmono inconsolata inconsolatago inconsolatalgc intelonemono iosevka iosevkaterm iosevkatermslab jetbrainsmono lekton liberationmono lilex martianmono meslo monaspace monofur monoid mononoki mplus noto opendyslexic overpass profont proggyclean recursive robotomono sharetechmono sourcecodepro spacemono terminus tinos ubuntu ubuntumono ubuntusans victormono zedmono
EOF
$ sudo emerge -a --norep media-fonts/nerdfonts
$
$ echo media-fonts/maple-mono::guru | sudo tee -a /etc/portage/package.unmask/maple-mono
$ echo media-fonts/maple-mono::guru ligature nerd | sudo tee -a /etc/portage/package.use/maple-mono
$ sudo emerge -a --norep media-fonts/maple-mono
Terminal emulators¶
$ echo x11-terms/kitty | sudo tee -a /etc/portage/package.use/kitty
$ sudo emerge -a --norep x11-terms/kitty
$ echo x11-terms/alacritty | sudo tee -a /etc/portage/package.use/alacritty
$ sudo emerge -a --norep x11-terms/alacritty
[!TIP] To avoid
x11-terms/ghosttypulling indev-lang/zigas a dependency, emergedev-lang/zig-binwith the--oneshotoption:$ sudo emerge -a1 --norep dev-lang/zig-bin
$ echo x11-terms/ghostty man | sudo tee -a /etc/portage/package.use/ghostty
$ sudo emerge -a --norep x11-terms/ghostty
Greetd display manager¶
For TUIGreet,
$ cat << EOF | sudo tee -a /etc/portage/package.use/greetd
gui-libs/greetd man
gui-apps/tuigreet
EOF
$ sudo emerge -a --norep gui-apps/tuigreet
$ sudo systemctl enable greetd
For configuration, edit /etc/greetd/config.toml to include:
[default_session]
...
command = "tuigreet --cmd sway"
For auto-login, include
...
[initial_session]
command = "Hyprland"
user = "<UNAME>"
Sway¶
$ cat << EOF | sudo tee -a /etc/portage/package.use/sway
gui-wm/sway man swaybar swaynag tray wallpapers
EOF
$ sudo emerge -a --norep gui-wm/sway
autotiling-rs
$ echo gui-apps/autotiling-rs::guru | sudo tee -a /etc/portage/package.{unmask,use}/autotiling-rs
$ sudo emerge -a --norep gui-apps/autotiling-rs
MangoWC¶
[!NOTE] This is a guide to build from the git version.
Unmask gui-wm/mangowc::guru and gui-libs/scenefx::guru:
$ cat << EOF | sudo tee -a /etc/portage/package.unmask/mangowc
gui-wm/mangowc::guru
gui-libs/scenefx::guru
EOF
Unmask the live ebuilds:
$ cat << EOF | sudo tee -a /etc/portage/package.accept_keywords/mangowc
gui-wm/mangowc::guru **
gui-libs/scenefx::guru **
EOF
Specify the particular git commits:
$ sudo mkdir -p /etc/portage/env/gui-wm
$ echo "EGIT_COMMIT=0.10.9" | sudo tee -a /etc/portage/env/gui-wm/mangowc-9999
$ sudo mkdir -p /etc/portage/env/gui-libs
$ echo "EGIT_COMMIT=0.4.1" | sudo tee -a /etc/portage/env/gui-libs/scenefx-9999
Emerge:
$ echo gui-wm/mangowc::guru | sudo tee -a /etc/portage/package.use/mangowc
$ sudo emerge -a gui-wm/mangowc
See Live ebuilds for updating live packages.
$ sudo emerge -a1 @live-rebuild
Support programs
-
clipmanandcliphist$ echo gui-apps/clipman::guru | sudo tee -a /etc/portage/package.{unmask,use}/clipman $ sudo emerge -a --norep gui-apps/clipman $ echo app-misc/cliphist::guru | sudo tee -a /etc/portage/package.{unmask,use}/cliphist $ sudo emerge -a --norep app-misc/cliphist -
fuzzel$ echo gui-apps/fuzzel::guru | sudo tee -a /etc/portage/package.{unmask,use}/fuzzel $ sudo emerge -a --norep gui-apps/fuzzel -
rofi$ echo x11-misc/rofi | sudo tee -a /etc/portage/package.use/rofi $ sudo emerge -a --norep x11-misc/rofi -
Snapshot tools:
grimandslurp$ echo gui-apps/grim | sudo tee -a /etc/portage/package.use/grim $ sudo emerge -a --norep gui-apps/grim $ echo gui-apps/slurp | sudo tee -a /etc/portage/package.use/slurp $ sudo emerge -a --norep gui-apps/slurp -
swaync$ echo gui-apps/swaync::guru | sudo tee -a /etc/portage/package.{unmask,use}/swaync $ sudo emerge -a --norep gui-apps/swaync -
swaybg$ echo gui-apps/swaybg gdk-pixbuf | sudo tee -a /etc/portage/package.use/swaybg $ sudo emerge -a --norep gui-apps/swaybg -
swayidle$ echo gui-apps/swayidle | sudo tee -a /etc/portage/package.use/swayidle $ sudo emerge -a --norep gui-apps/swayidle -
swaylock$ echo gui-apps/swaylock | sudo tee -a /etc/portage/package.use/swaylock $ sudo emerge -a --norep gui-apps/swaylock -
swayosd$ echo gui-apps/swayosd::guru | sudo tee -a /etc/portage/package.{unmask,use}/swayosd $ sudo emerge -a --norep gui-apps/swayosd -
sway-audio-idle-inhibit$ echo gui-apps/sway-audio-idle-inhibit::guru | sudo tee -a /etc/portage/package.{unmask,use}/sway-audio-idle-inhibit $ sudo emerge -a --norep gui-apps/sway-audio-idle-inhibit -
waybar$ cat << EOF | sudo tee -a /etc/portage/package.use/waybar gui-apps/waybar backlight experimental niri tray wifi mpd EOF $ sudo emerge -a --norep gui-apps/waybar -
wlr-dpms$ echo gui-apps/wlr-dpms::guru | sudo tee -a /etc/portage/package.{unmask,use}/wlr-dpms $ sudo emerge -a --norep gui-apps/wlr-dpms -
xev$ echo x11-apps/xev | sudo tee -a /etc/portage/package.use/xev $ sudo emerge -a --norep x11-apps/xev -
xwayland-satellite$ echo gui-apps/xwayland-satellite::guru | sudo tee -a /etc/portage/package.{unmask,use}/xwayland-satellite $ sudo emerge -a --norep gui-apps/xwayland-satellite -
xdg-user-dirsandxdg-user-dirs-gtk(the latter is pulled by thegtkUSE flag)See XDG user directories.
$ echo x11-misc/xdg-user-dirs gtk | sudo tee -a /etc/portage/package.use/xdg-user-dirs $ sudo emerge -a --norep x11-misc/xdg-user-dirsLink the autostart scripts:
$ mkdir -p ~/.config/autostart $ ln -s /etc/xdg/autostart/xdg-user-dirs.desktop ~/.config/autostart/xdg_user_dirs_update.desktop $ ln -s /etc/xdg/autostart/xdg-user-dirs-gtk.desktop ~/.config/autostart/xdg_user_dirs_update_gtk.desktop
TODOs¶
[!TODO]: virt-manage and qemu, zsh, Wayland over a network, autofs Pay attention to libvirt guests' graceful shutdown setting (
libvirt-guests.serviceand/etc/libvirt/libvirt-guests.conf)