Skip to content

Void Linux Single disk syslinux MBR

Zach Dykstra edited this page Oct 1, 2020 · 13 revisions

This guide can be used to install Void onto a single ZFS disk with or without ZFS encryption. The EFI partition will be created on a removable disk.

It assumes the following:

  • Your system uses BIOS to boot
  • Your system is x86_64
  • You will use glibc as your system libc.
  • /dev/sda is the onboard SSD, used for ZFS and syslinux
  • You're mildly comfortable with ZFS and discovering system facts on your own (lsblk, dmesg, gdisk, ...)

When following this guide, if a section requires different steps to be taken for a system with encryption versus a system without encryption, the steps are behind a Encrypted or Unencrypted collapsible header.

Download the latest hrmpf, write it to USB drive and boot your system in BIOS mode.

ZFS prep work

Build and load ZFS modules

xbps-reconfigure -a
modprobe zfs

Generate /etc/hostid

zgenhostid

Store your pool passphrase in a key file

Encrypted

echo "SomeKeyphrase" > /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key

SSD prep work

Create a syslinux partition on /dev/sda

Encrypted and unencrypted

bash-5.0# fdisk /dev/sda

Welcome to fdisk (util-linux 2.35.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): o
Created a new DOS disklabel with disk identifier 0xf5f142cb.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-1000215215, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1000215215, default 1000215215): +512M

Created a new partition 1 of type 'Linux' and of size 512 MiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (1050624-1000215215, default 1050624): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-1000215215, default 1000215215): 

Created a new partition 2 of type 'Linux' and of size 476.4 GiB.

Command (m for help): a
Partition number (1,2, default 2): 1

The bootable flag on partition 1 is enabled now.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

ZFS pool creation

Create the zpool

Encrypted

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/sda2

It's out of the scope of this guide to cover all of the pool creation options used - feel free to tailor them to suit your system. However, the following options need to be addressed:

  • encryption=aes-256-gcm - You can adjust the algorithm as you see fit, but this will likely be the most performant on modern x86_64 hardware.
  • keylocation=file:///etc/zfs/zroot.key - This sets our pool encryption passphrase to the file /etc/zfs/zroot.key, which we created in a previous step. This file will live inside your initramfs stored ON the ZFS boot environment.
  • keyformat=passphrase - By setting the format to passphrase, we can now force a prompt for this in zfsbootmenu. It's critical that your passphrase be something you can type on your keyboard, since you will need to type it in to unlock the pool on boot.
Unencrypted

zpool create -f -o ashift=12 \
 -O compression=lz4 \
 -O acltype=posixacl \
 -O xattr=sa \
 -O relatime=on \
 -o autotrim=on \
 -m none zroot /dev/sda2

Create our initial file systems

zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/void.$( date +%Y.%m.%d )
zfs create -o mountpoint=/home zroot/home

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, Void 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

Encrypted

zpool export zroot
zpool import -N -R /mnt zroot
zfs load-key -L prompt zroot
zfs mount zroot/ROOT/void.$( date +%Y.%m.%d )
zfs mount zroot/home
Unencrypted

zpool export zroot
zpool import -N -R /mnt zroot
zfs mount zroot/ROOT/void.$( date +%Y.%m.%d )
zfs mount zroot/home

Verify that everything is mounted correctly

# mount | grep mnt
zroot/ROOT/void.2020.01.30 on /mnt type zfs (rw,relatime,xattr,posixacl)
zroot/home on /mnt/home type zfs (rw,relatime,xattr,posixacl)

Install Void

Adjust the mirror / libc / package selection as you see fit

XBPS_ARCH=x86_64 xbps-install -S -R https://mirrors.servercentral.com/voidlinux/current -r /mnt base-system zfs vim efibootmgr gptfdisk

Copy our files into the new install

Encrypted

cp /etc/hostid /mnt/etc
cp /etc/resolv.conf /mnt/etc/
cp /etc/zfs/zroot.key /mnt/etc/zfs
Unencrypted

cp /etc/hostid /mnt/etc
cp /etc/resolv.conf /mnt/etc/

Chroot into the new OS

mount -t proc proc /mnt/proc
mount -t sysfs sys /mnt/sys
mount -B /dev /mnt/dev
mount -t devpts pts /mnt/dev/pts
chroot /mnt /bin/bash

Basic Void configuration

Set the keymap, timezone and hardware clock

cat << EOF >> /etc/rc.conf
KEYMAP="us"
TIMEZONE="America/Chicago"
HARDWARECLOCK="UTC"
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

To more quickly discover and import pools on boot, we need to set a pool cachefile

zpool set cachefile=/etc/zfs/zpool.cache zroot

Configure our default boot environment

zpool set bootfs=zroot/ROOT/void.$( date +%Y.%m.%d ) zroot

Configure Dracut to load ZFS support

Encrypted

cat << EOF > /etc/dracut.conf.d/zol.conf
nofsck="yes"
add_dracutmodules+=" zfs "
omit_dracutmodules+=" btrfs "
install_items+=" /etc/zfs/zroot.key "
EOF
Unencrypted

cat << EOF > /etc/dracut.conf.d/zol.conf
nofsck="yes"
add_dracutmodules+=" zfs "
omit_dracutmodules+=" btrfs "
EOF

Rebuild the initramfs

xbps-reconfigure -f linux5.4

Install and configure ZFSBootMenu

  • 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="spl_hostid=$( hostid ) ro quiet" zroot/ROOT

Create an ext4 filesystem on /dev/sda1

mkfs.ext4 /dev/sda1

Create an fstab entry and mount

cat << EOF >> /etc/fstab
$( blkid | grep /dev/sda1 | cut -d ' ' -f 2 ) /boot/syslinux ext4 defaults 0 0
EOF
mkdir /boot/syslinux
mount /boot/syslinux

Install the syslinux package, copy modules

xbps-install -S
xbps-install -Rs syslinux
cp /usr/lib/syslinux/*.c32 /boot/syslinux

Install extlinux

bash-5.0# extlinux --install /boot/syslinux
/boot/syslinux is device /dev/sda1

Install the syslinux MBR data

bash-5.0# dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr.bin of=/dev/sda
1+0 records in
1+0 records out
440 bytes copied, 0.000306845 s, 1.4 MB/s

Install the ZFSBootMenu package

xbps-install -Rs zfsbootmenu

Enable zfsbootmenu image creation

Edit /etc/zfsbootmenu/config.yaml and set:

  • ManageImages: true and BootMountPoint: /boot/syslinux under the Global section
  • ImageDir: /boot/syslinux/zfsbootmenu, Versions: 3 and Enabled: true under the Components section
  • Enabled: true under the Components.syslinux section

See generate-zbm(5) for more details.

Sample /etc/zfsbootmenu/config.yaml

Global:
  ManageImages: true
  BootMountPoint: /boot/syslinux
  DracutConfDir: /etc/zfsbootmenu/dracut.conf.d
Components:
  ImageDir: /boot/syslinux/zfsbootmenu
  Versions: 3
  Enabled: true
  syslinux:
    Config: /boot/syslinux/syslinux.cfg
    Enabled: true
EFI:
  ImageDir: /boot/efi/EFI/void
  Versions: 2
  Enabled: false
Kernel:
  CommandLine: ro quiet loglevel=0

Generate the initial bootmenu initramfs

bash-5.0# xbps-reconfigure -f zfsbootmenu
zfsbootmenu: configuring ...
Mounting /boot/efi
Creating ZFS Boot Menu 1.1_1, with vmlinuz 5.4.48_1
Found 0 existing images, allowed to have a total of 3
Created /boot/syslinux/zfsbootmenu/vmlinuz-1.1_1, /boot/syslinux/zfsbootmenu/initramfs-1.1_1.img
Unmounting /boot/efi
zfsbootmenu: configured successfully.

Exit the chroot, unmount everything

exit
umount -n /mnt/{dev/pts,dev,sys,proc}
umount /mnt/boot/syslinux

Export the zpool and reboot

zpool export zroot
reboot
Clone this wiki locally