Setting up root on ZFS in Debian Bullseye
Here is how I install debian 11 (bullseye) with root in ZFS, for reasons to use ZFS read ZFS in Debian Bullseye. I also wrote an article ZFS commands showing simple commands for creating zpools, datasets, snapshots...
The first section is about installing with UEFI boot and the second section is about installing with the legacy bios boot.
The first step is to copy Debian Bullseye live to a USB key and boot from the USB key.
My source for the commands on this page is OpenZFS Debian Buster - Root on ZFS.
2021-10-01 Update: I found the zfs-installer project which is also based on the OpenZFS instructions and provides a script for installing Bullseye on ZFS.
UEFI boot setup
sudo vi /etc/apt/sources.list
deb http://deb.debian.org/debian/ bullseye main contrib
sudo apt update
sudo -i
apt install --yes debootstrap gdisk dkms dpkg-dev \
linux-headers-$(uname -r)
apt install --yes --no-install-recommends zfs-dkms
modprobe zfs
apt install --yes zfsutils-linux
DISK=/dev/disk/by-id/xxx
# create partition
#uefi
sgdisk -n2:1M:+512M -t2:EF00 $DISK
#boot pool
sgdisk -n3:0:+1G -t3:BF01 $DISK
#root pool
sgdisk -n4:0:0 -t4:BF00 $DISK
# boot pool
zpool create \
-o cachefile=/etc/zfs/zpool.cache \
-o ashift=12 -d \
-o feature@async_destroy=enabled \
-o feature@bookmarks=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled \
-o feature@extensible_dataset=enabled \
-o feature@filesystem_limits=enabled \
-o feature@hole_birth=enabled \
-o feature@large_blocks=enabled \
-o feature@lz4_compress=enabled \
-o feature@spacemap_histogram=enabled \
-o feature@zpool_checkpoint=enabled \
-O acltype=posixacl -O canmount=off -O compression=lz4 \
-O devices=off -O normalization=formD -O relatime=on -O xattr=sa \
-O mountpoint=/boot -R /mnt \
bpool ${DISK}-part3
# root pool
zpool create \
-o ashift=12 \
-O acltype=posixacl -O canmount=off -O compression=lz4 \
-O dnodesize=auto -O normalization=formD -O relatime=on \
-O xattr=sa -O mountpoint=/ -R /mnt \
rpool ${DISK}-part4
zfs create -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o canmount=off -o mountpoint=none bpool/BOOT
zfs create -o canmount=noauto -o mountpoint=/ rpool/ROOT/debian
zfs mount rpool/ROOT/debian
zfs create -o mountpoint=/boot bpool/BOOT/debian
zfs create rpool/home
zfs create -o mountpoint=/root rpool/home/root
chmod 700 /mnt/root
zfs create -o canmount=off rpool/var
zfs create -o canmount=off rpool/var/lib
zfs create rpool/var/log
zfs create rpool/var/spool
zfs create -o canmount=off rpool/usr
zfs create rpool/usr/local
mkdir /mnt/run
mount -t tmpfs tmpfs /mnt/run
mkdir /mnt/run/lock
debootstrap bullseye /mnt
mkdir /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/
echo bullzfs > /mnt/etc/hostname
vi /mnt/etc/hosts
Add a line:
127.0.1.1 HOSTNAME
vi /mnt/etc/apt/sources.list
deb http://deb.debian.org/debian bullseye main contrib
deb-src http://deb.debian.org/debian bullseye main contrib
deb http://deb.debian.org/debian-security bullseye-security main contrib
deb-src http://deb.debian.org/debian-security bullseye-security main contrib
deb http://deb.debian.org/debian bullseye-updates main contrib
deb-src http://deb.debian.org/debian bullseye-updates main contrib
mount --rbind /dev /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys
chroot /mnt /usr/bin/env DISK=$DISK bash --login
ln -s /proc/self/mounts /etc/mtab
apt update
apt install --yes console-setup locales
apt install --yes dpkg-dev linux-headers-amd64 linux-image-amd64
apt install --yes zfs-initramfs
echo REMAKE_INITRD=yes > /etc/dkms/zfs.conf
'UEFI boot:
apt install dosfstools
mkdosfs -F 32 -s 1 -n EFI ${DISK}-part2
mkdir /boot/efi
echo /dev/disk/by-uuid/$(blkid -s UUID -o value ${DISK}-part2) \
/boot/efi vfat defaults 0 0 >> /etc/fstab
mount /boot/efi
apt-get install --yes grub-efi-amd64 shim-signed
apt remove --yes --purge os-prober
passwd
vi /etc/systemd/system/zfs-import-bpool.service
[Unit]
DefaultDependencies=no
Before=zfs-import-scan.service
Before=zfs-import-cache.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/zpool import -N -o cachefile=none bpool
# Work-around to preserve zpool cache:
ExecStartPre=-/bin/mv /etc/zfs/zpool.cache /etc/zfs/preboot_zpool.cache
ExecStartPost=-/bin/mv /etc/zfs/preboot_zpool.cache /etc/zfs/zpool.cache
[Install]
WantedBy=zfs-import.target
systemctl enable zfs-import-bpool.service
cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount
grub-probe /boot
update-initramfs -c -k all
vi /etc/default/grub
# Set: GRUB_CMDLINE_LINUX="root=ZFS=rpool/ROOT/debian"
# Remove quiet from: GRUB_CMDLINE_LINUX_DEFAULT
# Uncomment: GRUB_TERMINAL=console
# Save and quit.
update-grub
'UEFI boot:
grub-install --target=x86_64-efi --efi-directory=/boot/efi \
--bootloader-id=debian --recheck --no-floppy
>> if there is this error:
Installing for x86_64-efi platform.
grub-install: warning: Cannot set EFI variable Boot0004.
grub-install: warning: efivarfs_set_variable: writing to fd 6 failed: No space left on device.
grub-install: warning: _efi_set_variable_mode: ops->set_variable() failed: No space left on device.
grub-install: error: failed to register the EFI boot entry: No space left on device.
>> run:
rm /sys/firmware/efi/efivars/dump-type0-*
mkdir /etc/zfs/zfs-list.cache
touch /etc/zfs/zfs-list.cache/bpool
touch /etc/zfs/zfs-list.cache/rpool
ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
zed -F &
cat /etc/zfs/zfs-list.cache/bpool
cat /etc/zfs/zfs-list.cache/rpool
# output:
bpool /mnt/boot off on on off on off on off - none - - - - - - --
bpool/BOOT none off on on off on off on off - none - - - - - - --
bpool/BOOT/debian /mnt/boot on on on off on off on off - none - - - - -- - -
# stop zed
fg
Press Ctrl-C.
# fix the paths to eliminate /mnt
sed -Ei "s|/mnt/?|/|" /etc/zfs/zfs-list.cache/*
# first boot
apt install --yes openssh-server
zfs snapshot bpool/BOOT/debian@install
zfs snapshot rpool/ROOT/debian@install
exit
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \
xargs -i{} umount -lf {}
zpool export -a
? fail
reboot
# get an ip address
dhclient
zfs create rpool/home/user
adduser user
cp -a /etc/skel/. /home/user
chown -R user:user /home/user
usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video user
apt dist-upgrade --yes
# install desktop environment
tasksel
for file in /etc/logrotate.d/* ; do
if grep -Eq "(^|[^#y])compress" "$file" ; then
sed -i -r "s/(^|[^#y])(compress)/\1#\2/" "$file"
fi
done
vi /etc/network/interfaces
auto ens32
iface ens32 inet dhcp
reboot
sudo zfs destroy bpool/BOOT/debian@install
sudo zfs destroy rpool/ROOT/debian@install
Legacy bios boot setup
sudo vi /etc/apt/sources.list
deb http://deb.debian.org/debian/ bullseye main contrib
sudo apt update
sudo -i
apt install --yes debootstrap gdisk dkms dpkg-dev \
linux-headers-$(uname -r)
apt install --yes --no-install-recommends zfs-dkms
modprobe zfs
apt install --yes zfsutils-linux
DISK=/dev/disk/by-id/xxx
# create partition
#legacy bios
sgdisk -a1 -n1:24K:+1000K -t1:EF02 $DISK
#boot pool
sgdisk -n3:0:+1G -t3:BF01 $DISK
#root pool
sgdisk -n4:0:0 -t4:BF00 $DISK
# boot pool
zpool create \
-o cachefile=/etc/zfs/zpool.cache \
-o ashift=12 -d \
-o feature@async_destroy=enabled \
-o feature@bookmarks=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled \
-o feature@extensible_dataset=enabled \
-o feature@filesystem_limits=enabled \
-o feature@hole_birth=enabled \
-o feature@large_blocks=enabled \
-o feature@lz4_compress=enabled \
-o feature@spacemap_histogram=enabled \
-o feature@zpool_checkpoint=enabled \
-O acltype=posixacl -O canmount=off -O compression=lz4 \
-O devices=off -O normalization=formD -O relatime=on -O xattr=sa \
-O mountpoint=/boot -R /mnt \
bpool ${DISK}-part3
# root pool
zpool create \
-o ashift=12 \
-O acltype=posixacl -O canmount=off -O compression=lz4 \
-O dnodesize=auto -O normalization=formD -O relatime=on \
-O xattr=sa -O mountpoint=/ -R /mnt \
rpool ${DISK}-part4
zfs create -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o canmount=off -o mountpoint=none bpool/BOOT
zfs create -o canmount=noauto -o mountpoint=/ rpool/ROOT/debian
zfs mount rpool/ROOT/debian
zfs create -o mountpoint=/boot bpool/BOOT/debian
zfs create rpool/home
zfs create -o mountpoint=/root rpool/home/root
chmod 700 /mnt/root
zfs create -o canmount=off rpool/var
zfs create -o canmount=off rpool/var/lib
zfs create rpool/var/log
zfs create rpool/var/spool
zfs create -o canmount=off rpool/usr
zfs create rpool/usr/local
mkdir /mnt/run
mount -t tmpfs tmpfs /mnt/run
mkdir /mnt/run/lock
debootstrap bullseye /mnt
mkdir /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/
echo bullzfs > /mnt/etc/hostname
vi /mnt/etc/hosts
Add a line:
127.0.1.1 HOSTNAME
vi /mnt/etc/apt/sources.list
deb http://deb.debian.org/debian bullseye main contrib
deb-src http://deb.debian.org/debian bullseye main contrib
deb http://deb.debian.org/debian-security bullseye-security main contrib
deb-src http://deb.debian.org/debian-security bullseye-security main contrib
deb http://deb.debian.org/debian bullseye-updates main contrib
deb-src http://deb.debian.org/debian bullseye-updates main contrib
mount --rbind /dev /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys
chroot /mnt /usr/bin/env DISK=$DISK bash --login
ln -s /proc/self/mounts /etc/mtab
apt update
apt install --yes console-setup locales
apt install --yes dpkg-dev linux-headers-amd64 linux-image-amd64
apt install --yes zfs-initramfs
echo REMAKE_INITRD=yes > /etc/dkms/zfs.conf
'Legacy bios boot:
apt install --yes grub-pc
apt remove --yes --purge os-prober
passwd
vi /etc/systemd/system/zfs-import-bpool.service
[Unit]
DefaultDependencies=no
Before=zfs-import-scan.service
Before=zfs-import-cache.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/zpool import -N -o cachefile=none bpool
# Work-around to preserve zpool cache:
ExecStartPre=-/bin/mv /etc/zfs/zpool.cache /etc/zfs/preboot_zpool.cache
ExecStartPost=-/bin/mv /etc/zfs/preboot_zpool.cache /etc/zfs/zpool.cache
[Install]
WantedBy=zfs-import.target
systemctl enable zfs-import-bpool.service
cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount
grub-probe /boot
update-initramfs -c -k all
vi /etc/default/grub
# Set: GRUB_CMDLINE_LINUX="root=ZFS=rpool/ROOT/debian"
# Remove quiet from: GRUB_CMDLINE_LINUX_DEFAULT
# Uncomment: GRUB_TERMINAL=console
# Save and quit.
update-grub
'Legacy bios:
grub-install $DISK
mkdir /etc/zfs/zfs-list.cache
touch /etc/zfs/zfs-list.cache/bpool
touch /etc/zfs/zfs-list.cache/rpool
ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d
zed -F &
cat /etc/zfs/zfs-list.cache/bpool
cat /etc/zfs/zfs-list.cache/rpool
# output:
bpool /mnt/boot off on on off on off on off - none - - - - - - --
bpool/BOOT none off on on off on off on off - none - - - - - - --
bpool/BOOT/debian /mnt/boot on on on off on off on off - none - - - - -- - -
# stop zed
fg
Press Ctrl-C.
# fix the paths to eliminate /mnt
sed -Ei "s|/mnt/?|/|" /etc/zfs/zfs-list.cache/*
# first boot
apt install --yes openssh-server
zfs snapshot bpool/BOOT/debian@install
zfs snapshot rpool/ROOT/debian@install
exit
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \
xargs -i{} umount -lf {}
zpool export -a
? fail
reboot
# get an ip address
dhclient
zfs create rpool/home/user
adduser user
cp -a /etc/skel/. /home/user
chown -R user:user /home/user
usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video user
apt dist-upgrade --yes
# install desktop environment
tasksel
for file in /etc/logrotate.d/* ; do
if grep -Eq "(^|[^#y])compress" "$file" ; then
sed -i -r "s/(^|[^#y])(compress)/\1#\2/" "$file"
fi
done
vi /etc/network/interfaces
auto ens32
iface ens32 inet dhcp
reboot
sudo zfs destroy bpool/BOOT/debian@install
sudo zfs destroy rpool/ROOT/debian@install
hashtags: #zfs