/# Arch Linux Install Procedure A mostly vanilla Arch with BTRFS subvolumes and snapshotting, plus other tools that I use. Very opinionated!
-
Set the keyboard layout to standard British:
loadkeys uk
-
Connect to the wireless internet connection:
$ systemctl start systemd-networkd systemd-resolved iwd
$ iwctl
$ station wlan0 scan
$ station wlan0 get-networks
$ station wlan0 connect <SSID> # enter passphrase if prompted
$ exit
-
Update system clock:
timedatectl set-ntp true
-
Partitioning:
-
Show current partitioning scheme:
fdisk -l /dev/nvme0n1
-
Securely wipe current disk
dd if=/dev/zero of=/dev/nvme0n1 bs=4096 status=progress
-
Use
cfdisk
to interactively create two partitions: a 512M EFI System, and the rest as a Linux root (x86-64). Enter it using:cfdisk /dev/nvme0n1
-
Encrypt the main partition:
$ cryptsetup luksFormat /dev/nvme0n1p2 $ cryptsetup open /dev/nvme0n1p2 luks
-
Create EFI partition:
mkfs.vfat -F32 /dev/nvme0n1p1
-
Create root partition:
mkfs.btrfs -L ARCH /dev/mapper/luks
-
-
Create Btrfs Subvolumes:
-
Mount btrfs partition:
mount /dev/mapper/luks /mnt
-
Create subvolumes:
$ btrfs subvolume create /mnt/@ $ btrfs subvolume create /mnt/@home $ btrfs subvolume create /mnt/@pkg $ btrfs subvolume create /mnt/@snapshots
-
Unmount everything:
umount -R /mnt
-
Remount root partition:
$ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@ /dev/mapper/luks /mnt $ mkdir -p /mnt/{boot,home,var/cache/pacman/pkg,.snapshots,btrfs} $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@home /dev/mapper/luks /mnt/home $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@pkg /dev/mapper/luks /mnt/var/cache/pacman/pkg $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@snapshots /dev/mapper/luks /mnt/.snapshots $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvolid=5 /dev/mapper/luks /mnt/btrfs
-
-
Mount /boot:
mount /dev/nvme0n1p1 /mnt/boot
-
Install the OS and utilities:
pacstrap /mnt base base-devel linux linux-firmware btrfs-progs amd-ucode mesa mesa-vdpau vulkan-radeon libva-mesa-driver man-db man-pages fish neovim iwd git gnupg
-
Generate the fstab (and then optionally take a look at it to make sure it's fine):
genfstab -U /mnt >> /mnt/etc/fstab
-
Chroot into the new system:
arch-chroot /mnt
-
Change default shell to fish:
chsh -s /usr/bin/fish
, then go into it cause it's so much nicer. -
Timezone:
ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime
-
Run hwclock to generate
/etc/adjtime
:hwclock --systohc
-
Edit
/etc/locale.gen
to uncomment theen_GB.UTF-8 UTF-8
line (and the Hungarian and Romanian lines too, while you're at it), then runlocale-gen
-
Create minor configuration files:
$ localectl set-keymap --no-convert uk
$ echo LANG=en_GB.UTF-8 > /etc/locale.conf
$ echo KEYMAP=uk > /etc/vconsole.conf
$ echo adrians-{work/personal}-laptop > /etc/hostname
- Create hosts file (
/etc/hosts
) with these contents:
# /etc/hosts
127.0.0.1 localhost
::1 localhost
127.0.1.1 adrians-{work/personal}-laptop.localdomain adrians-{work/personal}-laptop
-
Create root password with:
passwd
-
Initramfs
- Change/add the following to
/etc/mkinitcpio.conf
:
# /etc/mkinitcpio.conf HOOKS=(base systemd keyboard autodetect modconf kms block sd-vconsole btrfs filesystems fsck) ... MODULES_DECOMPRESS="yes"
- Create a new initramfs
mkinitcpio -P
- Change/add the following to
-
Systemd-boot:
-
Initialize systemd-boot (none of that GRUB/ReFIND nastiness)
bootctl --esp-path=/boot install
-
Find and store the UUID of
nvme0n1p2
by running:blkid -s UUID -o value /dev/nvme0n1p2 > /boot/loader/entries/arch.conf
. -
Edit the previously created file
/boot/loader/entries/arch.conf
with the following contents (BEWARE! mitigations=off is insecure, though it will significantly increase performance on older CPUs):# /boot/loader/entries/arch.conf title Arch Linux linux /vmlinuz-linux initrd /amd-ucode.img initrd /initramfs-linux.img options cryptdevice=UUID=<UUID-OF-ROOT-PARTITION>:luks:allow-discards root=/dev/mapper/luks rootflags=subvol=@ rd.luks.options=discard rw lsm=landlock,lockdown,yama,apparmor,bpf nowatchdog nomce mitigations=off zswap.enabled=0
-
Edit the file
/boot/loader/loader.conf
:# /boot/loader/loader.conf default arch.conf
-
-
Reboot:
$ exit
$ umount -R /mnt
$ reboot
- Rejoice! 🎉
- Login with username
root
and the password you made previously
-
Start systemd serices required for networking:
systemctl start systemd-networkd.service systemd-resolved.service iwd.service
-
Temporarily configure
systemd-networkd
by editing/etc/systemd/network/25-wireless.network
and adding:
# /etc/systemd/network/25-wireless.network
[Match]
Name=wlan0
[Network]
DHCP=yes
-
Restart the services:
systemctl restart systemd-networkd.service systemd-resolved.service iwd
-
Connect to wireless network using
iwd
:
$ iwctl
$ station wlan0 scan
$ station wlan0 get-networks
$ station wlan0 connect <SSID> # enter passphrase if prompted
$ exit
- Verify with a ping:
ping -c 3 google.com
- Since we have no swap partition / file, we’ll install the cool kids zram-generator:
pacman -S zram-generator
- Create
/etc/systemd/zram-generator.conf
:
# /etc/systemd/zram-generator.conf
[zram0]
zram-size = ram
compression-algorithm = zstd
$ systemctl daemon-reload
$ systemctl start /dev/zram0
$ swapon
- Create the new user:
$ useradd -m -g users -G wheel adrian
$ passwd adrian
$ chsh -s /usr/bin/fish adrian
-
Edit
/etc/sudoers
and add this lineadrian ALL=(ALL) ALL
(afterroot ALL=(ALL) ALL
) -
Add these lines at the end of the sudoers file by running
sudo EDITOR=nvim visudo
:
## Use neovim as the editor for visudo
Defaults editor=/usr/bin/nvim
## Add asterisks when entering password
Defaults pwfeedback
- In order to make snapshotting as seamless as possible, we'll install a few helper tools:
-
Install snapper:
pacman -S snapper
-
Create snapper config:
```bash $ umount /.snapshots $ rm -r /.snapshots $ snapper -c root create-config / ```
-
For the above config, I have changed the following values:
```bash ## /etc/snapper/configs/root ALLOW_USERS="yes" TIMELINE_LIMIT_HOURLY="5" TIMELINE_LIMIT_HOURLY="10" TIMELINE_LIMIT_WEEKLY="0" TIMELINE_LIMIT_MONTHLY="0" TIMELINE_LIMIT_YEARLY="0" ```
-
Enable systemd times for automatic snapshotting and cleanup:
```bash # systemctl enable --now snapper-timeline.timer # systemctl enable --now snapper-cleanup.timer ```
-
Enable automatic pacman snapshotting:
pacman -S snap-pac
-
-
Add Chaotic-AUR for prebuilt AUR binaries! Intructions: https://aur.chaotic.cx/
-
Install support for battery, power, and thermals:
$ pacman -S acpi acpi_call acpid power-profiles-daemon $ systemctl enable —now acpid
-
Install reflector for better arch mirrors:
$ pacman -S reflector` $ nvim where/ever/config/file/is $ systemctl enable —now reflector.timer
-
Install bluetooth protocol stack packages:
$ pacman -S bluez bluez-utils $ systemctl enable —now bluetooth
-
Install support packages & drivers for printers:
$ pacman -S cups cups-pdf $ pacman -S foomatic-db-engine foomatic-db-ppds foomatic-db-nonfree foomatic-db-nonfree-ppds foomatic-db-gutenprint-ppds $ systemctl enable cups.service
-
Install SSH protocol support & sync packages:
$ pacman -S openssh rsync $ systemctl enable sshd
-
Install firewall support:
$ pacman -S firewalld $ systemctl enable firewalld
-
Enable automatic TRIM for SSD's, along with BTRFS scrub:
$ systemctl enable --now fstrim.timer $ systemctl enable --now [email protected] $ systemctl enable --now [email protected]
-
Enable automatic pacman cache deletion:
$ systemctl enable --now paccache.timer
-
Enable avahi daemon:
$ pacman -S avahi $ systemctl enable --now avahi-daemon.service
-
Install sound stuff:
pacman -S pipewire pipewire-alsa pipewire-pulse pipewire-jack pipewire-docs
- Install gnome and related packages
$ pacman -S gnome gnome-shell-extensions gnome-shell-extension-appindicator gnome-software-packagekit-plugin gnome-text-editor NetworkManager
$ pacman -S tilix powerline-fonts archlinux-appstream-data wl-clipboard
$ pacman -S nautilus-sendto nautilus-share python-nautilus seahorse-nautilus ffmpegthumbnailer webp-pixbuf-loader
$ pacman -S firefox fragments fprint foliate newsflash extension-manager-git
$ systemctl enable gdm.service
- Gnome uses NetworkManager, so will remove the previous network management to use the nice GUI interface for WiFi:
$ systemctl disable systemd-networkd.service
$ systemctl enable NetworkManager.service
- After
paru
has been installed, the additional Gnome Circle apps can be added:
$ paru -S gdm-settings-git menulibre gnome-connections
$ paru -S drawing mousai video-trimmer wike plots kooha bitstower-markets celluloid passes headlines rnote
- Install the required TPM2 packages:
$ pacman -S tpm2-tss tpm2-tools
$ sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/nvme0n1p2
- Then, change the following lines in
/boot/loader/entries/arch.conf
. NOTE!! inrd.luks.name=<UUID-OF-UNENCRYPTED-DEVICE-SUCH-AS-/dev/nvme0n1p2>=luks
theluks
at the end refers to the name of the openened device chosen at the beginning, aka/dev/mapper/luks
. I'm not sure why, but this is the only way I could get it to work correctly.
options rd.luks.name=<UUID-OF-UNENCRYPTED-DEVICE-SUCH-AS-/dev/nvme0n1p2>=luks rd.luks.options=discard,<SAME-AS-BEFORE>=tpm2-device=auto root=UUID=<UUID-OF-ENCRYPTED-DEVICE-SUCH-AS-/dev/mapper/luks> rootflags=subvol=@ rw lsm=landlock,lockdown,yama,apparmor,bpf audit=1 nowatchdog nomce mitigations=off zswap.enabled=0 quiet loglevel=3 systemd.show_status=true rd.udev.log_level=3 libahci.ignore_sss=1 sysctl.vm.swappiness=200
2.1 ...and in /etc/mkinitcpio.conf
and then remake it with sudo mkinitcpio -P
# /etc/mkinitcpio.conf
MODULES=(tpm_tis)
...
HOOKS=(base systemd keyboard autodetect modconf kms block sd-vconsole sd-encrypt btrfs filesystems fsck)
2.2 Install audit framework for AppArmor. More information can be found here https://wiki.archlinux.org/title/AppArmor and here https://wiki.archlinux.org/title/Audit_framework.
$ pacman -S audit
$ systemctl enable --now auditd.service
- you can then generate profiles for specific executables as described here: https://gitlab.com/apparmor/apparmor/-/wikis/Profiling_with_tools
- Rejoice again!
PS: steps taken mostly from here: https://gist.github.com/chrisx8/cda23e2d1fa3dcda0d739bc74f600175 and https://wiki.archlinux.org/title/Trusted_Platform_Module#systemd-cryptenroll
-
Regulatory stuff https://wiki.archlinux.org/index.php/Network_configuration/Wireless#Respecting_the_regulatory_domain
-
Add the following options to
/etc/modprobe.d/iwlwifi.conf
:options iwlwifi power_save=0 options iwlwifi disable_11ax=1 options iwlmvm power_scheme=1
-
Install
mkinitcpio-firmware
so that those super annoying warnings when remaking mkinitcpio go away. -
Enable pacman colour (which is great for the next step). Do
sudo nvim /etc/pacman.conf
and uncomment the line that says#Color
.
$ sudo pacman -S pkgstats bat ripgrep mosh tldr btop duf lsd fd python-pip git-delta zoxide units
$ sudo pacman -S noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra
$ sudo pacman -S poetry python-black python-isort python-coverage flake8
$ sudo paru -S starship gnome-shell-extension-extended-gestures-git pycharm-professional font-victor-mono cider papirus-icon-theme otf-san-francisco-mono ttf-mac-fonts ttf-yosemite-san-francisco-font-git
$ sudo paru -S whatsapp-for-linux rar btrfs-assistant bleachbit czkawka-gui
-
Docker:
$ sudo pacman -S docker docker-compose $ systemctl start docker.service $ sudo usermod -aG docker $USER $ newgrp docker $ docker run hello-world
-
Improve boot times (as far as I can tell everything is still functional after these, though you have to ensure the restart policy of the docker.service unit is set to
Restart=on-failure
):$ systemctl disable docker.service $ sudo systemctl disable NetworkManager-wait-online.service
- Btrfs defragmenting and rebalancing
$ btrfs filesystem defragment -r -v -czstd /
$ btrfs balance start -dusage=20 /
- Install CachyOS for x86-64-v3 compiled packages and optimised kernel: https://github.com/CachyOS/linux-cachyos
- update packages
- install new kernel
sudo pacman -S linux-cachyos
- remove old kernel?
sudo pacman -Rs linux
- update
/boot/loader/entries/arch.conf
to point to the new kernel images, while adding new AMD PSTATE (EPP) driverstitle Arch Linux linux /vmlinuz-linux-cachyos initrd /amd-ucode.img initrd /initramfs-linux-cachyos.img options rd.luks.name=f4d10b40-f2df-400c-b025-c66ac039aae0=luks rd.luks.options=discard,f4d10b40-f2df-400c-b025-c66ac039aae0=tpm2-device=auto root=UUID=1fd43ca3-0ccb-48a7-a688-af2ddbd7b99b rootflags=subvol=@ rw lsm=landlock,lockdown,yama,apparmor,bpf audit=1 nowatchdog nomce mitigations=off zswap.enabled=0 quiet loglevel=3 systemd.show_status=true rd.udev.log_level=3 libahci.ignore_sss=1 amd-pstate=active
- set a preference governor:
$ cpupower frequency-set -g powersave $ echo balance_performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference
- Enable systemd-oomd as described here: https://www.reddit.com/r/archlinux/comments/mk2lg6/how_to_properly_configure_systemdoomd/
- enable it with:
systemctl enable --now systemd-oomd.service
- add prelockd for further improvements to responsiveness: https://github.com/hakavlad/prelockd
- Add Firefox (and other browsers, including Brave), to RAM: https://wiki.archlinux.org/title/Firefox/Profile_on_RAM
- Keep this in mind: https://wiki.archlinux.org/index.php/System_maintenance
- This guide has been a super useful starting point: https://fogelholk.io/installing-arch-with-lvm-on-luks-and-btrfs/
- Some useful info here too: https://www.reddit.com/r/archlinux/comments/9ee872/noob_alert_arch_install_btrfs_gpt_efi/
- Similar guide, Btrfs specific: https://gist.github.com/mikroskeem/04ce5adcb63d6d20645a
- Again a similar guide, but with Snapper info: https://www.vultr.com/docs/install-arch-linux-with-btrfs-snapshotting