Skip to content

Case: Complete BTRFS Setup (step by step)

Katherine Door edited this page Jul 9, 2020 · 4 revisions

Based on issue #68

This page will go through the steps required to setup a machine with full disk encryption that can be remotely unlocked via ssh.


1. Disk Partitions

We will first create the boot partition (which is utilized both as the EFI system partition for boot, and also for /boot on linux to store kernel initramfs), and the LUKS container which will store our root later on.

Boot partition LUKS partition
Name /dev/sdX1 /dev/sdX2
Size 1GB 100%FREE
Part Type ef00 8308
FS Type FAT32 LUKS container
Mount /boot /dev/mapper/crypt

Use at your own risk. If you are unfamiliar with sgdisk, you can use the interactive utility gdisk as well.

# Clear disk partition table
sgdisk -og /dev/sdX

# Create boot, with label boot, and type ef00
sgdisk -n 1:0:+1G -c 1:boot -t 1:ef00 /dev/sdX

# Create luks parition, with label crypt, and type 8308
sgdisk -n 2:0:0 -c 2:crypt -t 2:8308 /dev/sdX

Now that the partitions are created, we need to create the filesystem on /boot, and create a LUKS container on /dev/sdX2.


2. Formatting of Partitions

# Create FAT32 partition on boot
mkfs.fat -F32 -n ESP /dev/sdX1

# Create LUKS container
cryptsetup luksFormat --type luks2 /dev/sdX2

# Open LUKS container as /dev/mapper/crypt
cryptsetup open /dev/sdX2 crypt

3. LVM Partitions

Now that the crypt has been opened, we want to create an LVM volume group inside it. This way, all of our data is encrypted by LUKS, and we can freely create as many partitions as we want using LVM.

# Purpose crypt as an LVM physical volume
# If the partition is not clean, and the command fails, -ff will force it
pvcreate /dev/mapper/crypt

# Utilize the physical volume in a volume group
vgcreate lvm /dev/mapper/crypt

we can take a look into what we want to create inside of the volume group 'lvm'.

Name root swap
Size 100%FREE amount of ram on system
Mount / swap
# Create the logical volumes
# Replace 8G with the amount of RAM you have installed in your system
lvcreate -L 8G lvm -n swap
lvcreate -l +100%FREE lvm -n root

# Format swap
mkswap -L swap /dev/lvm/swap

# Format root
mkfs.btrfs -L root /dev/lvm/root

4. Mounting of All Partitions

Now, we have finished partitioning and formatting everything we need.

To look back on what we have created, we can see with lsblk, we have created two partitions on the disk. However, the second partition expands into a LUKS container, which in turn expands into the swap and root partitions we have created.

Lets mount everything.

# Mount root
mount /dev/lvm/root /mnt

# Create dir to mount to
mkdir -p /mnt/boot

# Mount boot/esp
mount /dev/sdX1 /mnt/boot

# Turn on swap
swapon /dev/lvm/swap

Now, genfstab will be able to automagically configure our /etc/fstab file with our partitions. However, /etc/crypttab which is required to open our crypt (i.e. LUKS container) on boot will need to be created by us.


5. Time to Visit the Arch Wiki

Before we get to that, you have to go through the Arch Wiki Installation Guide and some extra steps linked in it, and go through the basic setup. Here's a checklist for what you should configure before coming back to this guide.

  • (recommended) Synchronize system clock
  • (optional) Configure best mirrors
  • pacstrap /mnt
  • Generate fstab
  • Chroot into your installation
    • Setup timezone
    • Setup system clock
    • Setup locale
    • Setup hostname
    • Setup networking (e.g. for a headless server, enable dhcpcd and sshd)
    • Create your user (as a member of wheel)
    • Add your ssh public key to both root and user authorized_keys (ensure permissions are good)

6. Installing systemd-tool and Setting Up Initramfs fstab and crypttab

Welcome back! Now that you are back here, we can focus on setting up our bootloader, and configuring mkinitcpio with systemd-tool. All of this will be done within the chroot.

# Install systemd-tool and various optional dependencies.
# Only omit things if you know what you are doing.
pacman -S mkinitcpio-systemd-tool busybox cryptsetup openssh tinyssh tinyssh-convert mc

Configure HOOKS on /etc/mkinitcpio.conf:

HOOKS=(base keyboard autodetect modconf block filesystems fsck systemd sd-lvm2 systemd-tool)

Now we need to create our crypttab files (one for the system, and one for the initramfs/systemd-tool) /etc/crypttab and /etc/mkinitcpio-systemd-tool/config/crypttab

# Create our crypttab files
echo "crypt UUID=$(blkid -s UUID -o value /dev/sdX2)" > /etc/crypttab
cat /etc/crypttab > /etc/mkinitcpio-systemd-tool/config/crypttab

Now our system knows how to open our crypt, and how to mount our partitions. Also, our initramfs (i.e. boot environment) knows how to open our crypt. However, we need to also teach it about the partitions it will find within the crypt.

If you have been following this guide accurately, your /etc/fstab should be the following.

/etc/fstab:

UUID=</dev/lvm/root UUID>   /       btrfs  rw,relatime,ssd,space_cache,subvolid=5,subvol=/ 0 0
UUID=</dev/sdX1 UUID>       /boot   vfat   rw,relatime,... 0 2
UUID=</dev/lvm/swap UUID>   none    swap   defaults 0 0 

It might not have ssd if you are not installing on an ssd, in which case, you should really consider upgrading ;)

Now, we will teach systemd-tool how to handle the partitions it finds in our crypt, so that it can hand them over to the system mounted in their respective directories.

/etc/mkinitcpio-systemd-tool/config/fstab:

/dev/lvm/root   /sysroot   auto   x-systemd.device-timeout=9999h   0 1
/dev/lvm/swap   none       swap   x-systemd.device-timeout=9999h   0 0

7. Building Initramfs with Required Services

# Enable required services
systemctl enable initrd-cryptsetup.path
systemctl enable initrd-tinysshd
systemctl enable initrd-debug-progs
systemctl enable initrd-sysroot-mount

# Build initramfs
mkinitcpio -P

8. Bootlader Installation

# Install systemd-boot
bootctl --path=/boot install

/boot/loader/loader.conf:

default arch.conf
timeout 3
console-mode max
editor no

/boot/loader/entries/arch.conf:

title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=/dev/lvm/root resume=/dev/lvm/swap

9. You are done!!!

Now, with your rescue usb in hand, exit chroot, unmount partitions, and reboot.

It is highly recommended to have a display attached to your device to see some diagnostic information as we try to verify everything works.

After initial boot tasks are done, you should see a prompt in the terminal on the screen.

The same prompt can be accessed via ssh as user root with the key you have installed on the root user.


10. Future Steps

  • Look into editing the tinyssh service file so it runs on a different port in order to avoid known_hosts warnings, and perhaps limit ssh to only your local network
  • Use a btrfs subvolume, instead of the root, in order to utilize snapshots
  • Use plymouth for prettier prompt on the physical display
  • Setup a keyfile for automatic decrypt of a data disk on your machine (btrfs raid, mdadm raid, single disk, etc)

Some of these might end up being included on this document in the future.