Installing Arch linux with dm-crypt and btrfs
Having recently purchased a new laptop, it was a good opportunity to try out a new filesystem, btrfs. Just to complicate things I wanted to secure my system with whole drive encryption, so today we're throwing dm-crypt (LUKS) into the mix!
Preparation
Installation media
First, download and write the installation image.
Cleaning hard drive
As the drive will be encrypted, we'll want to first fill it with random data. This is so that the encrypted areas are not easily identifiable.
cryptsetup open --type plain /dev/sda container
dd if=/dev/zero of=/dev/mapper/container
This took about 3hrs on my 500Gb drive
cryptsetup luksClose container
Partitioning
I'm going to be using a 500Mb EFI partition mounted as /boot and the rest of the disk for btrfs mounted on a dm-crypt partition. I have plenty of RAM so won't be using a swap partition for this setup (which also neatly avoids any issues with swap encryption).
gdisk /dev/sda
/dev/sda1
512Mb for/boot
/dev/sda2
remainder for btree filesystem
Filesystem and encryption
Set up dm-crypt container
I'm encrypting using sha512 instead of the default, sha1. Remember to increase iteration time when doing this, as each iteration will take longer with a stronger hash.
cryptsetup --hash sha512 --iter-time 2000 --use-random luksFormat /dev/sda2
Open the new encrypted container. I'm using the name "btree" which will open the container in /dev/mapper/btree
.
cryptsetup luksOpen /dev/sda2 btree
Create filesystem
Create the filesystems on both partitions. I'm labelling my btrfs partition "honey". Bee tree. Get it? Never mind.
mkfs.fat -F32 /dev/sda1
mkfs.btrfs -L honey /dev/mapper/btree
Mount root of btrfs partition for use. I'm using the same mount options that I intend to use in fstab.
mkdir /broot
mount -o autodefrag,compress=lzo,noatime,space_cache /dev/mapper/btree /broot
Set up subvolumes
Enter the root of the btrfs filesystem:
cd /broot
There are no difinitive rules (as yet) around subvolume heirarchy. There seem to be two popular methods:
- using
__active
(or__current
) and__snapshots
directories - using
@
for root subvolume,@home
for home subvolume, etc. directly in the root of the device
The first way seems to favour using __active
as the root, so all subvolumes can be created underneath and therefore will be auto-mounted. The issue with this comes when you want to restore a snapshot of /
(root) -- you need to move all the subvolumes first. The suggestion in the official wiki is to create both the root filesystem and other subvolumes on the same level, then mount the subvolumes separately in fstab, which is closer to the second method listed above.
I like both approaches: the subdirectories I find neater, but the flat structure allows for better root filesystem restores. I don't see why I can't combine both approaches -- so I will! First I'll create directories to hold the active and snapshot subvolumes (these don't need to be subvolumes themselves as I don't intend to mount them anywhere):
mkdir active snapshots
One thing to note is that when taking snapshots, we probably want to keep some paths out of the backup. The Suse documentation discusses each of these paths and the reason to have them as a separate subvolume. Of course, not all of these will be applicable to everyone and due to the nature of the COW in btrfs, we shouldn't worry too much about paths which aren't modified often (or by much). I've taken a look at the modified dates on these paths and determined that I ought to keep tmp
, run
, and var/log
separate, along with /home
of course. Arch creates tmpfs mounts for /run
and /tmp
so we don't need to worry about those.
btrfs subvolume create active/root
btrfs subvolume create active/home
btrfs subvolume create active/log
Mount subvolumes
Mount the root filesystem subvolume:
mount -o subvol=active/root /dev/mapper/btree /mnt
Create mount points and mount the boot partition and other subvolumes:
mkdir -p /mnt/{boot,home,var/log}
mount /dev/sda1 /mnt/boot
mount -o subvol=active/home /dev/mapper/btree /mnt/home
mount -o subvol=active/log /dev/mapper/btree /mnt/var/log
Install and config
Base system
pacstrap /mnt base btrfs-progs
genfstab -p /mnt >> /mnt/etc/fstab
Edit fstab if needs be -- in my case I had to change relatime
to noatime
.
Now arch-chroot
into new system and set hostname, time zone, locale, etc.
Initial RAM disk
Add encrypt
to the MODULES array in /etc/mkinitcpio.conf
and create a new initial RAM disk:
mkinitcpio -p linux
Bootloader
systemd-boot
(previously gummiboot) is my bootloader of choice and is already installed with systemd.
bootctl install
vi /boot/loader/loader.conf
default arch
vi /boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options cryptdevice=/dev/sda2:btree root=/dev/mapper/btree rootflags=subvol=active/root ro
Restart
Exit chroot, unmount partitions and reboot
exit
umount -R /mnt
reboot