How-To: Encrypted Btrfs install on Arch Linux
Jan 25, 2016
Setting up a Btrfs install while juggling encyption, UEFI, and swap can be tricky so I’ve decided to put down my method here. Btrfs is damn flexible and can do a lot of things from replacing the MBR/GPT schemes to RAID and then some. Unfortunately it does have some limitations. It doesn’t have built-in encryption, doesn’t support swap files and -not its fault- can’t use UEFI to boot. Encryption can be solved using dm-crypt and the other issues by having their own partitions.
Table of Contents
Partitioning
To begin with decide how exactly the install will be set up. If UEFI boot isn’t needed then there is no need for a separate EFI System Partition.
Note: Skip this and the Formatting step if neither UEFI or swap is required.
For this example, create 3 partitions:
- A small EFI System Partition for UEFI boot. ~ 512M
- Swap partition for hibernation. ~ Size of RAM
- A final partition that will be the encrypted Btrfs Arch Linux install. Rest of the drive.
When done it should look something like this:
sda ├─ sda1 EFI 512 MB ├─ sda2 swap 2 GB └─ sda3 114 GB
Set the EFI partition as bootable using whatever method you used to create the partitions. Formatting
Format the EFI and swap partitions correctly.
mkfs.fat -F32 /dev/sda1 mkswap /dev/sda2
And activate swap:
swapon /dev/sda2
Encyption
The first thing that needs to be done is to create a LUKS encrypted container in the final partition using dm-crypt.
cryptsetup -vy luksFormat /dev/sda3
The -y option is required to verify the password. Make sure it’s a secure password and don’t forget it. It will be required at the start of every boot..
Next unlock the encrypted container and enter the password:
cryptsetup open /dev/sda3 btrfsroot
Replace btrfsroot
with any preferred name. This will map the LUKS
container to /dev/mapper/btrfsroot
.
Create the btrfs filesystem:
mkfs.btrfs -L "arch" /dev/mapper/btrfsroot
The arch
label will be used to mount the various Btrfs subvolumes in
fstab. The layout should now look something like this:
sda ├─ sda1 EFI 512M ├─ sda2 swap 2G └─ sda3 crypto_LUKS 114G └─ btrfsroot Btrfs 114G
Note: Encrypting the swap partition is outside the scope of this article but is possible if needed. See dmcrypt/Swap encryption.
Setting up Btrfs and installing Arch Linux
Properly create and mount the subvolumes for the actual Arch Linux install.
First mount the container:
mount /dev/mapper/btrfsroot /mnt
cd /mnt
Now create the subvolumes. In Btrfs these essentially replace (or complement) the traditional partitions scheme. The ultimate scheme is preferencial. This is just one example. There are an infinite number of ways to create and mount subvolumes.
btrfs subvolume create __arch btrfs subvolume create __arch/root btrfs subvolume create __arch/home btrfs subvolume create __snapshots
There is one subvolume for the root(/
) directory and one for the
home(/home
) directory. The __snapshots
subvolume is where the
snapshots of the subvolumes will be stored. Snapshots can be created
of the root
or home
subvolumes (or both by snapshotting __arch
) prior
to major upgrades as a form of backup. They can also be automated via
simple scripts.
View the subvolumes:
btrfs subvolume list .
Unmount the LUKS container:
cd
umount -R /mnt
Decide where to mount the subvolumes and create the appropriate directories.
mount -o subvol=__arch/root /dev/mapper/btrfsroot /mnt mkdir /mnt/{home,.snapshots} mount -o subvol=__arch/home /dev/mapper/btrfsroot /mnt/home mount -o subvol=__snapshots /dev/mapper/btrfsroot /mnt/.snapshots
This mounts the corresponding subvolumes of the btrfsroot Btrfs filesystem to their appropriate locations.
Mount the EFI System Partition:
mkdir /mnt/boot mount /dev/sda1 /mnt/boot
Select the fastest mirrors and install Arch Linux
pacstrap -i /mnt base base-devel btrfs-progs
The btrfs-progs package is required in order to manipulate the btrfs install.
Post Installation
Generate the fstab file:
genfstab -U /mnt > /mnt/etc/fstab
genftab doesn’t handle btrfs subvolumes gracefully so edit the file. The subvolume mounting should look something like this:
LABEL=arch / btrfs rw,relatime,space_cache,subvol=__arch/root 0 0 LABEL=arch /home btrfs rw,relatime,space_cache,subvol=__arch/home 0 0 LABEL=arch /.snapshots btrfs rw,relatime,space_cache,subvol=__snapshots 0 0
Remove any reference to subvolid in the fstab file. It will conflict with snapshot recovery because snapshots have a seperate subvolume ID. This makes it tricky to easily recover subvolumes using older snapshots because the kernel will still be looking for the subvolume ID of the original subvolume. Subvolid can still be used but requires additional steps to be taken during the snapshotting and recovery process that can be avoided by relying specificallly on the subvolume name.
Chroot into the install:
arch-chroot /mnt /bin/bash
Edit the /etc/mkinitcpio.conf
file to include the encrypt
HOOK before
the filesystems hook:
HOOKS="... encrypt ... filesystems ..."
Regenerate the initramfs image with the encrypt
hook:
mkinitcpio -p linux
Install the systemd-boot bootloader:
bootctl install
This will by default install the bootloader in /boot
.
Create a file in /boot/loader/entires
called arch.conf
. Determine the
unique UUID of the encrypted partition (/dev/sda3
) and of the btrfs
LUKS container (/dev/mapper/btrfsroot
).
title Arch Linux linux /vmlinuz-linux initrd /initramfs-linux.img options cryptdevice=UUID=</dev/sda3 UUID>:btrfsroot root=UUID=</dev/mapper/btrfsroot UUID> rootflags=subvol=__arch/root rw quiet
Do not include the chevrons (<, >) in the file. Configure the rest of the system and reboot. Enter the password on restart that was chosen when creating the encrypted LUKS container.
Snapshots
Snapshots are straightforward in Btrfs. They act as another subvolume linked to the original. They take up almost no space unless changes are made on the original subvolume in which case they retain the files and hierarchy that existed at the time of the creation of the snapshot.
To create a snapshot the subvolume must be mounted.
btrfs subvolume snapshot /home /.snapshots/home-$(date "+%F")
This will create a complete copy of the __arch/home
subvolume in
__snapshots
.
Because snapshots act as subvolumes they can be viewed, deleted and mounted them the same way.
btrfs subvolume list /
btrfs subvolume delete /.snapshots/home-2016-01-25
mount -o subvol=__snapshots/home-2016-01-25 /dev/mapper/btrfsroot /mnt/home-snapshots
Snapshots and Subvolumes behave in many ways similar to directories
and so they can be renamed using the mv
command.
mv /.snapshots/home-2016-01-25 /.snapshots/home/2016-01-25
In order to rollback to a snapshot, first mount the toplevel Btrfs subvolume and simply replace the desired subvolume with the preferred snapshot.
mkdir /mnt/btrfs-toplevel
mount /dev/mapper/btrfsroot /mnt/btrfs-toplevel
cd /mnt/btrfs-toplevel
mv __arch/home __arch/home-old
mv __snapshots/home-2016-01-25 __arch/home
Then reboot and the kernel will mount the new __arch/home
subvolume
rather than the __arch/home-old
because fstab determines the
appropriate subvolume by name not ID in which case it would attempt to
mount __arch/home-old
again.