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).
1.2 Verify signature
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 forPartition number
andFirst sector
- Enter
+300M
forLast sector
- Type
t
and setPartition type
to1
(EFI System Partition)
- Press
- Type
n
to create the root partition :- Press
Enter
three times to use defaults forPartition number
,First sector
andLast sector
. This will use all the remaining space. - Type
t
,Enter
to select partition 2, and setPartition type
to23
(Linux Root x86-64) - Type
p
to check the layout :
- Press
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.
# 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
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
# 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
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
# 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)
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.3 Time zone
3.4 Localization
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
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.7 Root password
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
4 Reboot
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)
# 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
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
Cryptsetup's luksHeaderBackup
action stores a binary backup of the LUKS header and keyslot area :
$ sudo cryptsetup luksHeaderBackup /dev/nvme0n1p2 --header-backup-file /<safe-place>/<backup>/<file>.img
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
# 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/@
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
$ sudo pacman -S pkgstats
$ 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
$ 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
$ sudo pacman -S thermald
$ sudo systemctl enable --now thermald
$ sudo systemctl enable --now power-profiles-daemon
Disable hibernate (there is no swap to resume from):
$ sudoedit /etc/systemd/sleep.conf
-----------------------------------
AllowHibernation=no
AllowSuspendThenHibernate=no
Enable playback in totem
$ sudo pacman -S gst-libav
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
$ sudo timedatectl set-ntp true
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...
$ sudo pacman -S firewalld
$ sudo systemctl enable --now firewalld
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
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..)
$ sudo pacman -S zram-generator
$ sudoedit /etc/systemd/zram-generator.conf
--------------------------------------------
[zram0]
$ sudo systemctl enable --now systemd-oomd
Also check uresourced
$ sudoedit /etc/kernel/cmdline
------------------------------------------
[...] nowatchdog
$ sudoedit /etc/modprobe.d/blacklist.conf
------------------------------------------
blacklist iTCO_wdt
$ sudo systemctl enable fstrim.timer
$ 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\]'