# Installing Void Linux with encrypted Root on ZFS
#### This guide is how I install Void Linux onto a single disk with with encrypted Root on ZFS and a seperate encrypted swap partition.
It assumes the following:
Your system uses UEFI to boot
Your system is x86_64
You will use glibc as your system libc.
You're mildly comfortable with ZFS, EFI and discovering system facts on your own (lsblk, dmesg, gdisk, ...)
ZFSBootMenu does not require glibc and is not restricted to x86_64. If you are comfortable installing Void Linux on other architectures or with the musl libc, you can adapt the instructions here to your desired configuration.
### Please note that I have used information from the sources listed below:
> ZFS BootMenu Docs
<https://docs.zfsbootmenu.org/en/v2.3.x/guides/void-linux/uefi.html>
> Void Linux ZFS Docs
<https://docs.voidlinux.org/installation/guides/zfs.html>
> Chain's computar projects<br>
<https://forum.level1techs.com/t/chains-computar-projects/190001>
> Daniel Wayne Armstrong Blog<br>
<https://www.dwarmstrong.org/encrypt-swap/>
# To start
Download the latest hrmpf image from:<br>
<https://github.com/leahneukirchen/hrmpf>
Write it to USB drive and boot your system in EFI mode.
Confirm EFI support:
```
# dmesg | grep -i efivars
[ 0.301784] Registered efivars operations
```
# Configure Live Environment
## Source /etc/os-release
The file /etc/os-release defines variables that describe the running distribution. In particular, the $ID variable defined within can be used as a short name for the filesystem that will hold this installation.
```
source /etc/os-release
export ID
```
## Generate /etc/hostid
```
zgenhostid -f 0x00bab10c
```
# Disk preparation
Verify your target disk devices with lsblk. `/dev/sda`, `/dev/sdb` and `/dev/nvme0n1`.
<br>
On my laptop I,ll be using a single drive on `/dev/nvme0n1` with three paritions as follows:
**1 - EFI boot**
**2 - Swap** ( I'm using 64Gb but you can adjust to suit your needs or just not create swap and number the zpool parition 2 )
**3 - Zpool** ( This partition uses the remaining disk space )
**Note you will need to adjust below when wiping partitions if you use seperate disks.**
## Wipe partitions
```
zpool labelclear -f "/dev/nvme0n1"
wipefs -a "/dev/nvme0n1"
sgdisk --zap-all "/dev/nvme0n1"
```
## Create EFI boot partition
```
sgdisk -n "1:1m:+512m" -t "1:ef00" "/dev/nvme0n1"
```
## Create swap partition
```
sgdisk -n "2::64Gb" -t "2:8200" "/dev/nvme0n1" -c "2:cryptswap" "/dev/nvme0n1"
```
## Create zpool partition
```
sgdisk -n "3:0:-10m" -t "3:bf00" "/dev/nvme0n1"
```
# ZFS pool creation
## Store the pool passphrase in a key file
```
echo 'SomeKeyphrase' > /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key
```
## Create the encrypted zpool
```
zpool create -f -o ashift=12 \
-O compression=lz4 \
-O acltype=posixacl \
-O xattr=sa \
-O relatime=on \
-O encryption=aes-256-gcm \
-O keylocation=file:///etc/zfs/zroot.key \
-O keyformat=passphrase \
-o autotrim=on \
-m none zroot "/dev/disk/by-id/wwn-0x5000c500deadbeef-part3"
```
Adjust the pool (-o) and filesystem (-O) options as desired, and replace the partition identifier `wwn-0x5000c500deadbeef-part3` with that of the actual partition to be used.
You can find this out by typing `ls /dev/disk/by-id/` and they will be listed in the output.
When adding disks or partitions to ZFS pools, it is generally advisable to refer to them by the symbolic links created in /dev/disk/by-id or (on UEFI systems) /dev/disk/by-partuuid so that ZFS will identify the right partitions even if disk naming should change at some point. Using traditional device nodes like /dev/sda3 may cause intermittent import failures.
## Create initial file systems
```
zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/${ID}
zfs create -o mountpoint=/home zroot/home
zpool set bootfs=zroot/ROOT/${ID} zroot
```
> **Note**
It is important to set the property `canmount=noauto` on any file systems with `mountpoint=/` (that is, on any additional boot environments you create). Without this property, the OS will attempt to automount all ZFS file systems and fail when multiple file systems attempt to mount at `/`; this will prevent your system from booting. Automatic mounting of `/` is not required because the root file system is explicitly mounted in the boot process.
Also note that, unlike many ZFS properties, `canmount` is not inheritable. Therefore, setting `canmount=noauto` on `zroot/ROOT` is not sufficient, as any subsequent boot environments you create will default to `canmount=on`. It is necessary to explicitly set the `canmount=noauto` on every boot environment you create.
## Export, then re-import with a temporary mountpoint of `/mnt`
```
zpool export zroot
zpool import -N -R /mnt zroot
zfs load-key -L prompt zroot
```
```
zfs mount zroot/ROOT/${ID}
zfs mount zroot/home
```
## Verify that everything is mounted correctly
```
# mount | grep mnt
zroot/ROOT/void on /mnt type zfs (rw,relatime,xattr,posixacl)
zroot/home on /mnt/home type zfs (rw,relatime,xattr,posixacl)
```
## Update device symlinks
```
udevadm trigger
```
## Install Void
Adjust the mirror, libc, and package selection as you see fit.
```
XBPS_ARCH=x86_64 xbps-install \
-S -R https://mirrors.servercentral.com/voidlinux/current \
-r /mnt base-system
```
## Copy our files into the new install
```
cp /etc/hostid /mnt/etc
mkdir /mnt/etc/zfs
cp /etc/zfs/zroot.key /mnt/etc/zfs
```
## Chroot into the new OS
```
xchroot /mnt
```
## Basic Void configuration
### Set the keymap, timezone and hardware clock
```
cat << EOF >> /etc/rc.conf
KEYMAP="us"
HARDWARECLOCK="UTC"
TIMEZONE="Europe/London"
EOF
```
## Configure your glibc locale
```
cat << EOF >> /etc/default/libc-locales
en_US.UTF-8 UTF-8
en_US ISO-8859-1
EOF
xbps-reconfigure -f glibc-locales
```
## Set a root password
```
passwd
```
# ZFS Configuration
## Configure Dracut to load ZFS support
```
cat << EOF > /etc/dracut.conf.d/zol.conf
nofsck="yes"
add_dracutmodules+=" zfs "
omit_dracutmodules+=" btrfs resume "
install_items+=" /etc/zfs/zroot.key "
EOF
```
## Install ZFS and Cryptsetup
```
xbps-install -S zfs cryptsetup
```
## To quickly discover and import pools on boot, we need to set a pool cachefile
```
zpool set cachefile=/etc/zfs/zpool.cache zroot
```
# Install and configure ZFSBootMenu
## Set ZFSBootMenu properties on datasets
Assign command-line arguments to be used when booting the final kernel. Because ZFS properties are inherited, assign the common properties to the ROOT dataset so all children will inherit common arguments by default.
```
zfs set org.zfsbootmenu:commandline="quiet loglevel=4" zroot/ROOT
```
Setup key caching in ZFSBootMenu.
```
zfs set org.zfsbootmenu:keysource="zroot/ROOT/${ID}" zroot
```
## Create `vfat` and encrypted `swap` filesystems
```
mkfs.vfat -F32 /dev/nvme0n1p1
```
```
cat << EOF >> /etc/crypttab
cryptswap /dev/disk/by-partlabel/cryptswap /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=512
EOF
```
# Create fstab entries and mount the efi partition
```
cat << EOF >> /etc/fstab
$( blkid | grep /dev/nvme0n1p1 | cut -d ' ' -f 2 ) /boot/efi vfat defaults 0 0
/dev/mapper/cryptswap none swap defaults 0 0
EOF
mkdir -p /boot/efi
mount /boot/efi
```
## Install ZFSBootMenu
```
xbps-install -S zfsbootmenu gummiboot-efistub
```
Configure generate-zbm(5) by ensuring that the following keys appear in /etc/zfsbootmenu/config.yaml:
```
Global:
ManageImages: true
BootMountPoint: /boot/efi
Components:
Enabled: false
EFI:
ImageDir: /boot/efi/EFI/zbm
Versions: false
Enabled: true
Kernel:
CommandLine: quiet loglevel=0
```
My `CommandLine:` will be as follows as I don't want ZFSBootMenu automatically resizing the fonts according to the display size.
```
CommandLine: quiet loglevel=0 zbm.skip_hooks=20-console-autosize.sh
```
## Create a ZFSBootMenu image:
```
generate-zbm
```
## Configure EFI boot entries
```
xbps-install efibootmgr
```
```
efibootmgr -c -d "/dev/nvme0n1" -p "1" \
-L "ZFSBootMenu (Backup)" \
-l '\EFI\ZBM\VMLINUZ-BACKUP.EFI'
efibootmgr -c -d "/dev/nvme0n1" -p "1" \
-L "ZFSBootMenu" \
-l '\EFI\ZBM\VMLINUZ.EFI'
```
# Prepare for first boot
## Exit the chroot, unmount everything
```
exit
```
```
umount -n -R /mnt
```
## Export the zpool and reboot
```
zpool export zroot
```
```
reboot
```