Installing Arch on an encrypted BRTFS with EFI

Arch installation is a very manual process. This walkthrough details all the steps required for BTRFS & EFI.

Edit: Modified for optimizations after creating the automated installations.

When I first started playing with Arch, I installed it as a virtual machine on Proxmox. I found I used snapshots a lot when I was trying out new packages – I was never sure I could get my machine back to a working state if I messed things up.

Moving from the VM to bare metal, I wanted to retain this ability to snapshot, so after a discussion with a colleague I decided to use btrfs as the filesystem.

Note: btrfs is a little unstable, so you probably should not use it for a production environment.

This walkthrough is largely based on Staf Wagemakers excellent article Install Arch on an encrypted btrfs partition with some changes for my environment, like using EFI.

This installation was actually performed on the Proxmox VM so that I could easily create screenshots.

Note: A prompt is implied for each of the code blocks but has been omitted to allow you to copy and paste directly from this page to your ssh window.

Download Arch

Download the ISO for Arch and copy it to a USB key, CD or whatever you need. As I am installing it on to a VM, it was easy, I just needed to mount it. This ISO is the latest version at the time of writing, no doubt it will be updated by the time you read this, but it really doesn’t matter because Arch is designed to be easily updateable.


The full list of mirrors is available at

Booting Arch

Boot the ISO and select the highlighted option.

Once Booted, you will be presented with a command prompt. No installer, text or graphical. Welcome to the wonders of Arch!

Network Access

We need the DHCP assigned IP address and we need to verify everything is working correctly.

# Display the IP address
ip a

# Verify internet access
ping -c 3

Start SSH

If you want to install via SSH (way easier because you can copy and paste from the walkthrough), we need to start it.

# set a root password
passwd root

# start ssh
systemctl list-unit-files -t service | grep ssh
systemctl start sshd
ssh root@ip

Partition the hard disk

First find out the device name

cat /proc/partitions

Overwrite with random data. If you are impatient you can exit out of this after the first few bytes are completed and the partition table has been destroyed.

badblocks -c 10240 -s -w -t random -v /dev/sda

Use parted to partition the disk because we want EFI. We are creating the following partitions –

  • 200mb partition, formatted as FAT32 for the EFI
  • 600mb partition for the GRUB bootloader
  • 32gb (ish) partition for swap
  • A partition for btrfs that consumes the rest of the disk
parted /dev/sda

mklabel gpt
mkpart ESP fat32 1MiB 200MiB
set 1 boot on
name 1 efi

mkpart primary 200MiB 800MiB
name 2 boot

mkpart primary 800MiB 32Gib
(parted) name 3 swap

mkpart primary 32GiB 100%
name 4 btrfs

# print the partitions to make sure they are correct

# exit & write to disk

Create a LUKS volume & Open it

cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha256 --use-random /dev/sda4

cryptsetup luksOpen /dev/sda4 cryptroot

Format all the Partitions

mkfs.fat -F32 /dev/sda1
mkfs.ext4 /dev/sda2
mkswap /dev/sda3
mkfs.btrfs /dev/mapper/cryptroot

Mount the root file system

mount -o noatime,compress=lzo,discard,ssd,defaults /dev/mapper/cryptroot /mnt

Create the subvolumes

cd /mnt
btrfs subvolume create __active
btrfs subvolume create __active/rootvol
btrfs subvolume create __active/home
btrfs subvolume create __active/var
btrfs subvolume create __snapshots
btrfs subvolume create __snapshots/root
btrfs subvolume create __snapshots/home
btrfs subvolume create __snapshots/var
umount /mnt

Mount the subvolumes

mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/rootvol /dev/mapper/cryptroot /mnt
mkdir /mnt/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/root /dev/mapper/cryptroot /mnt/.snapshots
mkdir /mnt/{home,var,boot}
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/home /dev/mapper/cryptroot /mnt/home
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/var /dev/mapper/cryptroot /mnt/var
mkdir /mnt/home/.snapshots
mkdir /mnt/var/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/home /dev/mapper/cryptroot /mnt/home/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/var /dev/mapper/cryptroot /mnt/var/.snapshots

Mount the non-btrfs partitions

mount /dev/sda2 /mnt/boot
mkdir /mnt/boot/efi
mount /dev/sda1 /mnt/boot/efi
swapon /dev/sda3
swapon -a ; swapon -s

Install Arch Linux

Use the pacstrap script to install the base packages, obviously we are including the btrfs package and EFI support.

pacstrap /mnt base base-devel linux linux-firmware nano btrfs-progs efibootmgr grub networkmanager openssh git --noconfirm

Generate an fstab file.

genfstab -p -U /mnt >> /mnt/etc/fstab

Change root into the newly installed system

arch-chroot /mnt

Time zone

Set the timezone & hardware clock.
Link for timezone to /etc/localtime

ln -s /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
hwclock --systohc --utc


Edit /etc/locale.gen and uncomment en_US.UTF-8 UTF-8 and other needed locales.

nano /etc/locale.gen

Generate the locales by running:


Network Configuration

Replace ‘myhostname’ with your desired name.

echo myhostname > /etc/hostname

Create a hosts file.

nano /etc/hosts	localhost
::1		localhost	myhostname.localdomain	myhostname

Create a new initramfs

Add encrypt to HOOKS before filesystems in /etc/mkinitcpio.conf and create the initial ramdisk environment for booting the linux kernel.

sed -i 's/HOOKS=(base\ udev\ autodetect\ modconf\ block\ filesystems\ keyboard\ fsck)/HOOKS="base\ udev\ autodetect\ modconf\ block\ encrypt\ filesystems\ keyboard\ fsck"/' /etc/mkinitcpio.conf
mkinitcpio -p linux

Set the root password

passwd root

Autostart network manager & sshd services

systemctl enable NetworkManager.service
systemctl enable sshd.service

Install grub

grub-install --target=x86_64-efi --efi-directory=/boot/efi --recheck

Configure LUKS kernel parameters

sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=\/dev\/sda4:cryptroot\ root=\/dev\/mapper\/cryptroot\ rootflags=subvol=__active\/rootvol\ quiet"/' /etc/default/grub

Regenerate grub.cfg file:

grub-mkconfig -o /boot/grub/grub.cfg
grub-mkconfig -o /boot/efi/EFI/arch/grub.cfg
mkdir /boot/efi/EFI/BOOT
cp /boot/efi/EFI/arch/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI

Allow users to run SUDO

echo "%wheel ALL=(ALL) ALL" | (EDITOR="tee -a" visudo)

Create a user account

useradd -m -G wheel [username]
passwd [username]



First Boot

Login using your new user account

ssh [username]@[ip address]

Install YAY

You will probably want to install packages from the Arch User Repository (AUR). My favorite package manager for this is YAY (Yet another yogurt) – lets install it.

Warning: AUR packages are user produced content. Any use of the provided files is at your own risk.

git clone
cd yay/
makepkg -si --noconfirm
cd ..
sudo rm -dR yay/

Job done.

1. Install Arch on an encrypted btrfs partition –


Hey thanks for this guide I was able to successfully setup my system with it. A few considerations:

1. small typo when creating partition 4 it says to name it partition 3

2. For the intramfs config, that didnt work for me as the bootloader? could not find /dev/mapper/cryptroot, I ended up mapping it via UUID

3. steps to add a keyfile so the drive auto-decrypts at boot would be nice, I used another guide and got this working

4. after rebooting and entering the OS I had no wifi again so some quick steps to reconnect would be good, i had to use ip link commands? as iwctl and wifi-util were not installed

5. listing your preferred DE etc is always welcome 🙂

Leave a Reply