<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AlirezaGharib</title>
    <description>The latest articles on DEV Community by AlirezaGharib (@gharib).</description>
    <link>https://dev.to/gharib</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F620471%2F869e4e11-c24e-4ba9-bde2-fbbac4bf72fe.jpeg</url>
      <title>DEV Community: AlirezaGharib</title>
      <link>https://dev.to/gharib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gharib"/>
    <language>en</language>
    <item>
      <title>Debian 13 ZFS on ROOT Installer</title>
      <dc:creator>AlirezaGharib</dc:creator>
      <pubDate>Wed, 07 Oct 2026 17:45:53 +0000</pubDate>
      <link>https://dev.to/gharib/debian-13-zfs-on-root-installer-200p</link>
      <guid>https://dev.to/gharib/debian-13-zfs-on-root-installer-200p</guid>
      <description>&lt;p&gt;Two installers for &lt;strong&gt;Debian 13 (Trixie) with root on encrypted ZFS&lt;/strong&gt;, each with a different upstream guide:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;Bootloader&lt;/th&gt;
&lt;th&gt;&lt;code&gt;/boot&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Upstream guide&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;debian13-zbm-install.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rEFInd → &lt;strong&gt;ZFSBootMenu&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;on the ZFS root dataset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.zfsbootmenu.org/en/v3.1.x/guides/debian/uefi.html" rel="noopener noreferrer"&gt;ZFSBootMenu — Debian (UEFI)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;debian13-zbm-install-testing.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rEFInd → &lt;strong&gt;ZFSBootMenu&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;on the ZFS root dataset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.zfsbootmenu.org/en/v3.1.x/guides/debian/uefi.html" rel="noopener noreferrer"&gt;ZFSBootMenu — Debian (UEFI)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;debian13-root-on-zfs-grub.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;GRUB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;separate &lt;strong&gt;ext4&lt;/strong&gt; partition&lt;/td&gt;
&lt;td&gt;&lt;a href="https://openzfs.github.io/openzfs-docs/Getting%20Started/Debian/Debian%20Trixie%20Root%20on%20ZFS.html" rel="noopener noreferrer"&gt;OpenZFS — Debian Trixie Root on ZFS&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;strong&gt;ZFS native encryption&lt;/strong&gt; (&lt;code&gt;aes-256-gcm&lt;/code&gt;, passphrase) — mandatory, not optional&lt;/li&gt;
&lt;li&gt;require the disk to be given as a stable &lt;code&gt;/dev/disk/by-id/…&lt;/code&gt; path&lt;/li&gt;
&lt;li&gt;build the &lt;strong&gt;same dataset hierarchy&lt;/strong&gt; with separate datasets for &lt;code&gt;/home&lt;/code&gt;, &lt;code&gt;/root&lt;/code&gt;, &lt;code&gt;/opt&lt;/code&gt;, &lt;code&gt;/srv&lt;/code&gt;, &lt;code&gt;/var/log&lt;/code&gt;, &lt;code&gt;/var/spool&lt;/code&gt;, &lt;code&gt;/var/tmp&lt;/code&gt; and the container/VM stores&lt;/li&gt;
&lt;li&gt;create a &lt;code&gt;default&lt;/code&gt; and a &lt;code&gt;baseline&lt;/code&gt; boot environment&lt;/li&gt;
&lt;li&gt;install a &lt;strong&gt;1 GiB encrypted swap partition&lt;/strong&gt; with a fresh random key each boot&lt;/li&gt;
&lt;li&gt;install KDE, GNOME, or nothing, selected by an environment variable&lt;/li&gt;
&lt;li&gt;install CPU microcode and a broad firmware set (including &lt;code&gt;firmware-iwlwifi&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;leave boot messages &lt;strong&gt;visible&lt;/strong&gt; — &lt;code&gt;quiet&lt;/code&gt; is not set anywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every step is tagged in the source with &lt;code&gt;[GUIDE]&lt;/code&gt; (straight from the upstream document) or &lt;code&gt;[DEVIATION]&lt;/code&gt; (with the reason inline), so you can audit either script against its guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;Quick start&lt;/li&gt;
&lt;li&gt;Disk layouts&lt;/li&gt;
&lt;li&gt;Dataset hierarchy&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;What happens at boot&lt;/li&gt;
&lt;li&gt;After installation&lt;/li&gt;
&lt;li&gt;Upgrading OpenZFS and the pool&lt;/li&gt;
&lt;li&gt;Recovery&lt;/li&gt;
&lt;li&gt;Deviations from the upstream guides&lt;/li&gt;
&lt;li&gt;Safety notes&lt;/li&gt;
&lt;li&gt;Credits&lt;/li&gt;
&lt;li&gt;License&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;debian13-zbm-install.sh&lt;/code&gt; — ZFSBootMenu
&lt;/h3&gt;

&lt;p&gt;ZFSBootMenu is a small Linux+initramfs bundled into a single EFI executable. It imports your pool, asks for the passphrase, lists every boot environment and snapshot it can find, and &lt;code&gt;kexec&lt;/code&gt;s into the one you choose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose it if&lt;/strong&gt; you want boot environments to be a first-class, interactive feature: rolling back a bad upgrade is a menu selection at boot, not a rescue USB. You also get a snapshot browser, a diff viewer, a recovery shell, and pool health reporting before the OS ever starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt; ZFSBootMenu contains its own copy of the ZFS userland and module. If you &lt;code&gt;zpool upgrade&lt;/code&gt; to feature flags your ZBM image doesn't understand, it cannot import the pool and the machine won't boot. This is manageable — see Upgrading OpenZFS and the pool — but it is a real constraint you have to remember forever.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;debian13-root-on-zfs-grub.sh&lt;/code&gt; — GRUB
&lt;/h3&gt;

&lt;p&gt;GRUB reads the kernel and initramfs from a plain ext4 &lt;code&gt;/boot&lt;/code&gt;. It never touches ZFS at all; the kernel's initramfs imports the pool and prompts for the passphrase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose it if&lt;/strong&gt; you want the boring, maximally robust option. Because GRUB never reads the root pool, &lt;code&gt;zpool upgrade rpool&lt;/code&gt; is &lt;strong&gt;always safe&lt;/strong&gt;, forever. Any Debian live ISO can rescue the system with no special tooling. This is also the closest thing to a "normal" Debian install that still has root on ZFS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt; boot environments are not interactive. The script generates a GRUB entry for &lt;code&gt;baseline&lt;/code&gt;, but switching to an arbitrary snapshot means editing the kernel command line at the GRUB prompt or booting a live ISO.&lt;/p&gt;




&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;64-bit UEFI&lt;/strong&gt; system (the GRUB script can also do legacy BIOS via &lt;code&gt;BOOT_MODE=bios&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;whole disk&lt;/strong&gt; to erase — these scripts are not for dual-booting&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Debian 13 Live ISO&lt;/strong&gt;, booted in the matching firmware mode

&lt;ul&gt;
&lt;li&gt;The OpenZFS guide recommends a GUI image (e.g. GNOME) for the GRUB script&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Working internet in the live environment&lt;/li&gt;
&lt;li&gt;≥ 4 GiB RAM recommended (ZFS is slow below 2 GiB)&lt;/li&gt;
&lt;li&gt;Patience: &lt;code&gt;zfs-dkms&lt;/code&gt; compiles in the live environment on the ZFSBootMenu path, which takes several minutes before anything visible happens&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In the live environment&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git
git clone https://github.com/YOURNAME/debian-zfs-installers.git
&lt;span class="nb"&gt;cd &lt;/span&gt;debian-zfs-installers
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x &lt;span class="k"&gt;*&lt;/span&gt;.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Find your disk.&lt;/strong&gt; Run either script with no &lt;code&gt;DISK&lt;/code&gt; set and it lists the candidates and exits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./debian13-zbm-install.sh
&lt;span class="c"&gt;# Whole disks under /dev/disk/by-id/:&lt;/span&gt;
&lt;span class="c"&gt;#   /dev/disk/by-id/nvme-Samsung_SSD_990_PRO_1TB_S1A2B3C4    931.5G Samsung SSD 990 PRO&lt;/span&gt;
&lt;span class="c"&gt;#   /dev/disk/by-id/ata-CT1000MX500SSD1_2015E2A0B1C2          931.5G CT1000MX500SSD1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ZFSBootMenu install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DISK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_1TB_S1A2B3C4 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;TARGET_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;workstation &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;ADMIN_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alireza &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;TIMEZONE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Europe/Berlin &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;DESKTOP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kde &lt;span class="se"&gt;\&lt;/span&gt;
./debian13-zbm-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GRUB install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;DISK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_1TB_S1A2B3C4 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;TARGET_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;workstation &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;ADMIN_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alireza &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;TIMEZONE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Europe/Berlin &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;DESKTOP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kde &lt;span class="se"&gt;\&lt;/span&gt;
./debian13-root-on-zfs-grub.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both scripts print a full configuration summary, then require you to type &lt;code&gt;ERASE&lt;/code&gt; before touching the disk. Passwords are prompted interactively (root, admin user, ZFS passphrase) unless supplied as variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not sure about the keyboard layout?
&lt;/h3&gt;

&lt;p&gt;Both scripts inherit the layout you picked at the ISO boot menu. To see the variants available for your layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LIST_KEYBOARD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; ./debian13-zbm-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An empty &lt;code&gt;KEYBOARD_VARIANT&lt;/code&gt; is normal and correct for most people — it means the standard layout for that country code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Disk layouts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;debian13-zbm-install.sh&lt;/code&gt; (ZFSBootMenu)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1024 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ef00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESP → &lt;code&gt;/boot/efi&lt;/code&gt;, holds rEFInd + ZFSBootMenu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1024 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8309&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;encrypted swap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;rest − 10 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bf00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;zroot&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The kernel and initramfs live on the ZFS root dataset, so they are snapshotted and rolled back along with everything else. That is the whole point of the design.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;debian13-root-on-zfs-grub.sh&lt;/code&gt; (GRUB)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;EF02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BIOS boot (tiny; keeps the legacy path open)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;600 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;EF00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESP → &lt;code&gt;/boot/efi&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2048 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8300&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/boot&lt;/code&gt; — &lt;strong&gt;ext4&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1024 MiB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;encrypted swap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;rest&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BF00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rpool&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Dataset hierarchy
&lt;/h2&gt;

&lt;p&gt;Identical in both scripts (pool named &lt;code&gt;zroot&lt;/code&gt; for ZFSBootMenu, &lt;code&gt;rpool&lt;/code&gt; for GRUB, matching each guide's convention):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POOL/ROOT                       mountpoint=none   canmount=off
├── default                     mountpoint=/      canmount=noauto   ← active
└── baseline                    mountpoint=/      canmount=noauto   ← factory image
POOL/data                       mountpoint=none   canmount=off
├── home                        /home
│   ├── root                    /root
│   └── &amp;lt;username&amp;gt;              /home/&amp;lt;username&amp;gt;
├── opt                         /opt
├── srv                         /srv
└── var                         (container, canmount=off)
    ├── lib                     (container, canmount=off)
    │   ├── containers          /var/lib/containers      Podman
    │   ├── docker              /var/lib/docker          Docker
    │   ├── libvirt             /var/lib/libvirt         VMs
    │   └── lxc                 /var/lib/lxc             LXC
    ├── log                     /var/log
    ├── spool                   /var/spool
    └── tmp                     /var/tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ROOT&lt;/code&gt;/&lt;code&gt;data&lt;/code&gt; split is what makes boot environments useful: rolling back &lt;code&gt;ROOT/default&lt;/code&gt; reverts the OS without touching home directories, logs, or VM images.&lt;/p&gt;

&lt;p&gt;The container and VM datasets exist but &lt;strong&gt;no daemons are installed&lt;/strong&gt;. Install &lt;code&gt;docker.io&lt;/code&gt;, &lt;code&gt;podman&lt;/code&gt;, &lt;code&gt;libvirt-daemon-system&lt;/code&gt; or &lt;code&gt;lxc&lt;/code&gt; when you need them and they land on their own datasets automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional tuning
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;DATASET_TUNING=yes&lt;/code&gt; (the default), the scripts apply a light, conservative set of properties: &lt;code&gt;atime=off&lt;/code&gt; across &lt;code&gt;data/var&lt;/code&gt;, &lt;code&gt;setuid=off devices=off&lt;/code&gt; on &lt;code&gt;/var/tmp&lt;/code&gt;, &lt;code&gt;compression=zstd recordsize=64K&lt;/code&gt; on &lt;code&gt;/var/log&lt;/code&gt;, &lt;code&gt;recordsize=64K&lt;/code&gt; on libvirt, &lt;code&gt;32K&lt;/code&gt; on the container stores, and &lt;code&gt;com.sun:auto-snapshot=false&lt;/code&gt; on the container/VM datasets. Set &lt;code&gt;DATASET_TUNING=no&lt;/code&gt; to inherit pool defaults everywhere and tune it yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Environment variables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common to both scripts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DISK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Required.&lt;/strong&gt; Must be a &lt;code&gt;/dev/disk/by-id/…&lt;/code&gt; whole-disk path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TARGET_HOSTNAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;debian-zbm&lt;/code&gt; / &lt;code&gt;debian&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADMIN_USER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gets its own dataset and &lt;code&gt;sudo&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADMIN_FULLNAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;System Administrator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GECOS field&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADMIN_GROUPS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;see script&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sudo&lt;/code&gt; is always added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIMEZONE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Etc/UTC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any zoneinfo name; validated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LOCALE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;en_US.UTF-8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Must be UTF-8; &lt;code&gt;en_US.UTF-8&lt;/code&gt; generated regardless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;KEYMAP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;inherited from live ISO&lt;/td&gt;
&lt;td&gt;Validated against the XKB rules list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;KEYBOARD_VARIANT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;inherited from live ISO&lt;/td&gt;
&lt;td&gt;Empty = standard layout. Pass &lt;code&gt;KEYBOARD_VARIANT=&lt;/code&gt; to force none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DESKTOP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kde&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;kde&lt;/code&gt;, &lt;code&gt;gnome&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DESKTOP_SIZE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minimal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;minimal&lt;/code&gt; or &lt;code&gt;full&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SWAP_SIZE_MIB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1024&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; disables swap entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SWAP_RANDOM_SOURCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/dev/urandom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;See note on swap
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POOL_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;zroot&lt;/code&gt; / &lt;code&gt;rpool&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BE_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;default&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Active boot environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BASELINE_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;baseline&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BASELINE_MODE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clone&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clone&lt;/code&gt;, &lt;code&gt;send&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ASHIFT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COMPRESSION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lz4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATASET_TUNING&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;SUITE&lt;/code&gt; / &lt;code&gt;MIRROR&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;trixie&lt;/code&gt; / deb.debian.org&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COMPONENTS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;main contrib non-free-firmware&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENABLE_BACKPORTS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adds the repo unpinned; installs nothing from it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INSTALL_FIRMWARE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Microcode + probed firmware set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EXTRA_PACKAGES&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Space-separated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ROOT_PASSWORD&lt;/code&gt; / &lt;code&gt;ADMIN_PASSWORD&lt;/code&gt; / &lt;code&gt;ZFS_PASSPHRASE&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;prompted&lt;/td&gt;
&lt;td&gt;Passing these on the command line leaks them to &lt;code&gt;ps&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FORCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;no&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;yes&lt;/code&gt; skips &lt;strong&gt;only&lt;/strong&gt; the &lt;code&gt;ERASE&lt;/code&gt; confirmation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LIST_KEYBOARD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;List variants and exit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  ZFSBootMenu script only
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ESP_SIZE_MIB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1024&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SWAP_MODE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;random&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;random&lt;/code&gt;, &lt;code&gt;luks&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZBM_INSTALL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;prebuilt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;prebuilt&lt;/code&gt; (download the EFI) or &lt;code&gt;source&lt;/code&gt; (build with &lt;code&gt;generate-zbm&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZBM_CMDLINE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loglevel=6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ZFSBootMenu's &lt;strong&gt;own&lt;/strong&gt; kernel command line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;KERNEL_CMDLINE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loglevel=6 systemd.show_status=yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What ZBM passes to Debian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZBM_TIMEOUT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Countdown before booting &lt;code&gt;bootfs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ZBM_FALLBACK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Also install to &lt;code&gt;EFI/BOOT/BOOTX64.EFI&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENCRYPTION_ALGO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aes-256-gcm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POOL_COMPAT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(empty)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Set to &lt;code&gt;openzfs-2.3-linux&lt;/code&gt; to pin feature flags&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ZBM_CMDLINE&lt;/code&gt; and &lt;code&gt;KERNEL_CMDLINE&lt;/code&gt; are not the same thing.&lt;/strong&gt; The first configures ZFSBootMenu's own kernel (what you see while it imports the pool and asks for the passphrase). The second is stored in &lt;code&gt;org.zfsbootmenu:commandline&lt;/code&gt; and configures Debian. Conflating them is the most common mistake with this setup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  GRUB script only
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BOOT_MODE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uefi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;uefi&lt;/code&gt; or &lt;code&gt;bios&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ESP_SIZE_MIB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;600&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BOOT_SIZE_MIB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2048&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ext4 &lt;code&gt;/boot&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GRUB_VERBOSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removes &lt;code&gt;quiet&lt;/code&gt;, sets &lt;code&gt;GRUB_TERMINAL=console&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GRUB_CMDLINE_DEFAULT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loglevel=6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GRUB_TIMEOUT_SECS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REMOVE_OS_PROBER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Avoids &lt;code&gt;update-grub&lt;/code&gt; noise on single-boot systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DISABLE_LOG_COMPRESSION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/var/log&lt;/code&gt; is already a compressed dataset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DNODESIZE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NORMALIZATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;formD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Cannot be changed after pool creation.&lt;/strong&gt; Implies &lt;code&gt;utf8only=on&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INSTALL_SSH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;no&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BLKDISCARD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;no&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full-disk TRIM before partitioning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What happens at boot
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ZFSBootMenu
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firmware → rEFInd → ZFSBootMenu → zroot/ROOT/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rEFInd offers four ways in, all using the same EFI image:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entry&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Boot default&lt;/td&gt;
&lt;td&gt;10s countdown, then boots &lt;code&gt;bootfs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boot to menu&lt;/td&gt;
&lt;td&gt;always show the boot-environment selector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boot immediately&lt;/td&gt;
&lt;td&gt;no menu, no countdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verbose debug&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;loglevel=7&lt;/code&gt;, ZBM's full internal tracing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Inside ZFSBootMenu: &lt;code&gt;Ctrl-H&lt;/code&gt; for help, &lt;code&gt;Ctrl-S&lt;/code&gt; to browse snapshots of the selected environment, &lt;code&gt;Ctrl-R&lt;/code&gt; for a recovery shell.&lt;/p&gt;

&lt;p&gt;Change Debian's boot verbosity later without touching the bootloader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs &lt;span class="nb"&gt;set &lt;/span&gt;org.zfsbootmenu:commandline&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"loglevel=7 systemd.show_status=yes"&lt;/span&gt; zroot/ROOT
&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs &lt;span class="nb"&gt;set &lt;/span&gt;org.zfsbootmenu:commandline&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"quiet loglevel=3"&lt;/span&gt; zroot/ROOT   &lt;span class="c"&gt;# back to silent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The property is inherited by every environment under &lt;code&gt;ROOT&lt;/code&gt;. &lt;code&gt;%{parent}&lt;/code&gt; expands to the parent's value, so you can make just one environment verbose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs &lt;span class="nb"&gt;set &lt;/span&gt;org.zfsbootmenu:commandline&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"loglevel=7 %{parent}"&lt;/span&gt; zroot/ROOT/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ZFSBootMenu's own verbosity and countdown live in &lt;code&gt;/boot/efi/EFI/ZBM/refind_linux.conf&lt;/code&gt; — plain text, no regeneration needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  GRUB
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firmware → GRUB (reads ext4 /boot) → kernel + initramfs → unlock rpool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initramfs prompts for the passphrase. The GRUB menu has an entry for &lt;code&gt;rpool/ROOT/default&lt;/code&gt; and one for &lt;code&gt;rpool/ROOT/baseline&lt;/code&gt;, generated by &lt;code&gt;/etc/grub.d/11_baseline_be&lt;/code&gt; (which re-runs on every &lt;code&gt;update-grub&lt;/code&gt;, so it tracks kernel updates).&lt;/p&gt;

&lt;p&gt;The OpenZFS guide suggests reverting the verbose settings once you've rebooted twice and are confident everything works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/default/grub     &lt;span class="c"&gt;# add 'quiet', comment out GRUB_TERMINAL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-grub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  After installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating a new boot environment
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;canmount&lt;/code&gt; is &lt;strong&gt;not inheritable&lt;/strong&gt;, and two filesystems trying to mount at &lt;code&gt;/&lt;/code&gt; will prevent the system from booting. Set it explicitly on every environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs snapshot POOL/ROOT/default@pre-upgrade
&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs clone &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;canmount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noauto &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;mountpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
    POOL/ROOT/default@pre-upgrade POOL/ROOT/new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On ZFSBootMenu you can do this from the boot menu instead. On GRUB, copy &lt;code&gt;/etc/grub.d/11_baseline_be&lt;/code&gt; as a template, or edit the kernel line at the GRUB prompt and change &lt;code&gt;root=ZFS=…&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a user
&lt;/h3&gt;

&lt;p&gt;A per-user dataset makes the home directory exist — and &lt;strong&gt;&lt;code&gt;useradd&lt;/code&gt; will not copy &lt;code&gt;/etc/skel&lt;/code&gt; into a directory that already exists.&lt;/strong&gt; It prints &lt;code&gt;Not copying any file from skel directory into it&lt;/code&gt; and carries on, leaving the account with no &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.profile&lt;/code&gt;. Do it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs create &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;mountpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/NAME POOL/data/home/NAME
&lt;span class="nb"&gt;sudo &lt;/span&gt;useradd &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /home/NAME &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash NAME
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/skel/. /home/NAME/
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; NAME:NAME /home/NAME &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo chmod &lt;/span&gt;0750 /home/NAME
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;NAME
&lt;span class="nb"&gt;sudo &lt;/span&gt;passwd NAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating ZFSBootMenu
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fSL&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /boot/efi/EFI/ZBM/VMLINUZ.EFI https://get.zfsbootmenu.org/efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave &lt;code&gt;VMLINUZ-BACKUP.EFI&lt;/code&gt; alone as your known-good image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup
&lt;/h3&gt;

&lt;p&gt;Both scripts leave an &lt;code&gt;@install&lt;/code&gt; or &lt;code&gt;@baseline&lt;/code&gt; snapshot. Once you're happy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs list &lt;span class="nt"&gt;-t&lt;/span&gt; snapshot
&lt;span class="nb"&gt;sudo &lt;/span&gt;zfs destroy POOL/ROOT/default@install
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; root          &lt;span class="c"&gt;# disable the root password (optional)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;BASELINE_MODE=clone&lt;/code&gt;, the &lt;code&gt;@baseline&lt;/code&gt; snapshot &lt;strong&gt;cannot&lt;/strong&gt; be destroyed while the clone exists. That is deliberate — it's the guarantee a factory image should have.&lt;/p&gt;




&lt;h2&gt;
  
  
  Upgrading OpenZFS and the pool
&lt;/h2&gt;

&lt;p&gt;Both scripts add &lt;code&gt;trixie-backports&lt;/code&gt; (unpinned, so nothing is pulled from it automatically).&lt;/p&gt;

&lt;h3&gt;
  
  
  On the GRUB script
&lt;/h3&gt;

&lt;p&gt;Nothing to think about. GRUB never reads the root pool, so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; trixie-backports zfs-dkms zfsutils-linux zfs-initramfs
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-initramfs &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; all
&lt;span class="c"&gt;# reboot, verify `zfs version`, then:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;zpool upgrade rpool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  On the ZFSBootMenu script — order matters
&lt;/h3&gt;

&lt;p&gt;ZFSBootMenu ships its own ZFS. &lt;strong&gt;&lt;code&gt;zpool upgrade&lt;/code&gt; is irreversible, and a ZBM image that predates a newly enabled feature flag cannot import the pool.&lt;/strong&gt; Follow this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the newer ZFS in the OS:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; trixie-backports zfs-dkms zfsutils-linux zfs-initramfs
   &lt;span class="nb"&gt;sudo &lt;/span&gt;update-initramfs &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot; confirm both userland and kmod report the new version with &lt;code&gt;zfs version&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refresh ZFSBootMenu first.&lt;/strong&gt; Check which ZFS version a release embeds at&lt;br&gt;
&lt;a href="https://github.com/zbm-dev/zfsbootmenu/releases" rel="noopener noreferrer"&gt;zbm-dev/zfsbootmenu/releases&lt;/a&gt;, then download it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reboot through the new ZBM image&lt;/strong&gt; and confirm it still imports the pool and boots. &lt;em&gt;Only then:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;zpool upgrade zroot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that once the pool is upgraded, &lt;code&gt;VMLINUZ-BACKUP.EFI&lt;/code&gt; stops being a usable fallback unless it too has been refreshed.&lt;/p&gt;

&lt;p&gt;The scripts create the pool with &lt;strong&gt;no &lt;code&gt;compatibility=&lt;/code&gt; pin&lt;/strong&gt;, so it has every feature flag the installing ZFS supports. Set &lt;code&gt;POOL_COMPAT=openzfs-2.3-linux&lt;/code&gt; at install time if you'd rather have the guide's conservative default.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recovery
&lt;/h2&gt;

&lt;p&gt;From any Debian live ISO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; zfsutils-linux
zpool import &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; /mnt POOL
zfs load-key &lt;span class="nt"&gt;-a&lt;/span&gt;                        &lt;span class="c"&gt;# or: zfs load-key POOL&lt;/span&gt;
zfs mount POOL/ROOT/default
zfs mount &lt;span class="nt"&gt;-a&lt;/span&gt;
mount /dev/disk/by-id/…-partN /mnt/boot   &lt;span class="c"&gt;# GRUB script only (ext4 /boot)&lt;/span&gt;

mount &lt;span class="nt"&gt;--make-private&lt;/span&gt; &lt;span class="nt"&gt;--rbind&lt;/span&gt; /dev  /mnt/dev
mount &lt;span class="nt"&gt;--make-private&lt;/span&gt; &lt;span class="nt"&gt;--rbind&lt;/span&gt; /proc /mnt/proc
mount &lt;span class="nt"&gt;--make-private&lt;/span&gt; &lt;span class="nt"&gt;--rbind&lt;/span&gt; /sys  /mnt/sys
mount &lt;span class="nt"&gt;-t&lt;/span&gt; tmpfs tmpfs /mnt/run &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; /mnt/run/lock
&lt;span class="nb"&gt;chroot&lt;/span&gt; /mnt /bin/bash &lt;span class="nt"&gt;--login&lt;/span&gt;
mount /boot/efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exit
&lt;/span&gt;mount | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; zfs | &lt;span class="nb"&gt;tac&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/\/mnt/ {print $3}'&lt;/span&gt; | xargs &lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt; umount &lt;span class="nt"&gt;-lf&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
zpool &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If either script recorded problems during installation, they are kept at &lt;code&gt;/root/INSTALL-WARNINGS.txt&lt;/code&gt; on the installed system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deviations from the upstream guides
&lt;/h2&gt;

&lt;p&gt;Both scripts are annotated inline, but the ones worth knowing up front:&lt;/p&gt;

&lt;h3&gt;
  
  
  ZFSBootMenu script
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1024 MiB ESP&lt;/strong&gt; instead of 512, leaving room for several ZBM images and rEFInd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The pool key file is created.&lt;/strong&gt; The guide's encrypted &lt;code&gt;zpool create&lt;/code&gt; references &lt;code&gt;/etc/zfs/zroot.key&lt;/code&gt; as a file "created in a previous step" — but the Debian page never shows that step. The script creates it before &lt;code&gt;zpool create&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted export/import is spelled out.&lt;/strong&gt; The guide's encrypted tab omits it; the script does &lt;code&gt;zpool export&lt;/code&gt; → &lt;code&gt;zpool import -N -R /mnt&lt;/code&gt; → &lt;code&gt;zfs load-key&lt;/code&gt; → mount, which is what the other guides in the same series actually do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The vdev is referenced by PARTUUID&lt;/strong&gt;, so the pool doesn't care about device enumeration order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;EFI/BOOT/BOOTX64.EFI&lt;/code&gt; fallback&lt;/strong&gt;, for firmware that silently drops NVRAM boot entries. The guide flags this problem and links to its Portable ZFSBootMenu page but doesn't automate it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verbose command lines&lt;/strong&gt;, microcode, expanded firmware, and &lt;code&gt;zfs-zed&lt;/code&gt; — none of which the guide covers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GRUB script
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ext4 &lt;code&gt;/boot&lt;/code&gt; instead of &lt;code&gt;bpool&lt;/code&gt;.&lt;/strong&gt; This is the big one. The guide creates a second ZFS pool for &lt;code&gt;/boot&lt;/code&gt; pinned to &lt;code&gt;-o compatibility=grub2&lt;/code&gt;, because GRUB understands only a subset of pool features. Replacing it with ext4 removes that entire mechanism: no &lt;code&gt;bpool&lt;/code&gt;, no feature-flag pin, no &lt;code&gt;zfs-import-bpool.service&lt;/code&gt; (guide step 4.13), no &lt;code&gt;bpool&lt;/code&gt; entry in &lt;code&gt;zfs-list.cache&lt;/code&gt;. The consequence is that &lt;code&gt;zpool upgrade rpool&lt;/code&gt; is permanently safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-interactive native encryption.&lt;/strong&gt; The guide's &lt;code&gt;-O keylocation=prompt&lt;/code&gt; makes &lt;code&gt;zpool create&lt;/code&gt; prompt interactively. The script creates the pool against a temporary key in &lt;code&gt;/dev/shm&lt;/code&gt;, then runs &lt;code&gt;zfs set keylocation=prompt&lt;/code&gt; and shreds the file — ending in exactly the state the guide describes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu-isms corrected.&lt;/strong&gt; Guide steps 1.6 and 4.7 name &lt;code&gt;linux-headers-generic&lt;/code&gt; and &lt;code&gt;linux-image-generic&lt;/code&gt;, which are Ubuntu metapackages that don't exist in Debian. The script probes the archive and falls back to the &lt;code&gt;-amd64&lt;/code&gt; variants.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap on a partition, not a zvol.&lt;/strong&gt; The guide's step 7 uses a zvol and warns that under extreme memory pressure this can lock the system up. &lt;code&gt;RESUME=none&lt;/code&gt; is set either way, per the guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tasksel --new-install&lt;/code&gt; replaced&lt;/strong&gt; by the &lt;code&gt;DESKTOP&lt;/code&gt; variable, since tasksel is interactive.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Safety notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;These scripts erase an entire disk.&lt;/strong&gt; They are not for dual-booting. Back up first.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FORCE=yes&lt;/code&gt; skips &lt;strong&gt;only&lt;/strong&gt; the &lt;code&gt;ERASE&lt;/code&gt; confirmation. It does not skip password prompts, and all preflight validation still runs.&lt;/li&gt;
&lt;li&gt;Test in a VM before running on hardware you care about. For QEMU/KVM, set a unique serial on each virtual disk so &lt;code&gt;/dev/disk/by-id&lt;/code&gt; aliases appear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your passphrase is likely the weakest link.&lt;/strong&gt; On the ZFSBootMenu path it is typed inside ZBM, which uses a basic keymap — prefer unshifted ASCII you can type blind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A note on random-key swap
&lt;/h3&gt;

&lt;p&gt;The swap partition uses &lt;strong&gt;plain dm-crypt with a fresh key drawn from &lt;code&gt;/dev/urandom&lt;/code&gt; on every boot&lt;/strong&gt;, via crypttab's &lt;code&gt;swap&lt;/code&gt; option. Nothing on it survives a reboot.&lt;/p&gt;

&lt;p&gt;This is &lt;em&gt;not&lt;/em&gt; LUKS, and cannot be: LUKS requires a persistent header with keyslots, which is incompatible with a per-boot random key. The consequence is that &lt;strong&gt;hibernation is impossible&lt;/strong&gt;, which is why &lt;code&gt;RESUME=none&lt;/code&gt; is configured.&lt;/p&gt;

&lt;p&gt;If you need hibernation, the ZFSBootMenu script offers &lt;code&gt;SWAP_MODE=luks&lt;/code&gt; — a persistent LUKS2 volume unlocked from a keyfile on the encrypted root. Note that the scripts do not configure a resume device; that is left to you.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/dev/urandom&lt;/code&gt; is the default rather than &lt;code&gt;/dev/random&lt;/code&gt; because they are cryptographically identical on modern kernels and &lt;code&gt;/dev/urandom&lt;/code&gt; never blocks. Set &lt;code&gt;SWAP_RANDOM_SOURCE=/dev/random&lt;/code&gt; if you prefer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;These scripts are automation wrappers. All the hard thinking belongs to the upstream projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upstream projects
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://zfsbootmenu.org/" rel="noopener noreferrer"&gt;ZFSBootMenu&lt;/a&gt;&lt;/strong&gt; — the boot environment manager the first script installs.&lt;br&gt;
Documentation: &lt;a href="https://docs.zfsbootmenu.org/" rel="noopener noreferrer"&gt;https://docs.zfsbootmenu.org/&lt;/a&gt; · Source: &lt;a href="https://github.com/zbm-dev/zfsbootmenu" rel="noopener noreferrer"&gt;https://github.com/zbm-dev/zfsbootmenu&lt;/a&gt;&lt;br&gt;
Thanks to Zach Dykstra and the ZFSBootMenu team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://openzfs.org/" rel="noopener noreferrer"&gt;OpenZFS&lt;/a&gt;&lt;/strong&gt; — ZFS on Linux itself, and the &lt;em&gt;Root on ZFS&lt;/em&gt; documentation series the second script follows.&lt;br&gt;
Documentation: &lt;a href="https://openzfs.github.io/openzfs-docs/" rel="noopener noreferrer"&gt;https://openzfs.github.io/openzfs-docs/&lt;/a&gt; · Source: &lt;a href="https://github.com/openzfs/zfs" rel="noopener noreferrer"&gt;https://github.com/openzfs/zfs&lt;/a&gt;&lt;br&gt;
The Debian HOWTO is maintained by rlaager and contributors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prior art and inspiration
&lt;/h3&gt;

&lt;p&gt;Other projects solving the same problem, each worth reading before you write your own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Sithuk/ubuntu-server-zfsbootmenu" rel="noopener noreferrer"&gt;Sithuk/ubuntu-server-zfsbootmenu&lt;/a&gt;&lt;/strong&gt; — a mature, far more featureful Ubuntu installer: native ZFS or LUKS encryption, single/mirror/raidz topologies, integrated sanoid snapshot management with automatic pruning, an optional encrypted data pool on a second drive, and remote unlocking over SSH at boot so you can roll back a headless machine without physical access. If you're on Ubuntu rather than Debian, use this instead of these scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/okhsunrog/archinstall_zfs" rel="noopener noreferrer"&gt;okhsunrog/archinstall_zfs&lt;/a&gt;&lt;/strong&gt; — a ZFS-first Arch Linux installer with both a graphical (Slint/KMS) and terminal (ratatui) UI. Notably, it validates kernel/ZFS compatibility against OpenZFS release data before installing, and falls back from prebuilt modules to DKMS automatically — a class of problem these Debian scripts sidestep only because Debian's kernel is frozen within a release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/fnichol/cachyos-zfs-installer" rel="noopener noreferrer"&gt;fnichol/cachyos-zfs-installer&lt;/a&gt;&lt;/strong&gt; — configures CachyOS with an optionally encrypted ZFS root, ZFSBootMenu, and automatic boot environments by reconfiguring Calamares to use ZFS + ZFSBootMenu instead of ext4 + systemd-boot. Its pacman hooks are the interesting part: a pre-hook snapshots the current boot environment whenever kernel or ZFS packages are about to update, and a post-hook prunes old environments by retention policy and regenerates the ZBM images. That is a genuinely better answer to "snapshot before upgrade" than doing it by hand.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;MIT. The upstream guides, ZFSBootMenu, and OpenZFS carry their own licenses — ZFS is CDDL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;Issues and pull requests welcome. Please test changes in a VM and say which guide section your change relates to, so the &lt;code&gt;[GUIDE]&lt;/code&gt; / &lt;code&gt;[DEVIATION]&lt;/code&gt; annotations in the scripts stay accurate.&lt;/p&gt;

</description>
      <category>debian</category>
      <category>zfs</category>
      <category>zfsonroot</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
