VoidLinux: Full Disk Encryption

written the 12th Aug 2017

In order to get rid of systemd, quite a few nice options arise. My favorites range from the recent (albeit battle-tested through Docker) Alpine Linux, Gentoo/Funtoo, Sabotage Linux or sta.li. Others I have not tested.

Option 1: your disk uses MBR

Void Linux is on a good way, as it uses runit instead of the intrusive and immature systemd. Since the “official” manual for full disk encryption (FDE) does not work properly (at least, not for me), this is a complete list of instructions to achieve the FDE my way.

The goal and The problem

The aim is to have a single encrypted primary partition created using LUKS/LVM on a MBR disk scheme with logical disk scheme (one root partition and one swap partition). Using ArchLinux mkinicpio’s kernel hooks, a binary /crypto_keyfile.bin is added into a initramfs image in order to be able to decrypt and mount the partition automatically. User adds a password only a single time, when the computer starts (once GRUB asks for it).

The same principle should work in the Void Linux. The problem is that no matter the partition table (MBR or GPT), no matter the configuration, it still asks for the password two times…

Solution

The problem is a requirement of /etc/crypttab file, which needs to be provided to the initramfs as well (and which references to the /dev/sda1 encrypted partition).

So, no 3rd party “patch” is needed. Only a slight modification, such as the following:

$ blkid | grep LUKS | awk '{print $2}' | sed 's/UUID="/lvm-system        UUID=/g' | sed 's/"/    \/crypto_keyfile.bin    luks/g' >> /etc/crypttab
$ cat /etc/crypttab # and check crypttab to look similar to the following
  # crypttab: mappings for encrypted partitions
  lvm-system    UUID=01234567-89ab-cdef-0123-456789abcdef   /crypto_keyfile.bin luks

Rewrite the grub configuration and recompile the kernel/initramfs image and that’s it!

Summary

-bash-4.3# fdisk /dev/sda # starting with an empty disk (create MBR with a single partition)
Command (m for help): o
Command (m for help): n
Select (default p): 
Partition number (1-4, default 1): 
First sector (2048-500118191, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-500118191, default 500118191): 
Command (m for help): p
Command (m for help): w

-bash-4.3# cryptsetup luksFormat -v /dev/sda1 # let's encrypt the single partition
Are you sure? (Type uppercase yes): YES

-bash-4.3# cryptsetup luksOpen /dev/sda1 lvm-system # open it

-bash-4.3# pvcreate /dev/mapper/lvm-system # create a physical volume
-bash-4.3# vgcreate lvmSystem /dev/mapper/lvm-system # create a volume group
-bash-4.3# lvcreate -L 2.84G lvmSystem -n volSwap # create a logical swap partition (e.g same size as the RAM)
-bash-4.3# lvcreate -l +100%FREE lvmSystem -n volRoot # create a logical root partition (the rest of the available space)
-bash-4.3# mkswap /dev/lvmSystem/volSwap # format the swap partition
-bash-4.3# mkfs.ext4 /dev/lvmSystem/volRoot # format the root partition

-bash-4.3# mount /dev/lvmSystem/volRoot /mnt # mount root
-bash-4.3# swapon /dev/lvmSystem/volSwap # mount swap
-bash-4.3# mkdir /mnt/{boot,dev,proc,sys,home,root} # create necessary directories
-bash-4.3# mount --rbind /dev /mnt/dev
-bash-4.3# mount --rbind /proc /mnt/proc
-bash-4.3# mount --rbind /sys /mnt/sys
-bash-4.3# xbps-install -S -R https://repo.voidlinux.eu/current/ -r /mnt base-system base-devel lvm2 cryptsetup grub
[*] Updating `https://repo.voidlinux.eu/current//x86_64-repodata' ...
x86_64-repodata: 1085KB [avg rate: 128KB/s]
`https://repo.voidlinux.eu/current/' repository has been RSA signed by "Void Linux"
Fingerprint: 60:ae:0c:d6:f0:95:17:80:bc:93:46:7a:89:af:a3:2d
Do you want to import this public key? [Y/n] Y

List of packages to be installed into the /mnt directory...
...
Do you want to continue? [Y/n] Y

[*] Downloading binary packages
...
[*] Verifying package integrity
...
[*] Running transaction tasks
...
[*] Configuring unpacked packages
...

150 downloaded, 150 installed, 0 updated, 150 configured, 0 removed.
-bash-4.3# chroot /mnt /bin/bash
bash-4.3# passwd root
New password:
Retype new password:

bash-4.3# chown root:root /
bash-4.3# chmod 755 /
bash-4.3# vi /etc/rc.conf # set TIMEZONE
bash-4.3# echo DESIREDHOSTNAME > /etc/hostname

bash-4.3# blkid | grep volRoot | sed 's/^.*UUID="/UUID=/g' | sed 's/".*/ \/              ext4            rw,relatime,data=ordered,discard        0 1/g'
bash-4.3# blkid | grep volSwap | sed 's/^.*UUID="/UUID=/g' | sed 's/".*/ none            swap            defaults                                0 0/g'
bash-4.3# cat /etc/fstab # and check fstab to look similar to the following
#                       
tmpfs       /tmp    tmpfs   defaults,nosuid,nodev   0       0
UUID=abcdef01-2345-6789-abcd-ef0123456789   /           ext4        rw,relatime,data=ordered,discard    0 1
UUID=98765432-10fe-dcba-9876-543210fedcba   none        swap        defaults                0 0

bash-4.3# echo "LANG=en_US.UTF-8" > /etc/locale.conf # or DESIRED LOCALE
bash-4.3# echo "en_US.UTF-8 UTF-8" >> /etc/default/libc-locales
bash-4.3# xbps-reconfigure -f glibc-locales
bash-4.3# echo hostonly=yes > /etc/dracut.conf.d/hostonly

bash-4.3# cat /etc/default/grub # to look as follows

# Configuration file for GRUB.
#
GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=0
#GRUB_HIDDEN_TIMEOUT_QUIET=false
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="Void"
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=4"
# Uncomment to use basic console
#GRUB_TERMINAL_INPUT="console"
# Uncomment to disable graphical terminal
#GRUB_TERMINAL_OUTPUT=console
GRUB_BACKGROUND=/usr/share/void-artwork/splash.png
#GRUB_GFXMODE=1920x1080x32
#GRUB_DISABLE_LINUX_UUID=true
#GRUB_DISABLE_RECOVERY=true

GRUB_CRYPTODISK_ENABLE=y  # This option worked on void
GRUB_ENABLE_CRYPTODISK=y  # This one worked on Arch (include both just in case).
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=4 rd.auto=1"
GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda1:lvm-system"

bash-4.3# dd if=/dev/urandom of=/crypto_keyfile.bin bs=512 count=8 iflag=fullblock # generate a random key
bash-4.3# cryptsetup luksAddKey /dev/sda1 /crypto_keyfile.bin # add the key
bash-4.3# blkid | grep LUKS | awk '{print $2}' | sed 's/UUID="/lvm-system        UUID=/g' | sed 's/"/    \/crypto_keyfile.bin    luks/g' >> /etc/crypttab
bash-4.3# cat /etc/crypttab # and check crypttab to look similar to the following
# crypttab: mappings for encrypted partitions
lvm-system  UUID=01234567-89ab-cdef-0123-456789abcdef   /crypto_keyfile.bin luks

bash-4.3# echo "install_items+=\"/etc/crypttab /crypto_keyfile.bin\"" >> /etc/dracut.conf.d/10-crypt.conf
bash-4.3# cat /etc/dracut.conf.d/10-crypt.conf

bash-4.3# chmod 000 /crypto_keyfile.bin # actually, even root doesn't need to access the keys
bash-4.3# chmod -R g-rwx,o-rwx /boot

bash-4.3# mkdir /boot/grub # installation of GRUB # grub directory is missing, da fuq?!
bash-4.3# grub-mkconfig -o /boot/grub/grub.cfg # create initramfs image
bash-4.3# grub-install /dev/sda # install grub

bash-4.3# xbps-reconfigure -f linux4.6 # recompile the current kernel (whilst ignoring locale errors)

bash-4.3# chsh -s /bin/bash # change the default shell for root, /bin/sh as default, ye serious?!

bash-4.3# exit # exit chroot
-bash-4.3# reboot && exit # reboot and exit the installation process

Option 2: your disk uses EFI

WIP