Plugins¶
As of now plugins for the following bootloaders exist:
- FreeBSD’s loader -
freebsdloader - systemd-boot -
systemdboot - GRUB (alpha) -
grub
In order to integrate with a bootloader, an extra flag ‘-b/--bootloader’
must be used to specify a bootloader plugin. The plugin will make the necessary
changes to boot from the new Boot Environment.
If you expect you will always be using a certain bootloader, you can set the
org.zedenv:bootloader property on your boot environments, and the
bootloader plugin will be used without you having to specify.
$ zedenv set org.zedenv:bootloader=<bootloader plugin>
Plugins available for your system can be listed with zedenv --plugins.
freebsdloader¶
The freebsdloader plugin is quite simple. During activation, it will
respect /etc/rc.d/zfsbe if it exists, and set, all datasets to
canmount=noauto, otherwise the datasets will be set canmount=on.
It will also change the root dataset to mount from in /boot/loader.conf,
and /boot/loader.conf.local.
The current /boot/zfs/zpool.cache will also be copied into the newly
activated boot environment.
systemdboot¶
Multiple kernels can be managed with this plugin and systemd-boot, but it will require changing the mountpoint of the esp (EFI System Partition).
Problem With Regular Mountpoint¶
Usually the $esp would get mounted at /boot or /boot/efi. The
kernels would sit in the root of the $esp, and the configs for systemdboot
in $esp/loader/.
$esp
.
├── initramfs-linux-fallback.img
├── initramfs-linux.img
├── intel-ucode.img
├── vmlinuz-linux
│
└── loader/
├── entries/
│ └── arch.conf
└── loader.conf
The configs would then reference kernels in the root directory.
title Arch Linux
linux vmlinuz-linux
initrd intel-ucode.img
initrd initramfs-linux.img
options zfs=bootfs rw
The problem with this method, is multiple kernels cannot be kept at the same time. Therefore this hierarchy is not conducive to boot environments.
Alternate Mountpoint¶
First, remount the $esp to a new location, the default is /mnt/efi.
If you would like to explicitly specify the mountpoint used, you can set the
org.zedenv.systemdboot:esp property on your current boot environment, and the plugin
will use the specified location:
zedenv set org.zedenv.systemdboot:esp='/mnt/efi'
Don’t forget to change the mount point in /etc/fstab.
UUID=9F8A-F566 /mnt/efi vfat rw,defaults,errors=remount-ro 0 2
Now, make a subdirectory $esp/env, kernels will be kept in a subdirectory
of this location.
The bootloader configuration can now use a different path for each boot environment.
So the ‘default’ boot environment config, located at
$esp/loader/entries/zedenv-default.conf, would look something like:
title Arch Linux
linux /env/zedenv-default/vmlinuz-linux
initrd /env/zedenv-default/intel-ucode.img
initrd /env/zedenv-default/initramfs-linux.img
options zfs=zpool/ROOT/default rw
To make the system happy when it looks for kernels at /boot, this directory
should be bindmounted to /boot.
Bindmount /mnt/efi/env/zedenv-default to /boot in /etc/fstab.
/mnt/efi/env/zedenv-default /boot none rw,defaults,errors=remount-ro,bind 0 0
If this directory is not here, the kernels will not be updated when the system rebuilds the kernel.
Once our system is set up in the proper configuration, zedenv will update
the bootloader, and fstab - if requested - when a new boot environment is
activated.
It will also update the configuration described above, asking you if the modifications that made are correct. You will have a chance to inspect and change them if they are not.
If you are confident and the changes it is making, and do not wish to inspect
them, adding the --noconfirm/-y flag will run the command without asking
for confirmation.
GRUB¶
GRUB support is provided via external plugin.
One of two types of setup can be used with grub.
- Boot on ZFS - separate
grubdataset needed. - Separate partition for kernels
Boot on ZFS (Recommended)¶
To use boot on ZFS:
- A
grubdataset is needed. It should be mounted at/boot/grub. org.zedenv.grub:bootonzfsshould be set toyes- Individual boot environments should contain their kernels in
/boot, which should be part of the root dataset.
To convert an existing grub install, set up the grub dataset, and mount it. Then install grub again.
zfs create -o canmount=off zroot/boot
zfs create -o mountpoint=legacy zroot/boot/grub
mount -t zfs zroot/boot/grub /boot/grub
# efi
mount ${esp} /boot/efi
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB
# or for BIOS
grub-install --target=i386-pc /dev/sdx --recheck
If you get:
/dev/sda
Installing for i386-pc platform.
grub-install: error: failed to get canonical path of `/dev/ata-SAMSUNG_SSD_830_Series_S0VVNEAC702110-part2'.
A workaround is to symlink the expected partition to the id
ln -s /dev/sda2 /dev/ata-SAMSUNG_SSD_830_Series_S0VVNEAC702110-part2
Separate Partition for Kernels¶
An example system on Arch Linux with a separate partition for kernels would be the following:
- Boot partition mounted to
/mnt/boot. - The directory containing kernels for the active boot environment,
/mnt/boot/env/zedenv-${boot_env}bind mounted to/boot. - The grub directory
/mnt/boot/grubbindmounted to/boot/grub org.zedenv.grub:bootonzfsshould be set tono
What this would look like during an arch Linux install would be the following:
zpool import -d /dev/disk/by-id -R /mnt vault
mkdir -p /mnt/mnt/boot /mnt/boot
mount /dev/sda1 /mnt/mnt/boot
mkdir /mnt/mnt/boot/env/zedenv-default /mnt/boot/grub
mount --bind /mnt/mnt/boot/env/zedenv-default /mnt/boot
mount --bind /mnt/mnt/boot/grub /mnt/boot/grub
genfstab -U -p /mnt >> /mnt/etc/fstab
arch-chroot /mnt /bin/bash
In chroot
export ZPOOL_VDEV_NAME_PATH=1
grub-install --target=x86_64-efi --efi-directory=/mnt/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
Converting Existing System¶
Create a backup.
cp /boot /boot.bak
Unmount /boot, and remount it at /mnt/boot.
mkdir -p /mnt/boot
mount /dev/sdxY /mnt/boot
Then you want to move your current kernel to /mnt/boot/env/zedenv-${boot_env_name}
mkdir /mnt/boot/env/zedenv-default
mv /mnt/boot/* /mnt/boot/env/zedenv-default
Move the grub directory back if it was also moved (or don’t move it in the first place).
mv /mnt/boot/env/zedenv-default/grub /mnt/boot/grub
Now bindmount the current kernel directory to /boot so that everything is where the system expects it.
mount --bind /mnt/boot/env/zedenv-default /boot
Same thing with the grub directory
mount --bind /mnt/boot/grub /boot/grub
Now everything is back to appearing how it looked originally, but things are actually stored in a different place.
You’re also probably going to want to update your fstab, if you’re using Arch you can use genfstab, which requires arch-install-scripts.
genfstab -U -p /
You’ll need to add the output to /etc/fstab.
This is what an example looks like.
# /dev/sda1
UUID=B11F-0328 /mnt/boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 2
/mnt/boot/env/zedenv-grub-test-3 /boot none rw,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro,bind 0 0
/mnt/boot/grub /boot/grub none rw,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro,bind 0 0
Post Setup¶
After install, run zedenv --plugins, you should see grub.
zedenv will do its best to decide whether or not you are booting off of an all ZFS system, but it can also be set explicitly with org.zedenv.grub:bootonzfs=yes.
Any values you have set explicitly will show up with zedenv get.
You may want to disable all of the grub generators in /etc/grub.d/ except for 00_header and the zedenv generator 05_zfs_linux.py by removing the executable bit.