Here's a record of my experiences when setting up Void Linux for the first time, maybe it contains useful information for somebody :-)
- Laptop: Lenovo IdeaPad S340
- Void Linux installer version: 20191109 (x86_64 musl)
This guide explains how to set up Void Linux:
- On an NVMe disk
- Using full disk encryption - including /boot, with LUKS + LVM
- Uses btrfs as filesystem
- Offers a poor-man's 2FA using Yubikey's static password feature
- SSD/NVMe trimming only works if it is enabled on all intermediate layers, which in this case means LUKS, LVM and btrfs
- What I call "2FA" is not really 2FA, but rather a simplistic way to get "something you know" (a passphrase) and "something you have" (a Yubikey token, in my case). Yubikey has a feature to emit a static password upon pressing a button on the token. This is modeled as a USB keyboard, so it supports a wide range of hardware. The approach is to make the LUKS passphrase composed of two pieces: First, a password you have to remember, followed directly by the passphrase generated by the token.
# boot Void live system and log in using root:voidlinux
loadkeys de
cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-<interface>.conf
wpa_passphrase <SSID> <password> >> /etc/wpa_supplicant/wpa_supplicant-<interface>.conf
wpa_supplicant -B -i <interface> -c /etc/wpa_supplicant/wpa_supplicant-<interface>.conf
fdisk /dev/nvme0n1
# g to create a new GTP partition ta
# n new partition with +200M
# t 1 to set partition type to EFI
# n new partition with remaining space
# set up encryption
# here's the 2FA "trick":
# prepare a YubiKey that emits a *static* passphrase
# when pressing its touch button (best use the maximum
# passphrase length offered - 64 characters at the time
# of writing).
# when asked for the passphrase, *first* enter a
# password you need to *know*, then press the button
# on the Yubikey - voila, you have a passphrase requiring
# something you know and something to have
# not sufficient for government-grade security, maybe, but
# for my humble home laptop, it's OK
cryptsetup luksFormat --type=luks1 /dev/nvme0n1p2
cryptsetup open /dev/nvme0n1p2 crypt
# prepare LVM
vgcreate vg0 /dev/mapper/crypt
lvcreate --name swap -L 25G vg0
lvcreate --name void -l +100%FREE vg0
# filesystems
mkfs.vfat -n BOOT -F 32 /dev/nvme0n1p1
mkswap /dev/mapper/vg0-swap
mkfs.btrfs -L void /dev/mapper/vg0-void
mount -o rw,noatime,ssd,compress=lzo,space_cache,commit=60 /dev/mapper/vg0-void /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@snapshots
umount /mnt
mount -o rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@ /dev/mapper/vg0-void /mnt
mkdir /mnt/home
mkdir /mnt/.snapshots
mount -o rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@home /dev/mapper/vg0-void /mnt/home/
mount -o rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@snapshots /dev/mapper/vg0-void /mnt/.snapshots/
mkdir -p /mnt/boot/efi
mount -o rw,noatime /dev/nvme0n1p1 /mnt/boot/efi/
mkdir -p /mnt/var/cache
btrfs subvolume create /mnt/var/cache/xbps
btrfs subvolume create /mnt/var/tmp
btrfs subvolume create /mnt/srv
export XBPS_ARCH=x86_64-musl
xbps-install -Sy -R https://alpha.de.repo.voidlinux.org/current/musl -r /mnt base-system btrfs-progs cryptsetup grub-x86_64-efi lvm2
mount -t proc proc /mnt/proc/
mount -t sysfs sys /mnt/sys/
mount -o bind /dev /mnt/dev
mount -t devpts pts /mnt/dev/pts
cp -L /etc/resolv.conf /mnt/etc/
cp -L /etc/wpa_supplicant/wpa_supplicant-<interface>.conf /mnt/etc/wpa_supplicant/
chroot /mnt /bin/bash
passwd root
chown root:root /
chmod 755 /
echo <hostname> > /etc/hostname
cat <<EOF > /etc/rc.rc.conf
# /etc/rc.conf - system configuration for void
HOSTNAME="<hostname>"
HARDWARECLOCK="UTC"
TIMEZONE="Europe/Amsterdam"
KEYMAP="de"
EOF
echo 'en_US.UTF-8 UTF-8' > /etc/default/libc-locales
echo LANG=en_US.UTF-8 > /etc/locale.conf
export UEFI_UUID=$(blkid -s UUID -o value /dev/nvme0n1p1)
export LUKS_UUID=$(blkid -s UUID -o value /dev/nvme0n1p2)
export ROOT_UUID=$(blkid -s UUID -o value /dev/mapper/vg0-void)
export SWAP_UUID=$(blkid -s UUID -o value /dev/mapper/vg0-swap)
cat <<EOF > /etc/fstab
UUID=$ROOT_UUID / btrfs rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@ 0 1
UUID=$ROOT_UUID /home btrfs rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@home 0 2
UUID=$ROOT_UUID /.snapshots btrfs rw,noatime,ssd,compress=lzo,space_cache,commit=60,subvol=@snapshots 0 2
UUID=$UEFI_UUID /boot/efi vfat defaults,noatime 0 2
UUID=$SWAP_UUID none swap defaults 0 1
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
EOF
cat <<EOF >> /etc/default/grub
GRUB_ENABLE_CRYPTODISK=y
EOF
sed -i "/GRUB_CMDLINE_LINUX_DEFAULT=/s/\"$/ rd.auto=1 cryptdevice=UUID=$LUKS_UUID:lvm:allow-discards&/" /etc/default/grub
dd bs=512 count=4 if=/dev/urandom of=/boot/volume.key
cryptsetup luksAddKey /dev/nvme0n1p2 /boot/volume.key
chmod 000 /boot/volume.key
chmod -R g-rwx,o-rwx /boot
cat <<EOF >> /etc/crypttab
crypt /dev/nvme0n1p2 /boot/volume.key luks
EOF
cat <<EOF >> /etc/dracut.conf.d/10-crypt.conf
install_items+=" /boot/volume.key /etc/crypttab "
EOF
echo 'add_dracutmodules+=" crypt btrfs lvm resume "' >> /etc/dracut.conf
echo 'tmpdir=/tmp' >> /etc/dracut.conf
dracut --force --hostonly --kver 5.4.26_1
mkdir /boot/grub
grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=void --boot-directory=/boot --recheck
ln -s /etc/sv/dhcpcd /etc/runit/runsvdir/default
ln -s /etc/sv/wpa_supplicant/ /etc/runit/runsvdir/default
sed -i 's/issue_discards = 0/issue_discards = 1/' /etc/lvm/lvm.conf
As per "standing on the shoulders of giants", most of the information in this guide was no discovered by myself, but rather assembled from various existing guides, which I want to list here to give credit where credit is due:
[1] https://gist.github.com/gbrlsnchs/9c9dc55cd0beb26e141ee3ea59f26e21
[2] https://wiki.voidlinux.org/Full_Disk_Encryption_w/Encrypted_Boot
Great guide! I'm building my own setup based on it, but I use BTRFS on top of LUKS on top of LVM, because I want to support creating multiple users with /home's encrypted separately from each other, so multiple people could use the same installation without stealing someone else's data.
I also want root partition to be encrypted as well, via multiple key slots for each user.
For each user, user's passphrase should be used both for
root
keyslot and forhome
.With help of
cryptsetup-keyscript
,keyctl_keyscript
&PAM
, you can eliminate the need to enter passphrase twice. PC turns on, you enter your own passphrase, then both/
and/home/username
are opened, after that display manager logs you in without asking passphrase again.Unfortunately, it seems that
cryptsetup-keyscript
is based on Debian/Ubuntu specific patch.But it's possible to package it for
xbps
, as well askeyctl_keyscript
.I used to use ZFS for half a year, but it was slow (150 MiB/s max), because my laptop's CPU doesn't support AES-NI. At first I've thought about encrypting only important stuff instead of everything. Luckily, I've discovered Adiantum encryption algorithm.
cryptsetup benchmark -c xchacha12,aes-adiantum -s 256
gives me whopping 500 MiB/s per thread, which almost matches the speed of my mSATA SSD.