Skip to content

Instantly share code, notes, and snippets.

@lucas-mior
Last active December 11, 2024 15:14
Show Gist options
  • Save lucas-mior/e1c0c1caf3471787ec2264cda3226b79 to your computer and use it in GitHub Desktop.
Save lucas-mior/e1c0c1caf3471787ec2264cda3226b79 to your computer and use it in GitHub Desktop.

archlinux install with (almost) full disk encryption, btrfs and RAID

This tutorial focuses on the disk setup and boot process. You should be familiar with a standard archlinux installation to follow along. However, I also added some general things that the archlinux installation guide fails to adress.

Setup

  • 2 disks of 2TB each
  • Boot:
    • UEFI
    • GRUB (with luks2 and pbkdf2)
    • Unencrypted 2GB /efi partition with fat32 on first disk
    • Encrypted 2GB /boot partition with ext4 on second disk
  • Almost identical partition layout on both disks:
    • The first partition will be used for /efi on the first disk
    • The first partition will be used for /boot on the second disk
    • LUKS Encrypted 8GB swap partition for each disk (no swapfile)
    • LUKS Encrypted root partition for each disk
    • RAID for root filesystem using btrfs (no mdadm)

Rationalization

  • btrfs needs "block group profilewith redundancy" in order to auto-repair corrupted data
    • This means you can use RAID1, RAID1C3, RAID1C4, RAID10 or DUP btrfs multidevice profiles.
  • RAID using mdadm won't benefit from self-healing capabilities of btrfs.
  • Swapfiles are not compatible with a multidevice filesystem.
  • Encrypted /boot adds a little bit of security.
  • Saving a keyfile in the initramfs which resides in a encrypted /boot is a straightforward way to avoid having to type a password for each encrypted root. Now this guide uses sd-encrypt to do that.
  • Ext4 is much more stable than fat32, so it makes sense using it for /boot, since GRUB supports it. Btrfs would be overkill and potentially slow for that.
  • /efi has to stay unencrypted and formatted with fat32. If you want to install a windows bootloader, you should install it there.

Note about RAID10

I no longer recommend using RAID10 (or RAID1 for that matter) for repairing corrupted data. Yes, it could work, but apparently all modern storage devices have error detection/fixing built-in, so doing this again on the file system level is not very useful because you should have backups anyway, so you are wasting half of your space for a small convenience gain in case btrfs catches an error that your hardware didn't.

Furthermore, errors in storage devices are very rare compared to memory errors. So, unless you are using ECC RAM, you are likely increasing your chance to lose time by extensively reading your files into memory for scrubbing. If memory errors triggered a false positive, it could make you worry about your data and recover from backup when it is not needed. The situation could be even worse when you are also writing from corrupted memory, because then you couldn't possibly tell whether your working data or your backed-up data is correct.

However, RAID10 could be useful for performance gains for sequential reading, if you are using HDDs or (maybe) SATA SSDs. I noticed that the only performance penalty btrfs causes (compared to ext4) for NVME SSDs is for finding files, while reading and writing files is as fast as one could want.

About GRUB

Using GRUB is supposed to be the only way to have an encrypted /boot. However it is not, check https://github.com/maximbaz/arch-secure-boot. Future versions of this guide might not use GRUB nor any bootloader at all. The thing is that GRUB is kind of ubiquitous and easy to configure, and most people are used to it. So for now GRUB it is.

Another problem with GRUB is that its luks implementation is extremely slow. I don't recommend encrypting /boot (see notes about security), but if you want a fast /boot decryption, use --iter-time <low value> when adding your LUKS key. Note that it may decrease the security of your password. It should not matter if you have a strong password. However, a strong password is by definition slower and harder to type. And the GRUB password prompt is terrible (no feedback at all, and if you mistype, it leaves you with a useless grub rescue prompt). So my final suggestion is: Either don't encrypt /boot, or use a not so strong password for /boot, with a low iteration value, but use a different, strong password for your root partitions with the default LUKS2 options.

Procedure

Random tips when starting

Configure keyboard and font size

loadkeys br-abnt2 # if you are in Brazil
setfont ter-122n  # for miopic people like me
setfont ter-132n  # for people with 4k displays

Verify the boot mode

Even if you booted with legacy BIOS, you probably can configure your computer to use UEFI. Try rebooting and entering your firmware settings.

Connecting to the internet

If you can, use an ethernet cable. Otherwise, the general steps are:

  • Get your wifi adapter name with the command ip link. It is usually something with w, like wlan0.
  • ip link output will show if the adapter is UP. If it is not, run ip link set <adapter> up, where <adapter> is the name you discovered before.
    • If it doesn't work, you may try running rfkill unblock <adapter>
    • If it still doesn't work, google it.
    • If you couldn't find a solution, ask in a forum.
  • Use iwctl:
iwctl

device list
device <device> power on
station list
station <station> power on
station <station> scan on
station <station> connect <wifi-name>

Useful aliases

alias mount='mount --mkdir'
alias lsblk='lsblk -o NAME,SIZE,LABEL,FSTYPE,MOUNTPOINTS,UUID'

Partition the drives

Make sure both disks use a GUID partition table (GPT), it will avoid headaches in the future.

parted /dev/sda mklabel gpt
parted /dev/sdb mklabel gpt

Then launch cfdisk to partition the disks.

parted
cfdisk /dev/sda
cfdisk /dev/sdb

Partition layout

partition purpose encrypted partition purpose encrypted
/dev/sda1 /efi no /dev/sdb1 /boot yes
/dev/sda2 [SWAP] yes /dev/sdb2 [SWAP] yes
/dev/sda3 / yes /dev/sdb3 / yes
$ lsblk

Setup LUKS on root partitions

Format with LUKS

GRUB only supports LUKS2 using pbkdf2, not the default argon2, So the /boot partition has to be encrypted that way. The root partitions can be encrypted with default options just fine, since they will be unlocked by the kernel.

These commands will prompt you to create passwords.

cryptsetup luksFormat --pbkdf pbkdf2 /dev/sdb1 --iter-time 100

cryptsetup luksFormat /dev/sda3
cryptsetup luksFormat /dev/sdb3 # use the same password as sda3

Open LUKS partitions

These commands will prompt you to enter the passwords you set before.

cryptsetup open /dev/sdb1 cboot
cryptsetup open /dev/sda3 croot1
cryptsetup open /dev/sdb3 croot2

Setup btrfs

Format and mount

The second root partition will be added later.

mkfs.btrfs /dev/mapper/croot1
mount /dev/mapper/croot1 /mnt

Create subvolumes

btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home

Remount

Check which options are optimal for your disk, explanation for the options below:

  • noatime: Recommended for performance. Breaks applications that depend on access time. Not specific to btrfs.
  • commit=60: Recomended for performance, but in the event of a power loss, more data will be lost. Not specific to btrfs.
  • compress=zstd:1: Enables compression. zstd is the algorithm (standard recommendation) and 1 is the compression level. The general recommendation is:
    • zstd:1for NVME SSDs
    • zstd:3for SATA SSDs
    • zstd:9for HDDs
  • subvol=@: Specify subvolume.

Some useful options set by default:

  • ssd: Optimize for non rotating storage (by default, btrfs uses auto detection to set this).
  • rw: Read and write mode (mount default)
  • discard=async: Enables discarding of freed file blocks. Enabled by default if device supports it.
umount -R /mnt
mount /dev/mapper/croot1 /mnt      -o noatime,commit=60,compress=zstd:1,subvol=@
mount /dev/mapper/croot1 /mnt/home -o noatime,commit=60,compress=zstd:1,subvol=@home

Note: Most btrfs options can't be specified per subvolume and are instead applied to the whole filesystem (as per the first mount command above).

Setup /boot and /efi partitions

mkfs.ext4 /dev/mapper/cboot
mkfs.fat -F32 /dev/sda1

mount /dev/mapper/cboot /mnt/boot
mount /dev/sda1         /mnt/efi

Setup swap

The encryption for these partitions will be done later.

mkswap /dev/sda2
mkswap /dev/sdb2

Install system

pacstrap -K /mnt base linux linux-firmware \
    networkmanager gvim man-db man-pages btrfs-progs grub grub-btrfs efibootmgr

Configure fstab

Add unique labels to all partitions

cryptsetup config /dev/sdb1 --label "CBOOT"
cryptsetup config /dev/sda3 --label "CROOT1"
cryptsetup config /dev/sdb3 --label "CROOT2"

swaplabel -L "SWAP1" /dev/sda2
swaplabel -L "SWAP2" /dev/sdb2

fatlabel /dev/sda1 "EFI"

Generate fstab

genfstab -L /mnt >> /mnt/etc/fstab

Change root into installed system

arch-chroot /mnt

Post install stuff

Please check https://wiki.archlinux.org/title/Installation_guide for updated instructions.

Configure time

ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc

Configure locale and console

$ vim /etc/locale.gen
$ grep "en_US" /etc/locale.gen
en_US.UTF-8 UTF-8
en_US ISO-8859-1

$ vim /etc/locale.conf
$ cat /etc/locale.conf
LANG=en_US.UTF-8

$ vim /etc/vconsole.conf
$ cat /etc/vconsole.conf
KEYMAP=br-abnt2
FONT=ter-122n

Configure network

$ vim /etc/hostname
$ cat /etc/hostname
yourhostname

Password and user

useradd user
passwd root
passwd user
usermod -aG users,video,storage,optical,disk,audio,wheel user

Setup RAID

Add second encrypted root, then balance as RAID

You can also use raid1, raid1c3, raid1c4 or dup profiles.

btrfs device add /dev/mapper/croot2 /
btrfs balance start -dconvert=raid10 -mconvert=raid10 /

Check btrfs file system usage

The output of the command below should show both devices being used.

btrfs filesystem usage /

Setup mounting at boot

Unlock swap partitions using crypttab

This method uses a random key to unlock the swap. Therefore, all swap content will be lost across reboots, so suspend-to-disk can't be used.

$ vim /etc/crypttab
$ grep "cswap" /etc/crypttab
cswap1 /dev/disk/by-label/SWAP1 /dev/urandom swap,offset=1024,cipher=aes-xts-plain64,size=512
cswap2 /dev/disk/by-label/SWAP2 /dev/urandom swap,offset=1024,cipher=aes-xts-plain64,size=512

Mount swap partitions using fstab

$ vim /etc/cryptab
$ grep "cswap" /etc/fstab
/dev/mapper/cswap1 none swap defaults,pri=1 0 0
/dev/mapper/cswap2 none swap defaults,pri=1 0 0

Setup unlocking at boot

This method uses sd-encrypt hook to unlock both root partitions.

Configure mkinitcpio

You have to add the hooks systemd, sd-vconsole, and sd-encrypt to the HOOKS array, like below (order matters).

$ vim /etc/mkinitcpio.conf
$ grep "^HOOKS" /etc/mkinitcpio.conf
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont
sd-vconsole block sd-encrypt filesystems fsck)

Configure cryptab.initramfs

sd-encrypt can unlock the devices listed in /etc/crypttab.initramfs. It will ask for your password, and then try to reuse the same password for the other partition.

$ vim /etc/crypttab.initramfs
$ cat /etc/crypttab.initramfs
croot1 /dev/disk/by-label/CROOT1 none none
croot2 /dev/disk/by-label/CROOT2 none none

Pass root flags to grub config

$ vim /etc/default/grub
$ grep "GRUB_CMDLINE_LINUX" /etc/default/grub
GRUB_CMDLINE_LINUX="root=/dev/mapper/croot1 rootflags=subvol=@ rw"
$ grep "GRUB_ENABLE_CRYPTODISK" /etc/default/grub
GRUB_ENABLE_CRYPTODISK=y

Auto reboot on kernel panic (why not default???)

$ grep "GRUB_CMDLINE_LINUX" /etc/default/grub
GRUB_CMDLINE_LINUX="root=/dev/mapper/croot1 rootflags=subvol=@ rw panic=10"

Install grub and make config

grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg

Create a keyfile to unlock /boot again

This is only needed if you used a different password for /boot and still want it to be unlocked automatically when booting. Don't add this key file to your root partitions LUKS headers.

dd bs=512 count=4 if=/dev/random of=/crypto_keyfile.bin
chmod 600 /crypto_keyfile.bin

cryptsetup luksAddKey /dev/sdb1 /crypto_keyfile.bin

Add keyfile to initramfs

$ vim /etc/mkinitcpio.conf
$ grep "^FILES" /etc/mkinitcpio.conf
FILES=(/crypto_keyfile.bin)

Add /boot partition to crypttab

$ grep cboot /etc/crypttab
cboot /dev/disk/by-label/CBOOT /crypto_keyfile.bin

Check everything

$ lsblk
$ cat /etc/crypttab
$ cat /etc/crypttab.initramfs
$ cat /etc/fstab
$ cat /etc/default/grub
$ cat /etc/mkinitcpio.conf

Recreate the initramfs image

mkinitcpio -P

Reboot

GRUB should ask for a password. Then systemd should ask for another password.

Notes about security

An encrypted /boot partition does not add security, because you still have to keep a part of the bootloader in an unencrypted partition (/efi is this case). But it may help just a little bit, because if an attacker were to manipulate your /efi partition to load a malicious bootloader and ask for your password, it would have to reproduce an interface similar to the one you know, otherwise you would get suspicious when logging in. That is not that hard to do, and even if you noticed something is off, it is probably to late to do anything (except maybe powering off the machine and removing the disks). So again, the primary use for an encrypted /boot partition is to facilitate decrypting the rest of your disks, not security.

However, I changed this guide to use sd-encrypt hook instead, which can try using the same password for multiple drives automatically. So now the encrypted /boot is only about hiding what is inside it, not about unlocking the other encrypted partitions.

What about secure boot?

You may consider enabling secure boot (not explained here). Note however, that it is not a effective defense against evil maid attacks:

  • If you can change secure boot keys in your UEFI settings, so can an attacker with physical access. They install a malicious bootloader and you are done.
  • If you need a password to turn your computer on, and this password mechanism is safe, then you won't gain anything from using secure boot in this context.
  • Even if you think that secure boot is at least an inconvenience for an attacker, remember that with physical access, they can manipulate your hardware. So yeah, all bets are off.

Secure boot is only a defense against malware that will try to replace your bootloader and/or kernel while running. In this case, it also helps to have good practices while running your operating system. Note that, once a single malware has run on your system, you can only assume it has been fully compromised, even with secure boot. Start over from a trusted source and wipe your disks.

Considering an evil maid again, another thing that might help is booting from a separate USB disk. This way you make sure that no one messed with your bootloader and kernel. Of course, that does not guarantee that your computer is not compromised like explained above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment