Update Alpine, Arch, Fedora and RHEL root on ZFS guides

Signed-off-by: Maurice Zhou <jasper@apvc.uk>
This commit is contained in:
Maurice Zhou
2023-03-07 20:24:36 +01:00
committed by George Melikov
parent a0c149af5b
commit a69befb2ce
16 changed files with 628 additions and 391 deletions

View File

@@ -26,9 +26,9 @@ Preparation
List available disks with::
ls /dev/disk/by-id/*
find /dev/disk/by-id/
If using virtio as disk bus, use ``/dev/disk/by-path/*``.
If using virtio as disk bus, use ``/dev/disk/by-path/``.
Declare disk array::
@@ -40,11 +40,10 @@ Preparation
#. Set partition size:
Set swap size. It's `recommended <https://chrisdown.name/2018/01/02/in-defence-of-swap.html>`__
to setup a swap partition. If you intend to use hibernation,
the minimum should be no less than RAM size. Skip if swap is not needed::
Set swap size, set to 1 if you don't want swap to
take up too much space::
INST_PARTSIZE_SWAP=8
INST_PARTSIZE_SWAP=4
Root pool size, use all remaining disk space if not set::
@@ -54,7 +53,7 @@ Preparation
curl -L https://archzfs.com/archzfs.gpg | pacman-key -a -
pacman-key --lsign-key $(curl -L https://git.io/JsfVS)
curl -L https://git.io/Jsfw2 > /etc/pacman.d/mirrorlist-archzfs
curl -L https://raw.githubusercontent.com/openzfs/openzfs-docs/master/docs/Getting%20Started/Arch%20Linux/archzfs-repo/mirrorlist-archzfs > /etc/pacman.d/mirrorlist-archzfs
tee -a /etc/pacman.conf <<- 'EOF'
@@ -77,12 +76,26 @@ Preparation
* https://archzfs.com/archive_archzfs/
* https://archzfs.com/archzfs/x86_64/
::
curl -L https://archzfs.com/archive_archzfs/ \
| grep zfs-linux-[0-9] \
| grep -v src.tar \
| grep "5.18.7"
# ...<a href="zfs-linux-2.1.5_5.18.7.arch1.1-1-x86_64.pkg.tar.zst">...
Result: https/.../archive_archzfs/zfs-linux-2.1.5_5.18.7.arch1.1-1-x86_64.pkg.tar.zst
#. Find compatible zfs-utils package:
Search ZFS version string (e.g. 2.1.5) in both pages above.
::
curl -L https://archzfs.com/archzfs/x86_64/ \
| grep zfs-utils-2.1.5 \
| grep -v src.tar
# ...<a href="zfs-utils-2.1.5-1-x86_64.pkg.tar.zst">...
Result: https/.../archzfs/x86_64/zfs-utils-2.1.5-2-x86_64.pkg.tar.zst
#. Download both then install::

View File

@@ -10,13 +10,18 @@ System Installation
for i in ${DISK}; do
# wipe flash-based storage device to improve
# performance.
# ALL DATA WILL BE LOST
# blkdiscard -f $i
sgdisk --zap-all $i
sgdisk -n1:1M:+1G -t1:EF00 $i
sgdisk -n2:0:+4G -t2:BE00 $i
test -z $INST_PARTSIZE_SWAP || sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i
sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i
if test -z $INST_PARTSIZE_RPOOL; then
sgdisk -n3:0:0 -t3:BF00 $i
@@ -25,6 +30,12 @@ System Installation
fi
sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i
sync && udevadm settle && sleep 3
cryptsetup open --type plain --key-file /dev/random $i-part4 ${i##*/}-part4
mkswap /dev/mapper/${i##*/}-part4
swapon /dev/mapper/${i##*/}-part4
done
#. Create boot pool::
@@ -84,9 +95,7 @@ System Installation
If not using a multi-disk setup, remove ``mirror``.
#. This section implements dataset layout as described in `overview <1-preparation.html>`__.
Create root system container:
#. Create root system container:
- Unencrypted::
@@ -108,18 +117,34 @@ System Installation
-o keyformat=passphrase \
rpool/archlinux
Create system datasets::
You can automate this step (insecure) with: ``echo POOLPASS | zfs create ...``.
zfs create -o canmount=on -o mountpoint=/ rpool/archlinux/root
zfs create -o canmount=on -o mountpoint=/home rpool/archlinux/home
zfs create -o canmount=off -o mountpoint=/var rpool/archlinux/var
zfs create -o canmount=on rpool/archlinux/var/lib
zfs create -o canmount=on rpool/archlinux/var/log
Create system datasets, let Archlinux declaratively
manage mountpoints with ``mountpoint=legacy``::
Create boot dataset::
zfs create -o mountpoint=legacy rpool/archlinux/root
mount -t zfs rpool/archlinux/root /mnt/
zfs create -o mountpoint=legacy rpool/archlinux/home
mkdir /mnt/home
mount -t zfs rpool/archlinux/home /mnt/home
zfs create -o mountpoint=legacy rpool/archlinux/var
zfs create -o mountpoint=legacy rpool/archlinux/var/lib
zfs create -o mountpoint=legacy rpool/archlinux/var/log
zfs create -o mountpoint=none bpool/archlinux
zfs create -o mountpoint=legacy bpool/archlinux/root
mkdir /mnt/boot
mount -t zfs bpool/archlinux/root /mnt/boot
#. zfs-mkinitcpio requires root dataset to have a mountpoint
other than legacy::
umount -Rl /mnt
zfs set canmount=noauto rpool/archlinux/root
zfs set mountpoint=/ rpool/archlinux/root
mount -t zfs -o zfsutil rpool/archlinux/root /mnt
mount -t zfs rpool/archlinux/home /mnt/home
mount -t zfs bpool/archlinux/root /mnt/boot
zfs create -o canmount=off -o mountpoint=none bpool/archlinux
zfs create -o canmount=on -o mountpoint=/boot bpool/archlinux/root
#. Format and mount ESP::
@@ -131,14 +156,3 @@ System Installation
mkdir -p /mnt/boot/efi
mount -t vfat $(echo $DISK | cut -f1 -d\ )-part1 /mnt/boot/efi
#. Install packages::
pacstrap /mnt base vi mandoc grub efibootmgr mkinitcpio
CompatibleVer=$(pacman -Si zfs-linux | grep 'Depends On' | sed "s|.*linux=||" | awk '{ print $1 }')
pacstrap -U /mnt https://archive.archlinux.org/packages/l/linux/linux-${CompatibleVer}-x86_64.pkg.tar.zst
pacstrap /mnt zfs-linux zfs-utils
pacstrap /mnt linux-firmware intel-ucode amd-ucode

View File

@@ -8,13 +8,28 @@ System Configuration
#. Generate fstab::
mkdir -p /mnt/var/log
mkdir -p /mnt/var/lib
mount -t zfs rpool/archlinux/var/lib /mnt/var/lib
mount -t zfs rpool/archlinux/var/log /mnt/var/log
mkdir -p /mnt/etc/
for i in ${DISK}; do
echo UUID=$(blkid -s UUID -o value ${i}-part1) /boot/efis/${i##*/}-part1 vfat \
umask=0022,fmask=0022,dmask=0022 0 1 >> /mnt/etc/fstab
done
echo $(echo $DISK | cut -f1 -d\ )-part1 /boot/efi vfat \
noauto,umask=0022,fmask=0022,dmask=0022 0 1 >> /mnt/etc/fstab
genfstab -t PARTUUID /mnt | grep -v swap > /mnt/etc/fstab
sed -i "s|vfat.*rw|vfat rw,x-systemd.idle-timeout=1min,x-systemd.automount,noauto,nofail|" /mnt/etc/fstab
#. Install packages::
pacstrap /mnt base mg mandoc grub efibootmgr mkinitcpio
CompatibleVer=$(pacman -Si zfs-linux \
| grep 'Depends On' \
| sed "s|.*linux=||" \
| awk '{ print $1 }')
pacstrap -U /mnt https://archive.archlinux.org/packages/l/linux/linux-${CompatibleVer}-x86_64.pkg.tar.zst
pacstrap /mnt zfs-linux zfs-utils
pacstrap /mnt linux-firmware intel-ucode amd-ucode
#. Configure mkinitcpio::
@@ -28,19 +43,10 @@ System Configuration
hwclock --systohc
systemctl enable systemd-timesyncd --root=/mnt
#. Set locale, keymap, timezone, hostname and root password::
rm -f /mnt/etc/localtime
systemd-firstboot --root=/mnt --prompt --force
#. Generate host id::
zgenhostid -f -o /mnt/etc/hostid
#. Enable ZFS services::
systemctl enable zfs-import-scan.service zfs-mount zfs-import.target zfs-zed zfs.target --root=/mnt
#. Add archzfs repo::
curl -L https://archzfs.com/archzfs.gpg | pacman-key -a - --gpgdir /mnt/etc/pacman.d/gnupg
@@ -66,3 +72,16 @@ System Configuration
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
#. Generate initrd::
mkinitcpio -P
#. Import from by-id::
echo GRUB_CMDLINE_LINUX=\"zfs_import_dir=/dev/disk/by-id/\" >> /etc/default/grub
#. Set locale, keymap, timezone, hostname and root password::
rm -f /etc/localtime
systemd-firstboot --prompt --force

View File

@@ -6,15 +6,6 @@ Bootloader
.. contents:: Table of Contents
:local:
#. Create empty cache file and generate initrd::
rm -f /etc/zfs/zpool.cache
touch /etc/zfs/zpool.cache
chmod a-w /etc/zfs/zpool.cache
chattr +i /etc/zfs/zpool.cache
mkinitcpio -P
#. Apply GRUB workaround::
echo 'export ZPOOL_VDEV_NAME_PATH=YES' >> /etc/profile.d/zpool_vdev_name_path.sh
@@ -23,14 +14,11 @@ Bootloader
# GRUB fails to detect rpool name, hard code as "rpool"
sed -i "s|rpool=.*|rpool=rpool|" /etc/grub.d/10_linux
echo GRUB_CMDLINE_LINUX=\"zfs_import_dir=/dev/disk/by-id/\" >> /etc/default/grub
This workaround needs to be applied for every GRUB update, as the
update will overwrite the changes.
#. Install GRUB::
export ZPOOL_VDEV_NAME_PATH=YES
mkdir -p /boot/efi/arch/grub-bootdir/i386-pc/
mkdir -p /boot/efi/arch/grub-bootdir/x86_64-efi/
for i in ${DISK}; do
@@ -40,11 +28,8 @@ Bootloader
grub-install --target x86_64-efi --boot-directory \
/boot/efi/arch/grub-bootdir/x86_64-efi/ --efi-directory \
/boot/efi --bootloader-id arch --removable
#. Generate GRUB menu::
grub-mkconfig -o /boot/efi/arch/grub-bootdir/x86_64-efi/grub/grub.cfg
grub-mkconfig -o /boot/efi/arch/grub-bootdir/i386-pc/grub/grub.cfg
grub-mkconfig -o /boot/efi/arch/grub-bootdir/x86_64-efi/grub/grub.cfg
grub-mkconfig -o /boot/efi/arch/grub-bootdir/i386-pc/grub/grub.cfg
#. For both legacy and EFI booting: mirror ESP content::
@@ -70,3 +55,7 @@ Finish Installation
#. Reboot::
reboot
#. You can create a snapshot of the newly installed
system for later rollback,
see `this page <https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS/6-create-boot-environment.html>`__.

View File

@@ -0,0 +1,172 @@
.. highlight:: sh
Create a Boot Environment
==========================
This page is tested for Alpine, Arch Linux, Fedora and
RHEL guides. Not useful for NixOS since system rollback
is already managed by Nix.
With Root on ZFS, it is possible to take snapshots of
existing root file systems, which is a read-only copy of
that file system. A new, full-fledged file system --
clones -- can be then created from this snapshot. This
bootable clone of the current system is then called a
"Boot Environment".
This could be useful if you are performing a major
system upgrade and wish to have the option to go back to
a previous state if the upgrade fails.
#. Identify which dataset is currently mounted as root
``/`` and boot ``/boot``::
findmnt /
# output
TARGET SOURCE FSTYPE OPTIONS
/ rpool/archlinux/root zfs rw,relatime,xattr,posixacl
findmnt /boot
# output
TARGET SOURCE FSTYPE OPTIONS
/boot bpool/archlinux/root zfs rw,relatime,xattr,posixacl
#. Identify your distribution in the dataset (file system) path::
DISTRO=archlinux # or `fedora', `alma', `alpinelinux'
#. Choose a name for the new boot environment::
BE_NAME=backup
#. Take snapshots of the ``/`` and ``/boot`` datasets::
zfs snapshot rpool/$DISTRO/root@$BE_NAME
zfs snapshot bpool/$DISTRO/root@$BE_NAME
#. Create clones from read-only snapshots::
zfs clone -o canmount=noauto \
-o mountpoint=/ \
rpool/$DISTRO/root@$BE_NAME \
rpool/$DISTRO/$BE_NAME
zfs clone -o canmount=noauto \
-o mountpoint=legacy \
bpool/$DISTRO/root@$BE_NAME \
bpool/$DISTRO/$BE_NAME
#. Mount clone and update file system table (fstab) ::
mount -t zfs -o zfsutil rpool/$DISTRO/$BE_NAME /mnt
mount -t zfs bpool/$DISTRO/$BE_NAME /mnt/boot
sed -i "s|rpool/$DISTRO/root|rpool/$DISTRO/$BE_NAME|g" /mnt/etc/fstab
sed -i "s|bpool/$DISTRO/root|bpool/$DISTRO/$BE_NAME|g" /mnt/etc/fstab
If legacy mountpoint is used, omit ``-o zfsutil``
from mount command.
#. Create GRUB menu for new clone::
m='/dev /proc /sys'
for i in $m; do mount --rbind $i /mnt/$i; done
chroot /mnt /usr/bin/env sh <<EOF
if which grub-mkconfig; then
grub-mkconfig -o /boot/grub.cfg
else
grub2-mkconfig -o /boot/grub.cfg
fi
EOF
GRUB menu contains information on kernel version and initramfs.
#. Unmount clone::
umount -Rl /mnt
#. Add new boot environment as GRUB menu entry::
tee -a new_entry <<EOF
menuentry 'ZFS Clone of ${DISTRO}: ${BE_NAME}' { configfile (hd0,gpt2)/${DISTRO}/${BE_NAME}@/grub.cfg }
EOF
find /boot/efis/ -name "grub.cfg" \
| while read i; do
if grep -q "${DISTRO}" $i; then
cat $i new_entry > grub.cfg
cp grub.cfg $i
fi
done
rm new_entry
#. After reboot, select boot environment entry from GRUB
menu to boot from the clone. Press ESC inside
submenu to return to the previous menu.
#. Steps above can also be used to create a new clone
from an existing snapshot.
#. To set a boot environment as default, replace
existing ``grub.cfg`` inside EFI system partition
with the one from the boot environment::
mount -t zfs bpool/$DISTRO/$BE_NAME /mnt
# backup existing grub.cfg inside EFI
# then replace it with menu from clone
mkdir -p /mnt/grub_menu_backup
menu_counter=1
find /boot/efis/ -name "grub.cfg" \
| while read i; do
if grep -q "${DISTRO}" $i; then
cp $i /mnt/grub_menu_backup/grub_${menu_counter}.cfg
echo $i > /mnt/grub_menu_backup/grub_${menu_counter}_path.txt
cp /mnt/grub.cfg $i
menu_counter=$(($menu_counter + 1))
fi
done
umount -Rl /mnt
#. To delete the boot environment, check with
``findmnt`` that the boot environment is not
currently used::
findmnt /
findmnt /boot
Set variables::
DISTRO=archlinux
Then check the origin snapshot::
zfs get origin rpool/archlinux/backup
# rpool/archlinux/root@backup
zfs get origin bpool/archlinux/backup
# bpool/archlinux/root@backup
RM_BE=backup
RM_SNAPSHOT=root@backup
Finally, destroy clone (boot environment) and its
origin snapshot::
zfs destroy rpool/${DISTRO}/${RM_BE}
zfs destroy rpool/${DISTRO}/${RM_SNAPSHOT}
zfs destroy bpool/${DISTRO}/${RM_BE}
zfs destroy bpool/${DISTRO}/${RM_SNAPSHOT}
Remove GRUB entry::
find /boot/efis/ -name "grub.cfg" \
| while read i; do
if grep -q "${DISTRO}/${RM_BE}@/grub.cfg" $i; then
head -n -1 $i > grub.cfg
cp grub.cfg $i
fi
done