README: general clean up.
- grammar corrections - clear up language - fix up some formatting
This commit is contained in:
parent
87cd727425
commit
93881aa79e
91
README.md
91
README.md
|
@ -4,24 +4,26 @@
|
|||
|
||||
[![asciicast](https://asciinema.org/a/FN4gWtVUPPXzgZPrCjd8mK6Vz.svg)](https://asciinema.org/a/FN4gWtVUPPXzgZPrCjd8mK6Vz)
|
||||
|
||||
zfsbootmenu is implemented as a Dracut module to provide an experience similar to FreeBSD's bootloader, for Linux distributions. In broad strokes, it works as follows:
|
||||
ZFSBootMenu is a Dracut module that intends to provide Linux distributions with an experience similar to FreeBSD's bootloader. By taking advantage of ZFS features, it allows a user to have multiple "boot environments" (with different distros, for example), manipulate snapshots before booting, and, for the adventurous user, even bootstrap a system installation via `zfs recv`.
|
||||
|
||||
* Via GRUB, direct EFI booting, etc, boot a Linux kernel along with an initramfs containing ZFSBootMenu
|
||||
* Look for `zfsbootmenu` on the kernel command line
|
||||
* Optionally specify a default pool (if multiple are present)
|
||||
* Find all healthy pools and then import them
|
||||
* If a specific pool was set, look for the bootfs pool value. Prefer this boot environment.
|
||||
* If no pool was defined on the command line, use the bootfs value on the first-found pool
|
||||
* If a bootfs value is defined, start a 10 second countdown to boot that environment with the highest kernel found in /boot
|
||||
* If no bootfs value is defined, find every filesystem that mounts to / with a /boot directory, and find every kernel. Prompt via fzf.
|
||||
* If needed, prompt for encryption passphrases
|
||||
* Once the count down has been reached for the bootfs-selected environment, prompt for the encryption passphrase if needed
|
||||
* Mount the filesystem and find the highest-numbered kernel in /boot in the boot environment.
|
||||
* Load the kernel, initramfs and the kernel command line defined in the `org.zfsbootmenu:commandline` property (or, as a fallback, `/etc/default/grub`) into memory via kexec
|
||||
* Unmount all ZFS filesystems
|
||||
* Boot the final kernel and initramfs
|
||||
In broad strokes, it works as follows:
|
||||
|
||||
At this point, you'll be booting into your OS-managed kernel and initramfs, along with any arguments needed to correctly boot your system.
|
||||
* Via GRUB, direct EFI booting, etc, boot a Linux kernel along with an initramfs containing ZFSBootMenu.
|
||||
* Look for `zfsbootmenu` in the kernel command line.
|
||||
* Optionally specify a default pool (if multiple are present).
|
||||
* Find all healthy ZFS pools and import them.
|
||||
* If a specific pool was set, look for the `bootfs` pool value. Prefer this boot environment.
|
||||
* If no pool was defined in the command line, use the `bootfs` value on the first-found pool.
|
||||
* If a `bootfs` value is defined, start a 10 second (by default) countdown to boot that environment with the highest versioned kernel found in `/boot`.
|
||||
* If no `bootfs` value is defined, find every filesystem that mounts to `/` with a `/boot` directory, and find every kernel image. Prompt for boot environment selection via a fuzzy finder.
|
||||
* If needed, prompt for encryption passphrases.
|
||||
* Once the countdown has been reached for the bootfs-selected environment, prompt for the encryption passphrase if needed.
|
||||
* Mount the filesystem and find the highest versioned kernel in `/boot` in the selected boot environment.
|
||||
* Load the selected kernel and initramfs with the kernel command line defined in the `org.zfsbootmenu:commandline` property (or, as a fallback, `/etc/default/grub`) into memory with `kexec`.
|
||||
* Unmount all ZFS filesystems.
|
||||
* Boot the final kernel and initramfs.
|
||||
|
||||
At this point, you'll be booting into your usual OS-managed kernel and initramfs, along with any arguments needed to correctly boot your system.
|
||||
|
||||
This tool makes uses of the following additional software:
|
||||
* [fzf](https://github.com/junegunn/fzf) or [skim](https://github.com/lotabout/skim)
|
||||
|
@ -31,7 +33,7 @@ This tool makes uses of the following additional software:
|
|||
* [ZFS on Linux](https://zfsonlinux.org)
|
||||
* [dracut](https://github.com/dracutdevs/dracut)
|
||||
|
||||
ZFSBootMenu has been tested successfully with Kernel 5.8.14, Dracut 050 and OpenZFS 2.0.0-rc4
|
||||
ZFSBootMenu has been tested successfully with Kernel 5.8.14, Dracut 050 and OpenZFS 2.0.0-rc4.
|
||||
|
||||
# System prereqs
|
||||
|
||||
|
@ -57,9 +59,9 @@ On start, ZFSBootMenu will find the highest versioned kernel in `zroot/ROOT/void
|
|||
|
||||
# Installation
|
||||
|
||||
Kernel command-line arguments should be set by setting the ZFS property `org.zfsbootmenu:commandline` on each boot environment. If the property is not defined for a boot environment or its parents, command-line arguments will be taken from the `GRUB_CMDLINE_LINUX_DEFAULT` variable in the file `/etc/default/grub` of the boot environment if the file exist and the variable is defined. Do not set any `root=` or any other pool-related options in the kernel command line; these will be filled in automatically when a boot environment is selected.
|
||||
Kernel command line arguments should be configured by setting the `org.zfsbootmenu:commandline` ZFS property for each boot environment. If the property is not defined for a boot environment or its parents, command line arguments will be taken from the `GRUB_CMDLINE_LINUX_DEFAULT` variable defined in the boot environment's `/etc/default/grub` file, if it exists and the variable is set. Do not set any `root=` or any other pool-related options in the kernel command line; these will be filled in automatically when a boot environment is selected.
|
||||
|
||||
For example, I have the following command-line arguments set on my boot environment:
|
||||
For example, I have the following command line arguments set for my boot environment:
|
||||
|
||||
```
|
||||
zfs.zfs_arc_max=8589934592 elevator=noop
|
||||
|
@ -71,10 +73,10 @@ Because ZFS properties are inherited by default, it is possible to set the `org.
|
|||
|
||||
ZFSBootMenu integrates nicely with an EFI system. There will be two key things to configure here.
|
||||
|
||||
* The mountpoint of the EFI partition and it's contents
|
||||
* The mountpoint of the boot environment `/boot` and it's contents
|
||||
* The mountpoint of the EFI partition and its contents.
|
||||
* The mountpoint of the boot environment `/boot` and its contents.
|
||||
|
||||
Each boot environment should have `/boot` live on the ZFS filesystem. Using the above example, `zroot/ROOT/void.2019.11.01` would contain `/boot` with any kernel/initramfs pairs.
|
||||
Each boot environment should have its `/boot` directory in the ZFS filesystem. Using the above example, `zroot/ROOT/void.2019.11.01` would contain `/boot` with kernel/initramfs pairs:
|
||||
|
||||
```
|
||||
# ls /boot
|
||||
|
@ -89,8 +91,7 @@ vmlinuz-5.3.18_1
|
|||
vmlinuz-5.4.6_1
|
||||
```
|
||||
|
||||
|
||||
Once `/boot` is backed by ZFS in a boot environment, you'll need to install the boot menu files. Typically, EFI partitions are mounted to `/boot/efi`, and contain a number of sub-directories. In this example, `/boot/efi/EFI/void` holds the ZFSBootMenu kernel and initramfs.
|
||||
Once `/boot` is contained in a boot environment, it is necessary to install the boot menu files. Typically, EFI partitions (ESP) are mounted to `/boot/efi`, and contain a number of sub-directories. In this example, `/boot/efi/EFI/void` holds the ZFSBootMenu kernel and initramfs.
|
||||
|
||||
```
|
||||
# lsblk -f /dev/sda
|
||||
|
@ -106,18 +107,16 @@ vmlinuz-0.7.4
|
|||
vmlinuz-0.7.5
|
||||
```
|
||||
|
||||
With this layout, you'll now need a way to boot the kernel and initramfs via EFI. This can be done via a manual entry set via [efibootmgr](https://github.com/rhboot/efibootmgr), or it can be done with [rEFInd](http://www.rodsbooks.com/refind/).
|
||||
|
||||
With this layout, you'll now need a way to boot the kernel and initramfs via EFI. This can be done via a manual entry set via efibootmgr, or it can be done with rEFInd.
|
||||
If you do not generate the ZFSBootMenu initramfs locally, you'll need to identify the following additional details:
|
||||
|
||||
If you are using a pre-built kernel and initramfs downloaded from the releases page, you'll need to identify the following additional details:
|
||||
|
||||
* Your system's hostid (`hostid`). It's important that this command is executed as root, to ensure that it returns the correct value.
|
||||
* Your system's hostid (`hostid`). It's important that this command be executed as root, to ensure that it returns the correct value.
|
||||
* Your boot pool name, if you have multiple.
|
||||
* The disk path and partition index of your EFI partition. (/dev/sda, part 1)
|
||||
* The disk path and partition index of your EFI partition. (`/dev/sda`, part 1)
|
||||
|
||||
### efibootmgr
|
||||
|
||||
|
||||
```
|
||||
efibootmgr --disk /dev/sda \
|
||||
--part 1 \
|
||||
|
@ -130,25 +129,24 @@ efibootmgr --disk /dev/sda \
|
|||
|
||||
Take note to adjust `root=zfsbootmenu:POOL=`, `spl_hostid=`, `--disk` and `--part` to match your system configuration.
|
||||
|
||||
Each time the bootmenu is updated, a new EFI entry will need to be manually added.
|
||||
Each time ZFSBootMenu is updated, a new EFI entry will need to be manually added, unless you disable versioning in the ZFSBootMenu configuration.
|
||||
|
||||
### rEFInd
|
||||
|
||||
`rEFInd` is considerably easier to install and manage. Refer to your distributions packages for installation. Once rEFInd has been installed, you can create `refind_linux.conf` in the directory holding the ZFSBootMenu files (`/boot/efi/EFI/void` in our example):
|
||||
`rEFInd` is considerably easier to install and manage. Refer to your distribution's packages for installation. Once rEFInd has been installed, you can create `refind_linux.conf` in the directory holding the ZFSBootMenu files (`/boot/efi/EFI/void` in our example):
|
||||
|
||||
```
|
||||
"Boot Default BE" "ro quiet loglevel=0 timeout=0 root=zfsbootmenu:POOL= spl_hostid="
|
||||
"Select BE" "ro quiet loglevel=0 timeout=-1 root=zfsbootmenu:POOL= spl_hostid="
|
||||
```
|
||||
|
||||
|
||||
As with the efibootmgr section, the `root=zfsbootmenu:POOL=` and `spl_hostid=` options need to be configured to match your environment.
|
||||
|
||||
This file will configure `rEFInd` to create two entries for each kernel and initrams pair it finds. The first will directly boot into the environment set via the `bootfs` pool property. The second will force ZFSBootMenu to display an environment / kernel / snapshot selection menu, allowing you to boot alternate environments, kernels and snapshots.
|
||||
|
||||
# Kernel command-line options
|
||||
# Kernel command line options
|
||||
|
||||
The [zfsbootmenu(7)](pod/zfsbootmenu.7.pod#cli-parameters) manual page describes command-line options for ZFSBootMenu kernels in detail.
|
||||
The [zfsbootmenu(7)](pod/zfsbootmenu.7.pod#cli-parameters) manual page describes command line options for ZFSBootMenu kernels in detail.
|
||||
|
||||
# ZFS properties
|
||||
|
||||
|
@ -156,17 +154,19 @@ The [zfsbootmenu(7)](pod/zfsbootmenu.7.pod#zfs-properties) manual page describes
|
|||
|
||||
# initramfs creation
|
||||
|
||||
`bin/generate-zbm` can be used to create an initramfs on your system. It ships with void-specific defaults in [etc/zfsbootmenu/config.yaml](etc/zfsbootmenu/config.yaml). To create an initramfs, the following additional tools/libraries will need to be available on your system:
|
||||
`bin/generate-zbm` can be used to create an initramfs on your system. It ships with Void-specific defaults in [etc/zfsbootmenu/config.yaml](etc/zfsbootmenu/config.yaml). To create an initramfs, the following additional tools/libraries will need to be available on your system:
|
||||
|
||||
* For inclusion in the initramfs:
|
||||
* [fzf](https://github.com/junegunn/fzf) or [skim](https://github.com/lotabout/skim)
|
||||
* [kexec-tools](https://github.com/horms/kexec-tools)
|
||||
* [mbuffer](http://www.maier-komor.de/mbuffer.html)
|
||||
* For running `bin/generate-zbm`:
|
||||
* [perl Config::IniFiles](https://metacpan.org/pod/Config::IniFiles)
|
||||
* [perl YAML::PP](https://metacpan.org/pod/YAML::PP)
|
||||
|
||||
If you want to create an unified EFI file (kernel, initramfs, command line), you will also need:
|
||||
If you want to create a unified EFI executable (which bundles the kernel, initramfs and command line), you will also need:
|
||||
|
||||
* linuxx64.efi.stub (typically packaged with gummiboot)
|
||||
* linuxx64.efi.stub (typically packaged with gummiboot or systemd-boot)
|
||||
|
||||
Your distribution should have packages for these already.
|
||||
|
||||
|
@ -184,15 +184,15 @@ generate-zbm --migrate [ini-config] [--config yaml-config]
|
|||
|
||||
By default, the output YAML will be written to `/etc/zfsbootmenu/config.yaml`; use the `--config` argument to customize the output location.
|
||||
|
||||
The argument `[ini-config]` to `--migrate` is optional. When it is not provided, `generate-zbm` will derive an input file by dropping the `.yaml` extension from the output file and appending a `.ini` extension.
|
||||
The argument `[ini-config]` to `--migrate` is optional. When it is not provided, `generate-zbm` will derive an input file by replacing the `.yaml` extension from the output file with a `.ini` extension.
|
||||
|
||||
If (and only if) `generate-zbm` is run without a `--config` option (*i.e.*, it attempts to load the default `/etc/zfsbootmenu/config.yaml`) and the default configuration does *not* exist. Under these circumstances, `generate-zbm` will behave as if it were passed the `--migrate /etc/zfsbootmenu/config.ini` option.
|
||||
If (and only if) `generate-zbm` is run without a `--config` option (*i.e.*, it attempts to load the default `/etc/zfsbootmenu/config.yaml`) and the default configuration does *not* exist, `generate-zbm` will behave as if it had been passed the `--migrate /etc/zfsbootmenu/config.ini` option.
|
||||
|
||||
Whenever `generate-zbm` attempts to migrate configuraton files, it will exit immediately with a zero exit code on successful conversion and a nonzero exit code if problems were encountered during the conversion. No boot images will be produced in the same invocation as a migration attempt.
|
||||
Whenever `generate-zbm` attempts to migrate configuraton files, it will exit with a zero exit code on successful conversion and a nonzero exit code if problems were encountered during the conversion. No boot images will be produced in the same invocation as a migration attempt.
|
||||
|
||||
# Native encryption
|
||||
|
||||
ZFSBootMenu can import pools or filesystems with native encryption enabled. If your boot environments are not encrypted but say /home is, you will not receive a decryption prompt. To ensure that you can decrypt your pool to load the kernel and initramfs, you'll need to you have the filesystem parameters configured correctly.
|
||||
ZFSBootMenu can import pools or filesystems with native encryption enabled. If your boot environments are not encrypted but, for example, `/home` is, you will not receive a decryption prompt during boot. To ensure that you can decrypt your pool to load the kernel and initramfs, you'll need to you have the filesystem parameters configured correctly.
|
||||
|
||||
```
|
||||
zfs get all zroot | egrep '(encryption|keylocation|keyformat)'
|
||||
|
@ -201,12 +201,13 @@ zroot keylocation file:///etc/zfs/zroot.key local
|
|||
zroot keyformat passphrase -
|
||||
zroot encryptionroot zroot -
|
||||
```
|
||||
It's critical that `keyformat` is set to `passphrase`, otherwise you'll be unable to enter the correct value in the boot loader. ZoL currently only supports one key, but it does have a behavior that we can exploit. If you configure the `keylocation` value to a file on disk, put your passphrase in that, and then put that file into the FINAL initramfs, you won't receive a second password prompt on boot. You'll then still receive a password prompt in the boot loader, since we can force a prompt for passphrase input.
|
||||
|
||||
For Dracut-based systems, this can be done by creating `/etc/dracut.conf.d/zol.conf` with the following contents:
|
||||
It's critical that `keyformat` is set to `passphrase`, otherwise you'll be unable to enter the correct value in the boot loader. ZFS on Linux currently supports only one key, but in a way which we can exploit: if you configure the `keylocation` value to a file on disk, put your passphrase in that, and then include that file into the FINAL initramfs (the OS-managed one), you won't receive a second password prompt on boot. You'll still receive a password prompt in the boot loader, since we can force a prompt for passphrase input.
|
||||
|
||||
For Dracut-based systems, this can be done by creating a `/etc/dracut.conf.d/zol.conf` file with the following contents:
|
||||
|
||||
```
|
||||
install_items+=" /etc/zfs/zroot.key "
|
||||
```
|
||||
|
||||
It's critical that you do not put this key file into the ZFSBootMenu initramfs, since that file exists on an unencrypted volume - leaving your pool essentially wide-open.
|
||||
It's critical that you do not include this key file into the ZFSBootMenu initramfs, since that file exists on an unencrypted volume - leaving your pool essentially wide-open.
|
||||
|
|
Loading…
Reference in New Issue