Leap 15.4 UEFI

Preparation

This guide can be used to install openSUSE Leap onto a single disk with or without ZFS encryption.

It assumes the following:

  • Your system uses UEFI to boot

  • Your system is x86_64

  • You're mildly comfortable with ZFS, EFI and discovering system facts on your own (lsblk, dmesg, gdisk, ...)

Download openSUSE Leap 15.4 , write it to a USB drive and boot your system in EFI mode.

Confirm EFI support:

# dmesg | grep -i efivars
[    0.301784] Registered efivars operations

Configure Live Environment

Disable automounting

gsettings set org.gnome.desktop.media-handling automount false

Switch to a root account

sudo -i

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="$ID"

Enable filesystems repository

zypper -n addrepo https://download.opensuse.org/repositories/filesystems/$(lsb_release -rs)/filesystems.repo
zypper refresh

Install updated ZFS packages

zypper -n install zfs zfs-kmp-default
modprobe zfs

Generate /etc/hostid

zgenhostid -f 0x00bab10c

Define disk variables

For convenience and to reduce the likelihood of errors, set environment variables that refer to the devices that will be configured during the setup.

For many users, it is most convenient to place boot files (i.e., ZFSBootMenu and any loader responsible for launching it) on the the same disk that will hold the ZFS pool. However, some users may wish to dedicate an entire disk to the ZFS pool or create a multi-disk pool. A USB flash drive provides a convenient location for the boot partition. Fortunately, this alternative configuration is easily realized by simply defining a few environment variables differently.

Verify your target disk devices with lsblk. /dev/sda and /dev/sdb used below are examples.

First, define variables that refer to the disk and partition number that will hold boot files:

export BOOT_DISK="/dev/sda"
export BOOT_PART="1"
export BOOT_DEVICE="${BOOT_DISK}${BOOT_PART}"

Next, define variables that refer to the disk and partition number that will hold the ZFS pool:

export POOL_DISK="/dev/sda"
export POOL_PART="2"
export POOL_DEVICE="${POOL_DISK}${POOL_PART}"

Disk preparation

Wipe partitions

wipefs -a "$POOL_DISK"
wipefs -a "$BOOT_DISK"

sgdisk --zap-all "$POOL_DISK"
sgdisk --zap-all "$BOOT_DISK"

Create EFI boot partition

sgdisk -n "${BOOT_PART}:1m:+512m" -t "${BOOT_PART}:ef00" "$BOOT_DISK"

Create zpool partition

sgdisk -n "${POOL_PART}:0:-10m" -t "${POOL_PART}:bf00" "$POOL_DISK"

ZFS pool creation

Create the zpool

zpool create -f -o ashift=12 \
 -O compression=lz4 \
 -O acltype=posixacl \
 -O xattr=sa \
 -O relatime=on \
 -o autotrim=on \
 -m none zroot "$POOL_DEVICE"

Enable zpool.cache

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

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

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 mount zroot/ROOT/${ID}
zfs mount zroot/home

Verify that everything is mounted correctly

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

Install Leap

Enable software repositories

zypper --root /mnt ar https://download.opensuse.org/distribution/leap/$(lsb_release -rs)/repo/non-oss non-oss
zypper --root /mnt ar https://download.opensuse.org/distribution/leap/$(lsb_release -rs)/repo/oss oss
zypper --root /mnt ar https://download.opensuse.org/update/leap/$(lsb_release -rs)/oss update-oss
zypper --root /mnt ar https://download.opensuse.org/update/leap/$(lsb_release -rs)/non-oss update-nonoss
zypper --root /mnt ar https://download.opensuse.org/repositories/filesystems/$(lsb_release -rs)/filesystems.repo
zypper --root /mnt refresh

Note

Enter a to always trust the key.

Add base packages

zypper --root /mnt install -t pattern enhanced_base

Add package management

zypper --root /mnt install zypper yast2

Copy files into the new install

rm /mnt/etc/resolv.conf
cp -L /etc/resolv.conf /mnt/etc
cp /etc/hostid /mnt/etc
mkdir -p /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs

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 system configuration

update-ca-certificates
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
echo 'YOURHOSTNAME' > /etc/hostname
echo -e '127.0.1.1\tYOURHOSTNAME' >> /etc/hosts
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 "
EOF

Install kernel packages

zypper -n install kernel-default kernel-firmware

Install ZFS

zypper -n install zfs zfs-kmp-default

Build Kernel Modules

dracut --regenerate-all --force

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 rhgb" zroot/ROOT

Create a vfat filesystem

mkfs.vfat -F32 "$BOOT_DEVICE"

Create an fstab entry and mount

cat << EOF >> /etc/fstab
$( blkid | grep "$BOOT_DEVICE" | cut -d ' ' -f 2 ) /boot/efi vfat defaults 0 0
EOF

mkdir -p /boot/efi
mount /boot/efi

Install ZFSBootMenu

Fetch a prebuilt ZFSBootMenu EFI executable, saving it to the EFI system partition:

mkdir -p /boot/efi/EFI/ZBM
curl -o /boot/efi/EFI/ZBM/VMLINUZ.EFI -L https://get.zfsbootmenu.org/efi
cp /boot/efi/EFI/ZBM/VMLINUZ.EFI /boot/efi/EFI/ZBM/VMLINUZ-BACKUP.EFI

Configure EFI boot entries

mount -t efivarfs efivarfs /sys/firmware/efi/efivars
zypper -n install efibootmgr
efibootmgr -c -d "$BOOT_DISK" -p "$BOOT_PART" \
  -L "ZFSBootMenu (Backup)" \
  -l \\EFI\\ZBM\\VMLINUZ-BACKUP.EFI

efibootmgr -c -d "$BOOT_DISK" -p "$BOOT_PART" \
  -L "ZFSBootMenu" \
  -l \\EFI\\ZBM\\VMLINUZ.EFI

See also

Some systems can have issues with EFI boot entries. If you reboot and do not see the above entries in your EFI selection screen (usually accessible through an F key during POST), you might need to use a well-known EFI file name. See Portable EFI for help with this. Your existing ESP can be used, in place of an external USB drive.

Refer to zbm-kcl.8 and zfsbootmenu.7 for details on configuring the boot-time behavior of ZFSBootMenu.

Prepare for first boot

Exit the chroot, unmount everything

exit
umount -n -R /mnt

Export the zpool and reboot

zpool export zroot
reboot