This post describes how to setup a fully encrypted root btrfs on two disks, running in RAID 0.
Disclaimer
Some things are distribution agnostic, but other things (especially the how to make it boot) are arch linux specific.
Make sure you have a backup of everything before you start this. If you lose data or destroy your system, it is your own fault :D.
I also don’t claim that this setup is fully secure (I only encrypt to protect the data of my customers in case my laptop gets stolen or something, not to protect my super secret secrets from the NSA :) ).
Concept
To unlock the RAID disks with one password, I went for also encrypting the boot partition and store a key to unlock the root filesystem in the initramfs.
I have two SSDs one with 128GB and one with 120GB. The partitions used for raid 0 should be the same size. Different sizes is possible, but the left over size of the bigger partition won’t be used (but we don’t have to make them precisely equal for it to work).
I put boot efi and swap on the larger disk and use two 120GB partitions for the RAID.
Resulting disk layout:1
2
3
4
5
6
7
8
9
10
11NAME FSTYPE SIZE
sdY 119,2G
├─sdY1 vfat 1000M
├─sdY2 crypto_LUKS 1000M
│ └─cryptboot ext4 998M
├─sdY3 swap 4G
└─sdY4 crypto_LUKS 113,3G
└─cryptroot btrfs 113,3G
sdX 111,8G
└─sdX1 crypto_LUKS 111,8G
└─cryptroot2 btrfs 111,8G
(I’m not going to use the swap … just created it because of the space difference)
Formating the disks
- format the efi partition fat32
setup LUKS and format the boot partition with ext4
1
2
3sudo cryptsetup luksFormat /dev/sdX2
sudo cryptsetup open /dev/sdX2 cryptboot
sudo mkfs.ext4 /dev/mapper/cryptbootsetup LUKS and format the root partition with btrfs
1
2
3sudo cryptsetup luksFormat /dev/sdX4
sudo cryptsetup open /dev/sdX4 cryptroot
sudo mkfs.btrfs /dev/mapper/cryptrootsetup LUKS on the second drive
1
2sudo cryptsetup luksFormat /dev/sdY1
sudo cryptsetup open /dev/sdY1 cryptroot2mount first btrfs and add the partition from the other disk to it
1
2
3
4
5
6
7cd /mnt
sudo mkdir cryptroot
sudo mount -o compress=lzo /dev/mapper/cryptroot cryptroot/
sudo btrfs device add /dev/mapper/cryptroot2 /mnt/cryptroot
# doing it like this also works if the drive is added later (the balance can take a while in this case)
sudo btrfs balance start -dconvert=raid0 -mconvert=raid1 /mnt/cryptroot
Copy the root filesystem to the new btrfs RAID (or make a new install on it)
Now you can install your system, or copy your existing root to the new raid btrfs.
In this example I will copy an existing root filesystem onto the new btrfs raid.
create subvolumes (“@” seams to be a common name to use for the main subvolume)
1
2
3
4
5
6sudo btrfs subvol create /mnt/cryptroot/@
sudo btrfs subvol list /mnt/cryptroot/
# output of above: ID 330 gen 1354 top level 5 path @
# use the ID shown to set the "@" subvolume as default
sudo btrfs subvol set-default 330 /mnt/cryptroot/maybe create more subvolumes (“@home” is common for /home)
- copy the installation
1
2
3sudo mkdir /mnt/newroot
sudo mount -o subvol=@ /dev/mapper/cryptroot newroot
sudo cp -a /mnt/oldroot/. /mnt/newroot/
(-a .. recursive copy that preserves all the things, like permissions)
- copy kernel to new boot
1
2
3sudo mkdir /mnt/cryptboot
sudo mount /dev/mapper/cryptboot /mnt/cryptboot/
sudo cp -a /mnt/oldboot/vmlinuz-linux /mnt/cryptboot/
Make it boot
WARNING: This part is arch linux specific.
Boot will be unlocked by grub via password to get to the initramfs.
The initramfs will unlocked root (it will have the key in it).
Boot must be unlocked again with key in root so that it can be mounted in the “normal” mode (so that an update can store a new kernel and initramfs).
- add a keyfile for unlocking to all LUKS partitions
1
2
3
4
5
6sudo dd bs=512 count=4 if=/dev/random of=/mnt/cryptroot/crypto_keyfile.bin
sudo chmod 600 /mnt/cryptboot/cryptokey.bin
sudo cryptsetup luksAddKey /dev/sdX2 cryptroot/crypto_keyfile.bin
sudo cryptsetup luksAddKey /dev/sdX4 cryptroot/crypto_keyfile.bin
sudo cryptsetup luksAddKey /dev/sdY1 cryptroot/crypto_keyfile.bin
WARNING: use this name and path (“/crypto_keyfile.bin”), otherwise additional steps must be taken later (this is the default file name and location).
chroot into the new system
1
2
3
4
5for i in /dev /dev/pts /proc /sys /run; do sudo mount --bind $i /mnt/newroot$i; done
sudo mount /dev/mapper/cryptboot newroot/boot
sudo mount /dev/sdY1 newroot/boot/efi
sudo mount --bind /sys/firmware/efi/efivars newroot/sys/firmware/efi/efivars
sudo chroot /mnt/newrootadd additional hook that will be used by the initramfs to unlock the second root partition
1
2
3
4
5
6
7# copy the original hook
cp /usr/lib/initcpio/install/encrypt /etc/initcpio/install/encrypt2
cp /usr/lib/initcpio/hooks/encrypt /etc/initcpio/hooks/encrypt2
# adapt the new hook to use different names and to NOT delete the keyfile
sed -i "s/cryptdevice/cryptdevice2/" /etc/initcpio/hooks/encrypt2
sed -i "s/cryptkey/cryptkey2/" /etc/initcpio/hooks/encrypt2
sed -i "s/rm -f \${ckeyfile}//" /etc/initcpio/hooks/encrypt2
see also: https://wiki.archlinux.org/index.php/Dm-crypt/Specialties#Modifying_the_encrypt_hook_for_multiple_partitions
alternative hook see: https://bbs.archlinux.org/viewtopic.php?id=105086
- add encrypt2 hook to mkinitcpio.conf BEFORE encrypt hook (because encrypt hook deletes the key file at the end)
- edit “/mnt/cryptroot/etc/mkinitcpio.conf” to include your keyfile and add the proper hooks:
1
2FILES="/crypto_keyfile.bin"
HOOKS=" ... udev encrypt2 encrypt ... " #(before "filesystems")
(encrypt2 before encrypt because encrypt deletes the keyfile from the initial ram disk)
generate the initramfs
1
2
3
4mkinitcpio -p linux
# initramfs includes the key, so only root should be able to read it
chmod 600 /boot/initramfs-linux-fallback.img
chmod 600 /boot/initramfs-linux.imgadd boot to crypttab (root does not need to be here, it will be unlocked by the intitramfs)
1
cryptboot UUID=054cc16f-1257-4153-954b-6fea9c1ed931 /crypto_keyfile.bin luks,discard,nofail
edit /etc/fstab (use UUID of btrfs volume, it is the same for both raid volumes)
1
2
3UUID=8a67292b-24e7-4d4b-ba6e-e4f9f7160524 / btrfs defaults,subvol=@,noatime,discard,compress=lzo,space_cache,autodefrag 0 1
/dev/mapper/cryptboot /boot ext4 defaults,noatime 0 2
UUID=FD95-93A6 /boot/efi vfat defaults 0 0edit /etc/defaults/grub add cryptdevice2 with the second device
1
2GRUB_CMDLINE_LINUX="cryptdevice=/dev/disk/by-uuid/e506207c-11a0-43f9-9e0b-c212bb6b2fee:cryptroot:allow-discards cryptdevice2=/dev/disk/by-uuid/abc6207c-11a0-43f9-9e0b-c212bb6b2abc:cryptroot2:allow-discards root=/dev/mapper/cryptroot"
GRUB_ENABLE_CRYPTODISK=ygenerate grub config and install grub
1
2grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch-grub --rechecksync, unmount, reboot and hope for the best :)