I tend to use Fedora as my daily OS, but every once in a while I get the itch to check out Arch again. This is my collection of arch install notes I’ve accumulated over the years. Following these notes will get you a base Arch install with LUKS encryption, BTRFS, and zram swap enabled. I’ve collected all this into an Arch Install Script. The script just runs the steps outlined below.
Keep in mind these notes are based around a UEFI system with secure boot turned off.
See the Arch Install Guide for more details about the install process.
First start by syncing the system clock with
# timedatectl
You can then partition the disks. I tend to like to keep it simple with 2 partitions, 1 for boot and 1 for root respectively.
# parted --script "${device}" mklabel gpt \
mkpart efi fat32 1Mib 261MiB \
set 1 boot on \
mkpart system btrfs 261MiB 100%
This is an overview for setting up LUKS on a partition.
Find your device with lsblk
and run the following commands to encrypt the root partition.
# mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/efi
# cryptsetup -y -v luksFormat /dev/disk/by-partlabel/system
# cryptsetup open /dev/disk/by-partlabel/system root
# mkfs.btrfs -f /dev/mapper/root
Subvolumes allow for snapshots and rollbacks. There are several possible subvolume layouts, this is what I’ve settled on based on archinstaller:
# mount -t btrfs /dev/mapper/root /mnt
# btrfs subvolume create /mnt/@
# btrfs subvolume create /mnt/@home
# btrfs subvolume create /mnt/@log
# btrfs subvolume create /mnt/@pkg
# btrfs subvolume create /mnt/@snapshots
# btrfs subvolume set-default <subvol-id-of-@> /mnt
# umount -R /mnt
Now we need to mount the file system to prep for installing Arch.
I’ve chosen noatime
and compress=zstd
mount options
based on some recommendations from the original btrfs website.
# m_opts=noatime,compress=zstd
# mount btrfs -o defaults,$m_opts,subvol=@ /dev/mapper/root /mnt
# mount --mkdir -t btrfs -o defaults,$m_opts,subvol=@home /dev/mapper/root /mnt/home
# mount --mkdir -t btrfs -o defaults,$m_opts,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
# mount --mkdir -t btrfs -o defaults,$m_opts,subvol=@log /dev/mapper/root /mnt/var/log
# mount --mkdir -t btrfs -o defaults,$m_opts,subvol=@pkg /dev/mapper/root /mnt/var/cache/pacman/pkg
# mount --mkdir -t btrfs -o defaults,$m_opts,subvolid=5 /dev/mapper/root /mnt/btrfs
# mount --mkdir LABEL=EFI /mnt/boot
Update the arch mirror list with reflector
.
# reflector --latest 5 --sort rate --country US --save /etc/pacman.d/mirrorlist
Now that the drives are mounted and mirrors updated you can run pacstrap
to install the base packages and kernel.
I’ve go a selection of packages I like here, but feel free to change it up.
# pacstrap -K /mnt base base-devel linux linux-firmware linux-headers \
e2fsprogs btrfs-progs exfat-utils efibootmgr man-db man-pages \
texinfo cryptsetup networkmanager sudo ufw neovim git ${cpu}-ucode \
reflector greetd
It may be worth trying
linux-zen
if you experience UI hangs during high CPU load. Although the performance benefits are dubious.
Remember to install microcode,
amd-ucode
orintel-ucode
respectively.
Generate fstab
:
# genfstab -U /mnt >> /mnt/etc/fstab
Chroot into the new system:
# arch-chroot /mnt
Set the time zone:
# ln -sf /usr/share/zoneinfo/${region}/${city} /etc/localtime
Run hwclock
to generate /etc/adjtime
:
# hwclock --systohc
Uncomment en_US.UTF-8 UTF-8
in /etc/locale.gen
then generate the locales:
# sed -d `s/#en_US.UTF-8/en_US.UTF-8/` /etc/locale.gen
# locale-gen
Create /etc/locale.conf
and set the LANG
variable:
# echo "LANG=en_US.UTF-8" > /etc/locale.conf
Create /etc/hostname
with the name of this computer and populate the /etc/hosts
file:
# echo "${hostname}" > /etc/hostname
# cat > /mnt/etc/hosts << EOF
127.0.0.1 localhost
::1 localhost
127.0.1.1 ${hostname}.localdomain ${hostname}
EOF
Refresh initramfs
, be sure to add encrypt
to /etc/mkinitcpio.conf
:
# /etc/mkinitcpio.conf
...
HOOKS=(base udev ... block encrypt filesystems ...)
...
# mkinitcpio -P
Set the root password:
# passwd
Enable Network Manager and Firewall:
# systemctl enable NetworkManager.service
# systemctl enable ufw.service
Remember to run
ufw enable
after re-booting into the system.
Instead of a swap partition which takes disk space and has some encryption considerations you can use zram. Enabling zram swaps programs into a compressed area of ram, instead of a dedicated partition.
You can activate zram at boot with a udev rule. Alternatively, you can use zram-generator.
Here are the steps for the udev rule method.
Load module at boot:
# /etc/modules-load.d/zram.conf
zram
Create udev rule, adjust disksize
as necessary. 4GB seems common, although the standard $swap = \sqrt{ram}$ still seems to hold.
# /etc/udev/rules.d/99-zram.rules
ACTION=="add", KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="4G", RUN="/usr/bin/mkswap -U clear /dev/%k", TAG+="systemd"
Add /dev/zram
device to fstab.
# /etc/fstab
/dev/zram0 none swap defaults,pri=100 0 0
zswap
andzram
are mutually exclusive. Be sure to disablezswap
with thezswap.enabled=0
kernel parameter. I have this set in the next section.
zram
will not work with hibernate. Sleep should still work.
I like to use systemd-boot
since it’s included in the base install.
Install and update into boot partition:
# bootctl --path=/boot install
# bootctl update
Create a pacman
hook update boot partition when systemd-boot
updates:
# mkdir -p /etc/pacman.d/hooks
# cat > /etc/pacman.d/hooks/100-systemd-boot.hook << EOF
[Trigger]
Type = Package
Operation = Upgrade
Target = systemd
[Action]
Description = Updating systemd-boot.
When = PostTransaction
Exec = /usr/bin/systemctl restart systemd-boot-update.service
EOF
If you at some point enable secure boot see here for a hook to sign the new boot manager.
Create boot config files:
# cat > /boot/loader/loader.conf << EOF
default arch
timeout 0
console-mode max
editor no
EOF
# cat > /boot/loader/entries/arch.conf << EOF
title Arch Linux
linux /vmlinuz-linux
initrd /<cpu>-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=<device-UUID>:root root=/dev/mapper/root rw quiet splash zswap.enabled=0
You should now be ready to exit the chroot, unmount the filesystem, and reboot the system.
# exit
# umount -R /mnt
# reboot
Remove the install media and log in to your fresh system.
You can get
<device-UUID>
withblkid /dev/<partname>
and grab the top-level encrypted partition
Now you should have a minimal Arch system with btrfs, systemd-boot and zram swap. Here are some nice-to-haves for setting up the rest of the desktop system.
Periodically activating trim is good for SSD health:
# systemctl enable fstrim.timer
Create an admin user and edit sudoers to allow sudo
privileges for wheel group.
# useradd -mU -G wheel "${username}"
# echo "$username:$password" | chpasswd
# sed -i 's/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/' /etc/sudoers
root
AccountI like to have root
disabled.
# passwd -l root
Make sure
sudo
works for you user before doing this.
I hate the terminal bell, this disables it forever:
# rmmod pcspkr
# echo "blacklist pcspkr" > /mnt/etc/modprobe.d/nobeep.conf
Generally vm.swappiness=10
is a common recommendation.
However, PopOS and Fedora have done some experiments and found that with zram
swappiness values higher than 100 lead to performance improvements
# cat > /mnt/etc/sysctl.d/99-vm-zram-parameters.conf << EOF
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
EOF
sed -i "s/^#Color/Color/" /mnt/etc/pacman.conf
Install pipewire and associated packages.
$ sudo pacman -S pipewire pipewire-docs pipewire-audio pipewire-pulse pipewire-jack wireplumber
$ systemctl --user enable --now pipewire
$ systemctl --user enable --now pipewire-pulse
You can then use wpctl
to manage sources and sinks.
I like to use greetd
for simple autologin setup.
Configure greetd
autologin buy adding the following to /etc/greetd/config.toml
:
[initial_session]
command = "<command>" # e.g. "sway"
user = "<username>"
Then enable the service:
$ sudo systemctl enable greetd