ZFSBootMenu Documentation

repository·master·Indexed 20 days ago

https://github.com/zbm-dev/zfsbootmenu

A Linux bootloader that leverages ZFS features to manage multiple boot environments and snapshots. It operates as a minimal Linux environment that discovers kernels and initramfs on ZFS and boots them via kexec. The documentation covers the use of user-contributed customization scripts, building and serving documentation via Sphinx, and using the ZFSBootMenu builder container (via podman or docker) to generate UEFI bundles, kernels, and initramfs images.

Tokens
51.2K
Snippets
211
Records
267
Agent score
75%

What's inside ZFSBootMenu

  1. Overview of ZFSBootMenu

    master

    ZFSBootMenu is a Linux-based bootloader designed to provide a boot experience similar to FreeBSD's bootloader by leveraging ZFS features. It operates as a small, self-contained Linux system that identifies kernels and initramfs images within ZFS filesystems.

    Key capabilities include:

    • Managing multiple "boot environments" (e.g., different Linux distributions).
    • Manipulating ZFS snapshots before booting.
    • Bootstrapping system installations via zfs recv.
    • Launching selected kernels using the kexec command.
  2. Use zbm-kcl to manage kernel command lines

    master

    The zbm-kcl utility is used to review and manipulate the org.zfsbootmenu:commandline property on ZFS filesystems or the .cmdline section within ZFSBootMenu EFI executables.

    ZFSBootMenu uses this property to determine the kernel command line for the environment being booted. For EFI executables, the .cmdline section controls the behavior of ZFSBootMenu itself.

    Targeting Filesystems vs. EFI Executables:

    • If the argument matches an existing ZFS filesystem, zbm-kcl operates on that filesystem's org.zfsbootmenu:commandline property.
    • If no matching filesystem is found, the argument is treated as a path to an EFI executable.
    • To force zbm-kcl to treat an argument as a relative path to an EFI executable (even if a filesystem with the same name exists), prefix it with ./.
    • If no argument is provided, zbm-kcl attempts to operate on the current root filesystem.
    • Using - as an EFI executable argument tells zbm-kcl to read from stdin.
    # View the current command line of a filesystem
    zbm-kcl <FILESYSTEM> 
    
    # View the current command line of an EFI executable
    zbm-kcl /path/to/zfsbootmenu.EFI
  3. What is ZFSBootMenu and how does it work?

    master

    ZFSBootMenu is a bootloader designed for Linux systems running on ZFS. It acts as a small, self-contained Linux system that discovers, manipulates, and boots Linux kernels and initramfs images found within ZFS filesystems.

    Core Workflow

    1. Booting: It is launched via direct EFI booting, an EFI boot manager (like rEFInd), or a BIOS bootloader (like syslinux).
    2. Pool Discovery: It finds and imports healthy ZFS pools (or a specific pool if configured).
    3. Environment Selection:
      • It prefers the filesystem defined by the bootfs property of the preferred pool.
      • If no preference is set or the pool is missing, it uses the bootfs property of the first-found pool.
      • If no bootfs is found, it searches all imported pools for filesystems with mountpoint=/ containing Linux kernels and initramfs images in /boot, presenting them via fzf.
    4. Execution: Once an environment is selected, it mounts the filesystem, identifies the kernel, and uses kexec to load the kernel and initramfs into memory. It uses the org.zfsbootmenu:commandline ZFS property for kernel arguments.
    5. Handover: It unmounts ZFS filesystems and boots the final kernel.
  4. Configure HOOKS in mkinitcpio.conf

    master

    When using mkinitcpio, the generate-zbm command automatically ensures the zfsbootmenu hook is included in the HOOKS array of /etc/zfsbootmenu/mkinitcpio.conf.

    Important Hook Ordering Rules:

    1. Custom Hooks: If you need to add custom hooks to the ZFSBootMenu initramfs image, they must be placed before the zfsbootmenu hook in the HOOKS array.
    2. Redundancy: The default configuration includes the zfsbootmenu hook in the array. While this causes the hook to be added twice by generate-zbm, it is safe because the zfsbootmenu hook takes over execution and only runs once.
    3. Best Practice: To avoid configuration errors or duplicate hook issues, it is recommended to remove the zfsbootmenu hook from /etc/zfsbootmenu/mkinitcpio.conf when manually editing the HOOKS array.
  5. Configure kernel command-line arguments via ZFS properties

    master

    ZFSBootMenu identifies boot environments as filesystems containing an identifiable Linux kernel and initramfs. To pass specific kernel command-line arguments to a boot environment, set the org.zfsbootmenu:commandline ZFS property on the target filesystem.

    Key Rules:

    • Do not set root=: ZFSBootMenu automatically adds the appropriate root= argument and will suppress any conflicting root= options you provide in this property.
    • Inheritance: Properties are inherited by default. You can set org.zfsbootmenu:commandline on a common parent dataset to apply arguments to all child environments, then override them locally on specific children.
    • Substitution Keyword: Use %{parent} within the property value to recursively expand the value of the org.zfsbootmenu:commandline property from the parent dataset. This allows you to mix global defaults with environment-specific flags.

    To simplify these edits, use the zbm-kcl helper tool.

    # Set a global argument on the parent
    zfs set org.zfsbootmenu:commandline="zfs.zfs_arc_max=8589934592" zroot/ROOT
    
    # Inherit parent and add a local argument
    zfs set org.zfsbootmenu:commandline="%{parent} loglevel=4" zroot/ROOT/void.2019.11.01
    
    # Inherit parent and prepend a local argument
    zfs set org.zfsbootmenu:commandline="loglevel=7 %{parent}" zroot/ROOT/void.2019.10.04
  6. Prerequisites for Tailscale Integration

    master

    To enable Tailscale support in ZFSBootMenu for remote access behind firewalls or private networks, you must meet the following requirements:

    1. Initramfs Generator: You must use mkinitcpio to generate the ZFSBootMenu image.
    2. Tailscale Module: The recommended module is mkinitcpio-tailscale.
    3. Remote Access Setup: You must have remote access configured (either via Dropbear or Tailscale's built-in SSH server).
    4. Security Best Practice: Because the Tailscale node key is stored in the initramfs, use Tailscale ACLs to restrict the ZFSBootMenu node. It should not be able to initiate connections to other nodes in your Tailnet.

    Example ACL configuration to isolate the ZFSBootMenu node:

    {
      "tagOwners": {
        "tag:zfsbootmenu": ["autogroup:admin"],
        "tag:local":      ["autogroup:admin"]
      },
      "acls": [
        {"action": "accept", "src": ["tag:local"], "dst": ["*:*"]}
      ]
    }
  7. Customize the build container using Hooks

    master

    You can "terraform" the build container by placing executable hook files in your bind-mounted ${BUILDROOT}. The entrypoint executes these hooks at specific lifecycle stages.

    Hook Types

    1. Pre-setup Hooks (${BUILDROOT}/rc.pre.d/)

    Executed after installing requested packages (-p) but before the ZFSBootMenu source is fetched or populated at /zbm.

    • Use case: Overriding the standard process for fetching source archives or modifying environment variables like FONT in /etc/rc.conf.

    2. Post-setup Hooks (${BUILDROOT}/rc.d/)

    Executed after the ZFSBootMenu source is installed and symlinked, but before -e configuration modifications and the final generate-zbm execution.

    • Use case: Last-minute customization of ZFSBootMenu configuration or adding additional links (e.g., linking ${BUILDROOT}/initcpio to /etc/initcpio).
  8. Create a bundled UEFI executable with ZFSBootMenu

    master

    To avoid issues where UEFI firmware ignores command-line arguments (common on some Dell systems), you can create a bundled UEFI executable. This bundle encapsulates the Linux kernel, the ZFSBootMenu initramfs, and all required command-line arguments into a single .EFI file.

    Configuration

    Edit /etc/zfsbootmenu/config.yaml to control bundle creation:

    • EFI.Enabled: Set to true to enable bundling.
    • EFI.ImageDir: The destination directory on the ESP (e.g., /boot/efi/EFI/zbm).
    • EFI.Versions: Set to false or 0 to disable versioned filenames. This is recommended because firmware does not automatically update to point to new versions. When disabled, generate-zbm still creates a -backup.EFI of the previous version.
    • EFI.Stub: Path to the UEFI stub loader if the default systemd-boot location is not used.
    • Kernel.Prefix: The base name for the output file (e.g., vmlinuz.EFI). If omitted, it is derived from the kernel name.
    • Kernel.CommandLine: Arguments encoded into the bundle. If dracut's kernel_cmdline is also set, the two are concatenated.

    Booting the Bundle

    Use efibootmgr to register the .EFI file. Use backslashes for paths and remember that paths are case-insensitive on FAT volumes.

    It is highly recommended to create a backup entry pointing to the -backup.EFI file.

    # Register the primary bundle
    efibootmgr -c -d /dev/sda -p 1 -L "ZFSBootMenu" -l '\EFI\VOID\VMLINUZ.EFI'
    
    # Register the backup bundle
    efibootmgr -c -d /dev/sda -p 1 -L "ZFSBootMenu (Backup)" -l '\EFI\VOID\VMLINUZ-BACKUP.EFI'
  9. Release branch management and workflow

    master

    ZFSBootMenu uses long-lived release branches for minor versions (e.g., v3.1.x).

    Workflow Rules:

    • Target Branches: tag-release.sh only works on the master branch or an existing long-lived release branch. Running it on any other branch will fail.
    • Initial Minor Releases: The first release of a new minor version (e.g., 3.1.0) should be performed from the master branch. After tagging, a corresponding release branch (e.g., v3.1.x) should be created from that tag.
    • Patch Releases: Subsequent patch releases for a specific version should be made directly from its corresponding release branch.
    • Maintenance: Documentation updates on master should be backported to the latest release branch, along with trivial fixes required for patch releases.
  10. Understand ZFSBootMenu binary release types

    master

    ZFSBootMenu provides two types of pre-built images: release and recovery.

    • Release images: Recommended for normal system operation. They include all user-space tools necessary for full functionality and a minimal selection of additional pre-boot tools.
    • Recovery images: A superset of the tools in release images. These are designed for rebuilding unbootable systems from within the ZFSBootMenu emergency shell. They include network access components and utilities for manipulating disks and file systems. It is recommended to keep a recovery image installed alongside a standard release image and configure a backup boot option pointing to it.
  11. Use org.zfsbootmenu:keysource to automate key caching

    master

    ZFSBootMenu provides a convenience property org.zfsbootmenu:keysource to automate the searching and caching of ZFS key files. This prevents repeated passphrase prompts when performing operations like changing boot environments or cloning snapshots.

    How it works

    1. You set org.zfsbootmenu:keysource to the name of a filesystem containing your keys.
    2. When a filesystem specifies a file:// URI as its keylocation, ZFSBootMenu attempts to mount the keysource filesystem.
    3. It searches the keysource for the file named in the keylocation URI.
    4. If found, the key is cached in the in-memory root filesystem for subsequent operations.

    Implementation Example

    To set up a dedicated keystore filesystem (zroot/keystore) mounted at /etc/zfs/keys:

    # 1. Create the keystore dataset
    zfs create -o mountpoint=/etc/zfs/keys zroot/keystore
    
    # 2. Create the key file
    echo "MySecretPassphrase" > /etc/zfs/keys/zroot.key
    chmod 000 /etc/zfs/keys/zroot.key
    
    # 3. Configure the target filesystem to use this key
    zfs set keylocation=file:///etc/zfs/keys/zroot.key zroot
    
    # 4. Tell ZFSBootMenu where to find the keys
    zfs set org.zfsbootmenu:keysource=zroot/keystore zroot
    
    # 5. Include the key in your initramfs (dracut example)
    echo 'install_optional_items+= " /etc/zfs/keys/zroot.key " ' >> /etc/dracut.conf.d/zol.conf

    Path Mapping Logic

    ZFSBootMenu intelligently maps paths. If the keysource has a mountpoint of /etc/zfs/keys and the keylocation is file:///etc/zfs/keys/zroot.key, ZFSBootMenu will first try to find the file at the root of the keysource filesystem (zroot/keystore/zroot.key). If that fails, it falls back to the full path relative to the keysource (zroot/keystore/etc/zfs/keys/zroot.key).

    zfs create -o mountpoint=/etc/zfs/keys zroot/keystore
    echo "MySecretPassphrase" > /etc/zfs/keys/zroot.key
    chmod 000 /etc/zfs/keys/zroot.key
    zfs set keylocation=file:///etc/zfs/keys/zroot.key zroot
    zfs set org.zfsbootmenu:keysource=zroot/keystore zroot
    echo 'install_optional_items+= " /etc/zfs/keys/zroot.key " ' >> /etc/dracut.conf.d/zol.conf