Arch Install with Drive Encryption, BTRFS, and ZRAM
Mar 1, 2024
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. See the Arch Install Guide for more details about the install process.
Keep in mind these notes are based around a UEFI system with secure boot turned off. There is now also an official install script Archinstall. Probabably worth using that over my janky one.
Basic Install
First start by syncing the system clock with
timedatectl set-ntp true
Partitions
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.
Your device
will be something like /dev/sda
. You can run lsblk
to see a list of your devices.
parted --script "${device}" mklabel gpt \
mkpart efi fat32 1Mib 261MiB \
set 1 boot on \
mkpart system btrfs 261MiB 100%
Encryption Setup & Formatting
This is an overview for setting up LUKS on a partition.
The parted
command from the previous section applied labels to the partitions for easy reference.
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
Create BTRFS subvolumes
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
Mount files systems
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=defaults,noatime,compress=zstd
mount btrfs -o $m_opts,subvol=@ /dev/mapper/root /mnt
mount --mkdir -t btrfs -o $m_opts,subvol=@home /dev/mapper/root /mnt/home
mount --mkdir -t btrfs -o $m_opts,subvol=@snapshots /dev/mapper/root /mnt/.snapshots
mount --mkdir -t btrfs -o $m_opts,subvol=@log /dev/mapper/root /mnt/var/log
mount --mkdir -t btrfs -o $m_opts,subvol=@pkg /dev/mapper/root /mnt/var/cache/pacman/pkg
mount --mkdir -t btrfs -o $m_opts,subvolid=5 /dev/mapper/root /mnt/btrfs
mount --mkdir LABEL=EFI /mnt/boot
Install Packages
Update the arch mirror list with reflector
.
This will get you a list of your fastest mirrors.
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.
Select the microcode appropriate to your system, amd-ucode
or intel-ucode
.
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
It may be worth trying
linux-zen
if you experience UI hangs during high CPU load. Although the performance benefits are dubious. An analysis here.
Remember to install microcode,
amd-ucode
orintel-ucode
respectively. It’s important.
Configuration Stuff
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.
Setup Swap with zram
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 manually defined 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.
Setup Boot Loader
I like to use systemd-boot
since it’s included in the base arch 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=$(blkid -s UUID -o value /dev/disk/by-partlabel/system):root root=/dev/mapper/root rw quiet splash zswap.enabled=0
EOF
You can get
<device-UUID>
withblkid /dev/<partname>
and grab the top-level encrypted partition
Create an Admin User
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
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.
Now you should have a minimal Arch system with btrfs, encrypted root, systemd-boot and zram swap. You’re free to stop here and officially be able to tell everyone you use Arch… BTW.
Post-install Stuff
Here are some nice-to-haves for setting up the rest of the desktop system.
Disable root
Account
I like to have root
login disabled for some extra security.
passwd -l root
Make sure
sudo
works for you user before doing this.
Disable Terminal Bell
Die terminal bell, die!
rmmod pcspkr
echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf
Optimize swappiness for zram
Generally vm.swappiness=10
is a common recommendation for high-ram systems.
However, zram
has very low IO swap cost so these settings provide a little more optimization.
For zram
, swappiness of 100 is appropriate (100 indicates no extra IO cost)
cat > /etc/sysctl.d/99-vm-zram-parameters.conf << EOF
vm.swappiness = 100
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
EOF
Make pacman
pretty and fast
This will enable color output and parallel packages downloads.
sed -i "s/^#Color/Color/" /etc/pacman.conf
sed -i "s/^#ParallelDownloads/ParallelDownloads/" /etc/pacman.conf
It can also be worth setting up a schedule to clear the package cache. I tend to just do it manually occasionally.
Audio
Install pipewire
and associated packages.
This gives you a modern Linux audio stack.
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.
Make sure you run these commands as your user.
Display drivers
Drivers are dependent on what GPU you have. Take a look at the wiki article for display driver installation.
I have an AMD card, so I install:
pacman -S xf86-video-amdgpu mesa vulkan-radeon libva-mesa-driver libva-utils
If you’re using multilib (e.g. with Steam) you will also want
lib32-mesa
andlib32-vulkan-radeon
.
Fonts
For decent font coverage I install
ttf-liberation
for Microsoft compatible fonts.ttf-dejavu
because I like it.noto-fonts
,noto-fonts-cjk
,noto-fonts-emoji
,noto-fonts-extra
for language coverage.ttf-jetbrains-mono-nerd
for patch font symbols.
Gnome
I am an unabashed Gnome enjoyer.
This will install Gnome and enable gdm
at next boot.
pacman -S gnome gnome-shell-extension-appindicator
sysetmctl enable gdm
Printing and .local
discovery
Enable the avahi-daemon
to allow .local
domain device discovery.
systemctl enable --now avahi-daemon.service
You’ll also need cups
for printing and cups-pdf
if you want to be able to print to pdf.
pacman -S cups cups-pdf
systemctl enable cups.socket