Skip to content

Instantly share code, notes, and snippets.

@mybigman
Created December 31, 2021 05:42
Show Gist options
  • Save mybigman/d0b703bdc0f8ef1e0ba0aeac2ed9183a to your computer and use it in GitHub Desktop.
Save mybigman/d0b703bdc0f8ef1e0ba0aeac2ed9183a to your computer and use it in GitHub Desktop.
Arch Linux install notes (LUKS, btrfs,...)

Arch Linux, with LUKS, btrfs, systemd-homed, systemd-oomd, zram swap, encrypted DNS

Work in Progress ! Be very careful. This has had major modifications without having been thouroughly tested afterwards

Follow all steps in Arch Installation Guide and General recommandations, with following specificities. The steps are numbered as in the Arch wiki.

  • This is NOT a full setup guide, it does NOT contain all the steps required for a functioning Arch setup. Follow the official Installation Guide, and refer to this one when at the corresponding steps (check the numbers). This is intended to help in keeping this guide current, and because one should always refer to the original documentation.
  • Read through everything first
  • This is first and foremost an attempt at a modern Arch Linux setup, and a way to store my own personal notes for my setup (laptop).

Installation Guide

1. Pre-installation

1.9 Partition the disks

1.9.1 Partition layout

UEFI with GPT

Partition Partition type Size Mount point
/dev/nvme0n1p1 EFI system partition 300 MiB /mnt/boot
/dev/nvme0n1p2 Linux x86-64 root (/) Remainder of the device /mnt

Warning: If you create a new partition table on a disk with data on it, it will erase all the data on the disk. Make sure this is what you want to do.

  • Type g to create a new GUID Partition Table and clear all current partition data.
  • Type n to create the EFI system partition :
    • Press Enter twice to use defaults for Partition number and First sector
    • Enter +300M for Last sector
    • Type t and set Partition type to 1 (EFI System Partition)
  • Type n to create the root partition :
    • Press Enter three times to use defaults for Partition number, First sector and Last sector. This will use all the remaining space.
    • Type t, Enter to select partition 2, and set Partition type to 23 (Linux Root x86-64)
    • Type p to check the layout :
Device          Start        End   Sectors   Size Type
/dev/nvme0n1p1    256      77055     76800   300M EFI System
/dev/nvme0n1p2  77056    1310714       ...    ..G Linux Root x86-64
  • If this is correct, type w to write the changes to disk.

1.9.2 Encryption setup

# cryptsetup luksFormat --label Root /dev/nvme0n1p2
# cryptsetup --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue --persistent open /dev/disk/by-label/Root root

See TRIM support for SSDs and Disable workqueue for increased performance

1.9.3 Optional: create a keyfile on a USB device

This creates a physical key, which when plugged in before boot will automatically unlock the computer, without prompting for the Luks password.

# mkfs.fat /dev/sdX -n KEYDEV
# mount /dev/sdX /mnt
# dd bs=512 count=4 if=/dev/random of=/mnt/mykeyfile iflag=fullblock
# chmod 600 /mnt/mykeyfile
# cryptsetup luksAddKey /dev/disk/by-label/Root /mnt/mykeyfile
# umount /mnt

1.10 Format the partitions

# mkfs.fat -F 32 -n ESP /dev/nvme0n1p1
# mkfs.btrfs -L Arch /dev/mapper/root

Create subvolumes

# mount /dev/mapper/root /mnt
	
# btrfs subvolume create /mnt/@
# btrfs subvolume create /mnt/@home
# btrfs subvolume create /mnt/@var_cache
# btrfs subvolume create /mnt/@var_log
# btrfs subvolume create /mnt/@var_tmp
# btrfs subvolume create /mnt/@snap_root
# btrfs subvolume create /mnt/@snap_<username>

Tip: You can create all subvolumes in one command with for i in {@,@home,@var_{cache,log,tmp},@snap_{root,<username>}}; do btrfs subvolume create /mnt/"$i"; done

See Snapper suggested layout and layout discussion

Set the default subvolume to @ :

# btrfs subvolume list /mnt/

Note the ID number for @, i.e. 256 :

# btrfs subvolume set-default 256 /mnt/ 

Unmount the toplevel subvolume

# umount /mnt

1.11 Mount the file systems

We will use zstd compression, and asynchronous discard as mount options. No need to specify them again for subvolumes other than root, as they will inherit them by design.

# mount -o compress-force=zstd,discard=async /dev/mapper/root /mnt

# mkdir -p /mnt/{boot,home,var/{cache,log,tmp}}

# mount -o subvol=@home /dev/mapper/root /mnt/home
# mount -o subvol=@var_cache /dev/mapper/root /mnt/var/cache
# mount -o subvol=@var_log /dev/mapper/root /mnt/var/log
# mount -o subvol=@var_tmp /dev/mapper/root /mnt/var/tmp

Don't forget to mount the EFI system partition

# mount /dev/disk/by-label/ESP /mnt/boot

info on discard option

2. Installation

2.2 Install essential packages

# pacstrap /mnt base linux btrfs-progs snapper nano networkmanager iwd systemd-resolvconf reflector bash-completion sudo pacman-contrib base-devel git intel-ucode sof-firmware

Tip: intel-ucode and sof-firmware are device specific (Intel)

3. Configure the system

3.1 FSTAB

Manually modify the fstab file to keep it simple. Entries for / and /boot are not necessary thanks to 1:

# nano /mnt/etc/fstab
---------------------
# Static information about the filesystems.
# See fstab(5) for details.

# <file system> <dir> <type> <options> <dump> <pass>

LABEL=Arch	/var/cache     	btrfs	rw,subvol=@var_cache	0 0
LABEL=Arch	/var/log     	btrfs	rw,subvol=@var_log	0 0
LABEL=Arch	/var/tmp     	btrfs	rw,subvol=@var_tmp	0 0

3.2 Chroot

3.5 Network Configuration

Create the hostname file:

# nano /etc/hostname
--------------------
myhostname

Enable NetworkManager (for Gnome integration) with the newer iwd backend instead of wpa_supplicant, and systemd-resolved for Name Resolution:

# systemctl enable systemd-resolved NetworkManager iwd
# systemctl mask wpa_supplicant

Enable the iwd backend by creating the following drop-in configuration file

# nano /mnt/etc/NetworkManager/conf.d/wifi_backend.conf
-------------------------------------------------------
[device]
wifi.backend=iwd

Unmount /etc/resolv.conf to create the symlink for systemd-resolved

# umount /etc/resolve.conf
# ln -sf /run/systemd/resolve/stub-resolve.conf /etc/resolve.conf

3.6 Initramfs

Modify the MODULES and HOOKS variables in /etc/mkinitcpio.conf :

# nano /etc/mkinicpio.conf 
--------------------------
MODULES=(i915 vfat)
HOOKS=(base systemd autodetect modconf block filesystems keyboard sd-vconsole sd-encrypt fsck)

Warning, MODULES=() is device specific (i915 for enabling early KMS on Intel graphics, vfat is for the USB keyfile)

For mkinitcpio to create Unified kernel images, add / modify the following lines in /etc/mkinitcpio.d/linux.preset

# nano /etc/mkinitcpio.d/linux.preset
-------------------------------------
...
ALL_microcode=(/boot/*-ucode.img)
...
default_efi_image="/boot/EFI/Linux/archlinux-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
..
fallback_efi_image="/boot/EFI/Linux/archlinux-linux-fallback.efi"
fallback_options="-S autodetect --splash /usr/share/systemd/bootctl/splash-arch.bmp"

Set the Kernel parameters :

# nano /etc/kernel/cmdline
--------------------------
root=/dev/mapper/root rootflags=compress-force=zstd,discard=async rw quiet bgrt_disable

Note: root=/dev/mapper/root is necessary despite 1, otherwise the options compress-force and discard=async will not be respected. See 2.

Optional: If a USB key-file was created, create /etc/crypttab.initramfs :

# nano /etc/crypttab.initramfs
------------------------------
# <name>      <device>      <password>              <options>
root	      LABEL=Root    /keyfile:LABEL=KEYDEV    keyfile-timeout=10s

Wait after installing the bootloader to regenerate the initramfs, so that the EFI folders are available.

3.8 Bootloader

Use bootctl to install systemd-boot into the EFI system partition by running:

# bootctl install
# systemctl enable systemd-boot-update.service

Adjust the loader configuration to disable the editor for safety reasons :

# nano /boot/loader/loader.conf
-------------------------------
editor no

Recreate the initramfs image:

# mkinitcpio -P

General recommendations

1. System Administration

1.1 Users and groups

Use systemd-homed to create a new user :

# systemctl enable --now systemd-homed
# homectl create <username>

homectl will autodetect LUKS + Btrfs, and this will create @home/_username_.homedir subvolume mounted with same flags as above (compress/discard)

1.2 Privilege elevation

# EDITOR=nano visudo /etc/sudoers.d/01_conf
----------------------------------------------
username  ALL=(ALL) ALL

# Reset environment by default
Defaults      env_reset

# Set default EDITOR to nano, and do not allow visudo to use EDITOR/VISUAL.
Defaults      editor=/usr/bin/nano, !env_editor

ref and ref

1.4 System Maintenance

Check for errors

Check for failed services / errors in log

$ systemctl --failed
$ sudo journalctl -p 3 -b

Limit logging to 6 months

$ mkdir /etc/systemd/journald.conf.d/
$ sudo nano /etc/systemd/journald.conf.d/00-journal-size.conf
-----------------------------------------------------------
[Journal]
MaxRetentionSec=6months

Backup

Cryptsetup's luksHeaderBackupaction stores a binary backup of the LUKS header and keyslot area :

$ sudo cryptsetup luksHeaderBackup /dev/nvme0n1p2 --header-backup-file /<safe-place>/<backup>/<file>.img

Snapshots

Snapper

Create a config for root and <user>.homedir :

$ sudo snapper -c root create-config /
$ sudo snapper -c <user> create-config /home/<user>.homedir/

Snapper create-config automatically creates snapshot subvolumes that are not needed for the suggested filesystem layout. Those can be deleted :

$ sudo btrfs subvolume delete /.snapshots
$ sudo btrfs subvolume delete /home/<user>.homedir/.snapshots

After deleting the subvolumes, recreate the snapshot directories to be used as mount points :

$ sudo mkdir /.snapshots
$ sudo mkdir /home/<user>.homedir/.snapshots

Edit /etc/fstab to add the snapshot lines :

# nano /mnt/etc/fstab
---------------------
[...]
LABEL=Arch	/.snapshots			btrfs	rw,subvol=@snap_root	0 0
LABEL=Arch	/home/<user>.homedir/.snapshots	btrfs	rw,subvol=@snap_<user>	0 0

Remount all entries from /etc/fstab to mount them, and check that everything went well :

$ sudo mount -a
$ findmnt | grep btrfs

Give the folders 750 permission

$ sudo chmod 750 /.snapshots
$ sudo chmod 750 /home/<user>/.snapshots 

Use the provided systemd units to start the automatic snapshot timeline :

$ sudo systemctl enable --now snapper-timeline.timer snapper-cleanup.timer

To prevent slowdowns, edit the configurations files to reduce the amount of snapshots kept, for example :

$ sudo nano /etc/snapper/configs/root
---------------------------------------
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="5"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="0"
TIMELINE_LIMIT_YEARLY="0"

Install snap-pac to take pre/post transaction snapshots automatically when using pacman :

$ sudo pacman -S snap-pac

How to restore

Manual snapshots
# sudo btrfs subvolume snapshot -r / "/.snapshots/@-$(date +%F-%R)"

To restore from a snapshot, delete the currently used @ and replace it with an earlier snapshot, and reboot

# mount -o subvolid=5 /dev/mapper/root /mnt
# btrfs subvolume delete /mnt/@
# brtfs subvolume snapshot /mnt/@snapshots/@root-(date) /mnt/@

2. Package Management

2.1 Pacman

useful scripts from pacman-contrib :

$ checkupdates
$ pacdiff

Use paccache.timer to discard unused cached versions of installed and uninstalled packages weekly with the paccache script from pacman-contrib.

To Keep only one version of cached packages instead of the default three :

$ sudo systemctl edit paccache.service
--------------------------------------
[Service]
ExecStart=
ExecStart=/usr/bin/paccache -rk1
$ sudo systemctl enable --now paccache.timer

To delete cached versions of uninstalled packages:

$ sudo paccache -ruk0

Uncomment "VerbosePkgLists" to see old and new versions of available packages, as well as "Color" and "ParallelDownloads" :

$ sudoedit /etc/pacman.conf

2.2 Repositories

$ sudo pacman -S pkgstats

2.3 Mirrors

$ sudo systemctl enable --now reflector

If reflector.service fails after boot due to NetworkManager-wait-online.service finishing too early, remove the -s switch from the NetworkManager-wait-online.service:

$ sudo systemctl edit NetworkManager-wait-online.service
--------------------------------------------------------
[Service]
ExecStart=
ExecStart=/usr/bin/nm-online -q

4. Graphical user interface

$ sudo pacman -S gnome gdm gnome-tweaks arc-gtk-theme arc-icon-theme

When prompted, choose Wireplumber over pipewire-media-session

$ sudo systmectl enable --now gdm.service
$ gsettings set org.gnome.SessionManager logout-prompt false

5. Power Management

5.2 CPU frequency scaling

$ sudo pacman -S thermald
$ sudo systemctl enable --now thermald

5.3 Laptops

$ sudo systemctl enable --now power-profiles-daemon

5.4 Suspend and hibernate

Disable hibernate (there is no swap to resume from):

$ sudoedit /etc/systemd/sleep.conf
-----------------------------------
AllowHibernation=no 
AllowSuspendThenHibernate=no 

6. Multimedia

Enable playback in totem

$ sudo pacman -S gst-libav

6.1 Sound system

Use Pipewire instead of Pulseaudio

$ sudo pacman -S pipewire-alsa pipewire-pulse

Enable WebRTC screen sharing on Wayland using Pipewire

$ sudo pacman -S xdg-desktop-portal xdg-desktop-portal-gtk

7. Networking

7.1 Clock synchronization

$ sudo timedatectl set-ntp true

7.2 DNS Security

Configure encrypted DNS

$ sudo mkdir /etc/systemd/resolved.conf.d
$ sudoedit /etc/systemd/resolved.conf.d/dnsotls.conf
-----------------------------------------------------
[Resolve]
DNS=9.9.9.9#dns.quad9.net
DNSOverTLS=yes
Domains=~.

or Nextdns, etc...

7.3 Setting up a firewall

$ sudo pacman -S firewalld
$ sudo systemctl enable --now firewalld

9. Optimization

9.2 Improving performance

2. Storage Devices

Enable Btrfs monthly scrub

$ sudo systemctl enable [email protected]

GCC can automatically detect and enable safe architecture-specific optimizations. To use this feature, first remove any -march and -mtune flags, then add -march=native. Also add -C target-cpu=native for the rust compiler. For example:

$ sudo nano /etc/makepkg.conf
-----------------------------
CFLAGS="-march=native -O2 -pipe -fno-plt ... "
...
RUSTFLAGS="-C opt-level=2 -C target-cpu=native"
...
MAKEFLAGS="-j4"
...
BUILDDIR=/tmp/makepkg

Move Firefox disk cache to ram
Move Firefox profile to ram

4.3 Hardware Video Acceleration

Warning, steps specific to my device (Intel integrated Graphics)

$ sudo pacman -S intel-media-driver libvdpau-va-gl
$ mkdir ~/.config/environment.d/01_env.conf
$ sudoedit ~/.config/environment.d/01_env.conf
----------------------------
LIBVA_DRIVER_NAME=iHD
VDPAU_DRIVER=va_gl

GPGPU

$ sudo pacman -S intel-compute-runtime ocl-icd

Vulkan

$ sudo pacman -S vulkan-intel

Configure specific applications (Firefox, etc..)

5. RAM, swap and OOM handling

$ sudo pacman -S zram-generator	
$ sudoedit /etc/systemd/zram-generator.conf
--------------------------------------------
[zram0]
$ sudo systemctl enable --now systemd-oomd

Also check uresourced

7. Watchdogs

$ sudoedit /etc/kernel/cmdline
------------------------------------------
[...] nowatchdog

$ sudoedit /etc/modprobe.d/blacklist.conf
------------------------------------------
blacklist iTCO_wdt

9.3 Solid state drives

$ sudo systemctl enable fstrim.timer

12. Console Improvements

$ sudoedit ~/.config/environment.d/01_env.conf
----------------------------
VISUAL=nano
EDITOR=nano
$ nano .bash_aliases
--------------------

alias ls='ls --color=auto'
alias diff='diff --color=auto'
alias grep='grep --color=auto'
alias mkdir='mkdir -p -v'
#alias sudo='sudo -v && sudo'

alias sublist='sudo btrfs subvolume list -t --sort=path'
alias pacdiff='sudo DIFFPROG=nano pacdiff'
alias checkupdates='checkupdates | column -t'

function cpr() {
  rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 "$@"
} 

function mvr() {
  rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 --remove-source-files "$@"
}
$ nano .bashrc
--------------
PS1='\[\e[1m\][\u@\h \W]\$ \[\e[0m\]'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment