Setting Up Arch Linux With BTRFS, Encryption, and Swap
This post was last updated at 2024-10-24. The Arch Linux install guide on the Arch wiki may have more up-to-date instructions on installation.
This blog post will demonstrate how I set up a new Arch Linux install with BTRFS, an encrypted filesystem with dm-crypt, encrypted swap partition via a swap file, and (optionally) hibernation. This post assumes some basic familiarity with the command line, Linux distros, and terminology around installing a Linux distro.
Why?
- Why Arch: Arch Linux is a rolling release distro. That means getting to play with the latest features! You get to decide how you like the software: the customization is endless. Plus, the comprehensive official Arch Linux repositories with the Arch User Repository (AUR) centralizes the installation of software. However, being on the bleeding edge and being hands-on with the software means that an update or change might accidentally break the system, which leads to the next point.
- Why BTRFS: While BTRFS supports many advanced features, such as copy-on-write, one of the main advantages of this filesystem is the ability to easily create snapshots in a space-efficient manner. Snapshots can be restored from an Arch Linux install USB, which is handy especially if you can no longer log into the system.
- Why encryption: Data security is important, especially on laptops. As someone who has access and may locally store protected health information (PHI), ensuring that these data cannot be accessed if my device is lost or stolen is paramount. BTRFS supports encryption with swap files.
- Why hibernation: While optional these days as flash storage is commonplace, hibernation can be an excellent option for preserving battery life while preserving the data of your open applications. As I occasionally need to switch between my primary Arch install and secondary Windows install for certain applications, hibernation allows me to quickly pause my work and start where I left off.
Installation
The steps below assumes the system you’re installing Arch Linux to uses UEFI (which has been the standard for some time now), not legacy BIOS.
- 
    Boot into an Arch Linux install USB. Verify the system is using UEFI boot mode by checking the UEFI bitness. Establish a network connection with iwdif using Wi-Fi and verify the system clock.cat /sys/firmware/efi/fw_platform_size iwctl timedatectl
- 
    Create a 1 GB EFI partition and a Linux filesystem partition (usually the rest of the disk space) for Linux filesystem. - The disk name usually looks like sdafor SATA-attached disks ornvme0n1for NVME drives. You can check this withfdisk -l. I will usenvme0n1from now on.
- For NVME disks, the first partition is named nvme0n1p1(sda1for SATA devices) and the second partition isnvme0n1p2(sda2for SATA devices).
- You can use several different tools for this, including fdiskas we used before, but I usegdiskas it defaults to GPT over MBR.
- If formatting and overwriting  an existing disk, use wipefs --allfollowed by the device name (e.g./dev/nvme0n1). For good measure, I also clear the partition data and create a new GPT table ingdiskwith theooption.
- In gdisk, create a new partition withnand follow the prompts. I make my first partition the EFI partition (press Enter to accept default first sector, then type+1G) and the second my filesystem partition (press Enter and accept all defaults).
- In gdisk, useef00to set the filesystem of the first partition to EFI.
 gdisk /dev/nvme0n1
- The disk name usually looks like 
- 
    Create a FAT32 system on the EFI partition, e.g. nvme0n1p1orsda1.mkfs.fat -F 32 /dev/nvme0n1p1
- 
    Initialize encryption on the Linux filesystem partition. You’ll be prompted to enter a password to encrypt your system twice. cryptsetup -y -v luksFormat /dev/nvme0n1p2 cryptsetup open /dev/nvme0n1p2 cryptroot
- 
    Create a BTRFS file system on the newly encrypted Linux filesystem partition and mount it. mkfs.btrfs /dev/mapper/cryptroot mount /dev/mapper/cryptroot /mnt
- 
    Change into /mntand create subvolumes forroot,home,snapshots,var/log, andswap. The names of the subvolumes here are recommended for use withsnapper, a program that will help automate snapshots for us. I add an additional subvolume for our swap file since it needs to be on a non-snapshotted subvolume.cd /mnt btrfs subvolume create @ btrfs subvolume create @home btrfs subvolume create @snapshots btrfs subvolume create @var_log btrfs subvolume create @swap
- 
    Unmount cryptrootand then remount subvolumes and boot partition. For BTRFS mount options, I usenoatime(disables file writing access times to improve performance),zstd(file compression), andspace_cache=v2(new implementation of a free space tree for BTRFS cache).cd umount /mnt mount -o noatime,compress=zstd,space_cache=v2,subvol=@ /dev/mapper/cryptroot /mnt mkdir -p /mnt/{boot,home,.snapshots,var/log,swap} mount -o noatime,compress=zstd,space_cache=v2,subvol=@home /dev/mapper/cryptroot /mnt/home mount -o noatime,compress=zstd,space_cache=v2,subvol=@snapshots /dev/mapper/cryptroot /mnt/.snapshots mount -o noatime,compress=zstd,space_cache=v2,subvol=@var_log /dev/mapper/cryptroot /mnt/var/log mount -o noatime,subvol=@swap /dev/mapper/cryptroot /mnt/swap mount /dev/nvme0n1p1 /mnt/boot
- 
    Create a swap file and turn it on. My rule of thumb is 2 GB for VMs or 0.5 times the system RAM in GB; change the size=parameter as appropriate. If using hibernation, set the size equal to the memory of the computer.cd /mnt/swap btrfs filesystem mkswapfile --size 4g --uuid clear ./swapfile swapon ./swapfile
- 
    Install the necessary base packages on your system. I use the packages below. Be sure to replace intel-ucodewithamd-ucodeif using an AMD processor.cd pacstrap -K /mnt base base-devel linux linux-firmware intel-ucode zsh zsh-completions sudo vim git btrfs-progs dosfstools e2fsprogs exfat-utils ntfs-3g smartmontools networkmanager dialog man-db man-pages texinfo pacman-contrib
- 
    Continue with the install guide by generating your fstab,arch-chrooting into/mnt, and setting up time zone, system locale, hostname, networking, users, and sudogenfstab -U /mnt >> /mnt/etc/fstab arch-chroot /mnt # Look in /usr/share/zoneinfo/ for your region and city! ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime hwclock --systohc # Edit /etc/locale.gen and uncomment necessary locales vim /etc/locale.gen locale-gen # Add name of machine to /etc/hostname vim /etc/hostname # Edit /etc/hosts and add uncommented info below # 127.0.0.1 localhost # ::1 localhost # 127.0.1.1 [replace all this text and brackets with name of machine] vim /etc/hosts # Set root password passwd # Set username and password. Also add to the wheel group for sudo. I use the zsh shell. useradd -m -G wheel -s /bin/zsh cody passwd cody chfn -f “Cody Hou” cody # Uncomment wheel line using vim. Use EDITOR=nano if preferred. visudo
- 
    For the boot manager, I use grubbecause there are some packages that play nicely with restoring snapshots from the GRUB interface that we will see later.pacman -S grub efibootmgr
- 
    Edit /etc/mkinitcpio.conf. AddbtrfstoMODULESand addencrypttoHOOKS, as in the following example. If using hibernate, also addresumefollowingfilesystems.HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
- 
    Regenerate your initramfs.mkinitcpio -P
- 
    Generate your bootloader. grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
- 
    Obtain the UUID of the partition that the system was installed on. You can see this with the blkidcommand (don’t usecryptroot; use the UUID of e.g./dev/nvme0n1p2or/dev/sda2). It should look something like5f5b0b02-318c-4980-bcb5-793d44fe4387.
- 
    Edit /etc/default/gruband at the line beginning withGRUB_CMDLINE_LINUX_DEFAULT, insert at the end with a space afterquiet. Replace the UUID with the one on your system partition.root=/dev/mapper/cryptroot cryptdevice=UUID=5f5b0b02-318c-4980-bcb5-793d44fe4387:cryptroot
- 
    Regenerate grub.cfg.grub-mkconfig -o /boot/grub/grub.cfg
- 
    Add or configure any additional software. For example, I make sure to enable the following services. # Networking on reboot systemctl enable NetworkManager.service # TRIM on SSDs systemctl enable fstrim.timer # pacman cache cleaner systemctl enable paccache.timer
- 
    Exit chroot, reboot the system, and remove the Arch Linux install USB. You should be prompted to enter a password for your encrypted partition before logging in! If not, something in the process didn’t go quite right (e.g. UUID wasn’t typed correctly). With the install USB, you can remount all the partitions and arch-chrootto fix this.
- 
    We’re now going to set up snapper.sudo pacman -S snapper
- When we create a snapshot configuration with snapper, it will also create a subvolume and folder called/.snapshots, even though we created thesnapshotssubvolume mounted on/.snapshotsearlier. To remedy this we will:- 
        Unmount our snapshotssubvolume mounted at/.snapshotsand delete the/.snapshotsfolder.sudo umount /.snapshots sudo rm -r /.snapshots
- 
        Create our snapperconfig and letsnapperdo its weird thing.sudo snapper -c root create-config /
- 
        Confirm that snapperdid its weird thing and delete the newly created subvolume and folder.sudo btrfs subvolume list / sudo btrfs subvolume delete /.snapshots
- 
        Recreate the folder and remount it to our snapshotssubvolume.sudo mkdir /.snapshots sudo mount -a
 
- 
        
- 
    Let’s give read, write and execute access from our snapshots (so we can access them). sudo chmod 750 /.snapshots
- Edit snapperconfig at/etc/snapper/configs/root, add ALLOW_USERS=”[your username here, replace the brackets too]” and change frequency to that listed on thesnapperwiki page.
- 
    Enable the snapperservices. If on an SSD, enable TRIM.sudo systemctl enable --now snapper-timeline.timer sudo systemctl enable --now snapper-cleanup.timer sudo systemctl enable fstrim.timer
- 
    Home stretch! Next I’ll install yay, an AUR helper. It helps us install and manage packages from the AUR. You can also useparuif you wish.git clone https://aur.archlinux.org/yay cd yay makepkg -si PKGBUILD
- 
    Install snap-pac-grubandrsync.snap-pac-grubtakes a system snapshot after every single install withpacman(so we can revert if an upgrade breaks something) and then makes these snapshots accessible and bootable from GRUB. Since our boot partition is not being snapshotted (only root), I’ll usersyncto copy the files of/bootduring every Linux kernel upgrade.yay -S snap-pac-grub rsync
- 
    Edit /etc/mkinitcpio.confand addgrub-btrfs-overlayfsto the end ofHOOKS, and then regenerate yourinitramfs. We did something like this earlier. This step enables booting from our snapshots from GRUB.sudo mkinitcpio -P
- 
    Our BTRFS snapshots will not backup /bootas it is on a different partition. If an update to a newer kernel version causes instability, we will want to restore the older kernel image. Create the folder/etc/pacman.d/hooksand in it, create a first hook which will sync/bootbefore a kernel update.sudo mkdir /etc/pacman.d/hooks cd /etc/pacman.d/hooks sudo vim 0-bootbackup-pretransaction.hook[Trigger] Operation = Upgrade Operation = Install Operation = Remove Type = Path Target = /usr/lib/modules/*/vmlinuz [Action] Depends = rsync Description = Backing up /boot before committing transaction... When = PreTransaction Exec = /usr/bin/rsync -a --delete /boot /.bootbackup/pretransaction
- 
    Duplicate this hook and name it as 95-bootbackup-posttransaction.hook, this time to copy the new kernel after updating.sudo cp 0-bootbackup-pretransaction.hook /etc/pacman.d/hooks/95-bootbackup-posttransaction.hook[Trigger] Operation = Upgrade Operation = Install Operation = Remove Type = Path Target = /usr/lib/modules/*/vmlinuz [Action] Depends = rsync Description = Backing up /boot after committing transaction... When = PostTransaction Exec = /usr/bin/rsync -a --delete /boot /.bootbackup/posttransaction
- 
    Reboot, and you’re finished! Phew, that was a handful. But this establishes an excellent base system from which to work off of. You can install your favorite desktop environment/window manager and programs. I use KDE. sudo pacman -S plasma-meta mesa sddm konsole xdg-user-dirs xdg-utils tlp reflector firefox dolphin ark kate okular elisa vlc gwenview gimp krita kcalc spectacle kcharselect ksystemlog noto-fonts noto-fonts-cjk noto-fonts-emoji fcitx5-mozc fcitx5-configtool bitwarden libreoffice-still hunspell hunspell-en_us bluez bluez-utils neofetch kdeconnect
Resources
- Arch Linux Install Guide
- dm-crypt Wiki Page
- Snapper Wiki Page
- Ermanno Ferrari’s YouTube video where much of this documentation was based off of
 
  
  
 
       
       
      