Alpine, Arch Linux, Fedora, RHEL, NixOS Root on ZFS guide: add CI/CD tests
Remove unmaintained Arch Linux guides. Signed-off-by: Maurice Zhou <yuchen@apvc.uk>
This commit is contained in:
committed by
George Melikov
parent
a67d02b8ac
commit
4fb5fb694f
@@ -1,11 +0,0 @@
|
||||
RHEL Root on ZFS
|
||||
=======================================
|
||||
Start from "Preparation".
|
||||
|
||||
Contents
|
||||
--------
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
|
||||
RHEL-based distro Root on ZFS/*
|
||||
@@ -1,74 +0,0 @@
|
||||
.. highlight:: sh
|
||||
|
||||
Preparation
|
||||
======================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:local:
|
||||
|
||||
#. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled.
|
||||
#. Download a variant of `AlmaLinux Minimal Live ISO
|
||||
<https://repo.almalinux.org/almalinux/9.1/live/x86_64/>`__
|
||||
and boot from it.
|
||||
#. Connect to the Internet.
|
||||
#. Set root password or ``/root/.ssh/authorized_keys``.
|
||||
#. Start SSH server::
|
||||
|
||||
echo PermitRootLogin yes >> /etc/ssh/sshd_config
|
||||
systemctl restart sshd
|
||||
|
||||
#. Connect from another computer::
|
||||
|
||||
ssh root@192.168.1.19
|
||||
|
||||
#. Target disk
|
||||
|
||||
List available disks with::
|
||||
|
||||
find /dev/disk/by-id/
|
||||
|
||||
If using virtio as disk bus, use ``/dev/disk/by-path/``.
|
||||
|
||||
Declare disk array::
|
||||
|
||||
DISK='/dev/disk/by-id/ata-FOO /dev/disk/by-id/nvme-BAR'
|
||||
|
||||
For single disk installation, use::
|
||||
|
||||
DISK='/dev/disk/by-id/disk1'
|
||||
|
||||
#. Set partition size:
|
||||
|
||||
Set swap size, set to 1 if you don't want swap to
|
||||
take up too much space::
|
||||
|
||||
INST_PARTSIZE_SWAP=4
|
||||
|
||||
Root pool size, use all remaining disk space if not set::
|
||||
|
||||
INST_PARTSIZE_RPOOL=
|
||||
|
||||
#. Temporarily set SELinux to permissive in live environment::
|
||||
|
||||
setenforce 0
|
||||
|
||||
SELinux will be enabled on the installed system.
|
||||
|
||||
#. Add ZFS repo and install ZFS inside live system::
|
||||
|
||||
dnf install -y https://zfsonlinux.org/epel/zfs-release-2-2$(rpm --eval "%{dist}").noarch.rpm
|
||||
rpm -e --nodeps zfs-fuse || true
|
||||
source /etc/os-release
|
||||
export VERSION_ID
|
||||
dnf config-manager --disable zfs
|
||||
dnf config-manager --enable zfs-kmod
|
||||
dnf install -y zfs
|
||||
modprobe zfs
|
||||
|
||||
#. Install partition tool and arch-install-scripts::
|
||||
|
||||
dnf install -y epel-release
|
||||
dnf install -y gdisk dosfstools cryptsetup
|
||||
dnf download arch-install-scripts
|
||||
rpm -i --nodeps arch-install-scripts*.rpm
|
||||
dnf remove -y epel-release
|
||||
@@ -1,151 +0,0 @@
|
||||
.. highlight:: sh
|
||||
|
||||
System Installation
|
||||
======================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:local:
|
||||
|
||||
#. Partition the disks::
|
||||
|
||||
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
|
||||
|
||||
sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i
|
||||
|
||||
if test -z $INST_PARTSIZE_RPOOL; then
|
||||
sgdisk -n3:0:0 -t3:BF00 $i
|
||||
else
|
||||
sgdisk -n3:0:+${INST_PARTSIZE_RPOOL}G -t3:BF00 $i
|
||||
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::
|
||||
|
||||
zpool create \
|
||||
-o compatibility=grub2 \
|
||||
-o ashift=12 \
|
||||
-o autotrim=on \
|
||||
-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 \
|
||||
mirror \
|
||||
$(for i in ${DISK}; do
|
||||
printf "$i-part2 ";
|
||||
done)
|
||||
|
||||
If not using a multi-disk setup, remove ``mirror``.
|
||||
|
||||
You should not need to customize any of the options for the boot pool.
|
||||
|
||||
GRUB does not support all of the zpool features. See ``spa_feature_names``
|
||||
in `grub-core/fs/zfs/zfs.c
|
||||
<http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/fs/zfs/zfs.c#n276>`__.
|
||||
This step creates a separate boot pool for ``/boot`` with the features
|
||||
limited to only those that GRUB supports, allowing the root pool to use
|
||||
any/all features.
|
||||
|
||||
Features enabled with ``-o compatibility=grub2`` can be seen
|
||||
`here <https://github.com/openzfs/zfs/blob/master/cmd/zpool/compatibility.d/grub2>`__.
|
||||
|
||||
#. Create root pool::
|
||||
|
||||
zpool create \
|
||||
-o ashift=12 \
|
||||
-o autotrim=on \
|
||||
-R /mnt \
|
||||
-O acltype=posixacl \
|
||||
-O canmount=off \
|
||||
-O compression=zstd \
|
||||
-O dnodesize=auto \
|
||||
-O normalization=formD \
|
||||
-O relatime=on \
|
||||
-O xattr=sa \
|
||||
-O mountpoint=/ \
|
||||
rpool \
|
||||
mirror \
|
||||
$(for i in ${DISK}; do
|
||||
printf "$i-part3 ";
|
||||
done)
|
||||
|
||||
If not using a multi-disk setup, remove ``mirror``.
|
||||
|
||||
#. Create root system container:
|
||||
|
||||
- Unencrypted::
|
||||
|
||||
zfs create \
|
||||
-o canmount=off \
|
||||
-o mountpoint=none \
|
||||
rpool/alma
|
||||
|
||||
- Encrypted:
|
||||
|
||||
Pick a strong password. Once compromised, changing password will not keep your
|
||||
data safe. See ``zfs-change-key(8)`` for more info::
|
||||
|
||||
zfs create \
|
||||
-o canmount=off \
|
||||
-o mountpoint=none \
|
||||
-o encryption=on \
|
||||
-o keylocation=prompt \
|
||||
-o keyformat=passphrase \
|
||||
rpool/alma
|
||||
|
||||
You can automate this step (insecure) with: ``echo POOLPASS | zfs create ...``.
|
||||
|
||||
Create system datasets, let Alma declaratively
|
||||
manage mountpoints with ``mountpoint=legacy``::
|
||||
|
||||
zfs create -o mountpoint=/ -o canmount=noauto rpool/alma/root
|
||||
zfs mount rpool/alma/root
|
||||
zfs create -o mountpoint=legacy rpool/alma/home
|
||||
mkdir /mnt/home
|
||||
mount -t zfs rpool/alma/home /mnt/home
|
||||
zfs create -o mountpoint=legacy rpool/alma/var
|
||||
zfs create -o mountpoint=legacy rpool/alma/var/lib
|
||||
zfs create -o mountpoint=legacy rpool/alma/var/log
|
||||
zfs create -o mountpoint=none bpool/alma
|
||||
zfs create -o mountpoint=legacy bpool/alma/root
|
||||
mkdir /mnt/boot
|
||||
mount -t zfs bpool/alma/root /mnt/boot
|
||||
mkdir -p /mnt/var/log
|
||||
mkdir -p /mnt/var/lib
|
||||
mount -t zfs rpool/alma/var/lib /mnt/var/lib
|
||||
mount -t zfs rpool/alma/var/log /mnt/var/log
|
||||
|
||||
#. Format and mount ESP::
|
||||
|
||||
for i in ${DISK}; do
|
||||
mkfs.vfat -n EFI ${i}-part1
|
||||
mkdir -p /mnt/boot/efis/${i##*/}-part1
|
||||
mount -t vfat ${i}-part1 /mnt/boot/efis/${i##*/}-part1
|
||||
done
|
||||
|
||||
mkdir -p /mnt/boot/efi
|
||||
mount -t vfat $(echo $DISK | cut -f1 -d' ')-part1 /mnt/boot/efi
|
||||
@@ -1,80 +0,0 @@
|
||||
.. highlight:: sh
|
||||
|
||||
System Configuration
|
||||
======================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:local:
|
||||
|
||||
#. Generate fstab::
|
||||
|
||||
mkdir -p /mnt/etc/
|
||||
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 basic system packages::
|
||||
|
||||
dnf --installroot=/mnt \
|
||||
--releasever=$VERSION_ID -y install \
|
||||
@core grub2-efi-x64 \
|
||||
grub2-pc-modules grub2-efi-x64-modules \
|
||||
shim-x64 efibootmgr \
|
||||
kernel-$(uname -r)
|
||||
|
||||
dnf --installroot=/mnt \
|
||||
--releasever=$VERSION_ID -y install \
|
||||
https://zfsonlinux.org/epel/zfs-release-2-2$(rpm --eval "%{dist}").noarch.rpm
|
||||
dnf config-manager --installroot=/mnt --disable zfs
|
||||
dnf config-manager --installroot=/mnt --enable zfs-kmod
|
||||
dnf --installroot=/mnt --releasever=$VERSION_ID \
|
||||
-y install zfs zfs-dracut
|
||||
|
||||
#. Configure dracut::
|
||||
|
||||
echo 'add_dracutmodules+=" zfs "' >> /mnt/etc/dracut.conf.d/zfs.conf
|
||||
echo 'forced_drivers+=" zfs "' >> /mnt/etc/dracut.conf.d/zfs.conf
|
||||
if grep mpt3sas /proc/modules; then
|
||||
echo 'forced_drivers+=" mpt3sas "' >> /mnt/etc/dracut.conf.d/zfs.conf
|
||||
fi
|
||||
if grep virtio_blk /proc/modules; then
|
||||
echo 'filesystems+=" virtio_blk "' >> /mnt/etc/dracut.conf.d/fs.conf
|
||||
fi
|
||||
|
||||
#. Generate host id::
|
||||
|
||||
zgenhostid -f -o /mnt/etc/hostid
|
||||
|
||||
#. Install locale package, example for English locale::
|
||||
|
||||
dnf --installroot=/mnt install -y glibc-minimal-langpack glibc-langpack-en
|
||||
|
||||
#. By default SSH server is enabled, allowing root login by password,
|
||||
disable SSH server::
|
||||
|
||||
systemctl disable sshd --root=/mnt
|
||||
systemctl enable firewalld --root=/mnt
|
||||
|
||||
#. Chroot::
|
||||
|
||||
history -w /mnt/home/sys-install-pre-chroot.txt
|
||||
arch-chroot /mnt /usr/bin/env DISK="$DISK" bash --login
|
||||
|
||||
#. For SELinux, relabel filesystem on reboot::
|
||||
|
||||
fixfiles -F onboot
|
||||
|
||||
#. Generate initrd::
|
||||
|
||||
for directory in /lib/modules/*; do
|
||||
kernel_version=$(basename $directory)
|
||||
dracut --force --kver $kernel_version
|
||||
done
|
||||
|
||||
#. Set locale, keymap, timezone, hostname and root password::
|
||||
|
||||
rm -f /etc/localtime
|
||||
systemd-firstboot --prompt --root-password=PASSWORD --force
|
||||
|
||||
#. Set root password, the password set earlier does not work due to SELinux::
|
||||
|
||||
passwd
|
||||
@@ -1,81 +0,0 @@
|
||||
.. highlight:: sh
|
||||
|
||||
Bootloader
|
||||
======================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:local:
|
||||
|
||||
#. Apply GRUB workaround::
|
||||
|
||||
echo 'export ZPOOL_VDEV_NAME_PATH=YES' >> /etc/profile.d/zpool_vdev_name_path.sh
|
||||
source /etc/profile.d/zpool_vdev_name_path.sh
|
||||
|
||||
# GRUB fails to detect rpool name, hard code as "rpool"
|
||||
sed -i "s|rpool=.*|rpool=rpool|" /etc/grub.d/10_linux
|
||||
|
||||
This ``sed`` workaround needs to be applied for every
|
||||
GRUB update, as the update will overwrite the
|
||||
changes.
|
||||
|
||||
#. Install GRUB::
|
||||
|
||||
echo 'GRUB_ENABLE_BLSCFG=false' >> /etc/default/grub
|
||||
mkdir -p /boot/efi/almalinux/grub-bootdir/i386-pc/
|
||||
mkdir -p /boot/efi/almalinux/grub-bootdir/x86_64-efi/
|
||||
for i in ${DISK}; do
|
||||
grub2-install --target=i386-pc --boot-directory \
|
||||
/boot/efi/almalinux/grub-bootdir/i386-pc/ $i
|
||||
done
|
||||
cp -r /usr/lib/grub/x86_64-efi/ /boot/efi/EFI/almalinux/
|
||||
grub2-mkconfig -o /boot/efi/EFI/almalinux/grub.cfg
|
||||
grub2-mkconfig -o /boot/efi/almalinux/grub-bootdir/i386-pc/grub2/grub.cfg
|
||||
mkdir -p /boot/grub2
|
||||
grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
|
||||
#. For both legacy and EFI booting: mirror ESP content::
|
||||
|
||||
unalias -a
|
||||
ESP_MIRROR=$(mktemp -d)
|
||||
cp -r /boot/efi/EFI $ESP_MIRROR
|
||||
for i in /boot/efis/*; do
|
||||
cp -r $ESP_MIRROR/EFI $i
|
||||
done
|
||||
rm -rf $ESP_MIRROR
|
||||
|
||||
#. Note: you need to regenerate GRUB menu after kernel
|
||||
updates, otherwise computer will still boot old
|
||||
kernel on reboot::
|
||||
|
||||
grub2-mkconfig -o /boot/efi/EFI/almalinux/grub.cfg
|
||||
grub2-mkconfig -o /boot/efi/almalinux/grub-bootdir/i386-pc/grub2/grub.cfg
|
||||
grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
|
||||
Finish Installation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#. Exit chroot::
|
||||
|
||||
exit
|
||||
|
||||
#. Export pools::
|
||||
|
||||
umount -Rl /mnt
|
||||
zpool export -a
|
||||
|
||||
#. Reboot::
|
||||
|
||||
reboot
|
||||
|
||||
Post installaion
|
||||
~~~~~~~~~~~~~~~~
|
||||
#. Install package groups::
|
||||
|
||||
dnf group list --hidden -v # query package groups
|
||||
dnf group install gnome-desktop
|
||||
|
||||
#. Add new user, configure swap.
|
||||
|
||||
#. 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>`__.
|
||||
662
docs/Getting Started/RHEL-based distro/Root on ZFS.rst
Normal file
662
docs/Getting Started/RHEL-based distro/Root on ZFS.rst
Normal file
@@ -0,0 +1,662 @@
|
||||
.. highlight:: sh
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# For the CI/CD test run of this guide,
|
||||
# Enable verbose logging of bash shell and fail immediately when
|
||||
# a commmand fails.
|
||||
set -vxeuf
|
||||
distro=${1}
|
||||
|
||||
cp /etc/resolv.conf ./"rootfs-${distro}"/etc/resolv.conf
|
||||
arch-chroot ./"rootfs-${distro}" sh <<-'ZFS_ROOT_GUIDE_TEST'
|
||||
|
||||
set -vxeuf
|
||||
|
||||
# install alpine setup scripts
|
||||
apk update
|
||||
apk add alpine-conf curl
|
||||
|
||||
.. In this document, there are three types of code-block markups:
|
||||
``::`` are commands intended for both the vm test and the users
|
||||
``.. ifconfig:: zfs_root_test`` are commands intended only for vm test
|
||||
``.. code-block:: sh`` are commands intended only for users
|
||||
|
||||
Rocky Linux Root on ZFS
|
||||
=======================================
|
||||
|
||||
**Customization**
|
||||
|
||||
Unless stated otherwise, it is not recommended to customize system
|
||||
configuration before reboot.
|
||||
|
||||
Preparation
|
||||
---------------------------
|
||||
|
||||
#. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled.
|
||||
#. Because the kernel of latest Live CD might be incompatible with
|
||||
ZFS, we will use Alpine Linux Extended, which ships with ZFS by
|
||||
default.
|
||||
|
||||
Download latest extended variant of `Alpine Linux
|
||||
live image
|
||||
<https://dl-cdn.alpinelinux.org/alpine/v3.17/releases/x86_64/alpine-extended-3.17.3-x86_64.iso>`__,
|
||||
verify `checksum <https://dl-cdn.alpinelinux.org/alpine/v3.17/releases/x86_64/alpine-extended-3.17.3-x86_64.iso.asc>`__
|
||||
and boot from it.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
gpg --auto-key-retrieve --keyserver hkps://keyserver.ubuntu.com --verify alpine-extended-*.asc
|
||||
|
||||
dd if=input-file of=output-file bs=1M
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# check whether the download page exists
|
||||
# alpine version must be in sync with ci/cd test chroot tarball
|
||||
|
||||
#. Login as root user. There is no password.
|
||||
#. Configure Internet
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
setup-interfaces -r
|
||||
# You must use "-r" option to start networking services properly
|
||||
# example:
|
||||
network interface: wlan0
|
||||
WiFi name: <ssid>
|
||||
ip address: dhcp
|
||||
<enter done to finish network config>
|
||||
manual netconfig: n
|
||||
|
||||
#. If you are using wireless network and it is not shown, see `Alpine
|
||||
Linux wiki
|
||||
<https://wiki.alpinelinux.org/wiki/Wi-Fi#wpa_supplicant>`__ for
|
||||
further details. ``wpa_supplicant`` can be installed with ``apk
|
||||
add wpa_supplicant`` without internet connection.
|
||||
|
||||
#. Configure SSH server
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
setup-sshd
|
||||
# example:
|
||||
ssh server: openssh
|
||||
allow root: "prohibit-password" or "yes"
|
||||
ssh key: "none" or "<public key>"
|
||||
|
||||
#. Set root password or ``/root/.ssh/authorized_keys``.
|
||||
|
||||
#. Connect from another computer
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
ssh root@192.168.1.91
|
||||
|
||||
#. Configure NTP client for time synchronization
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
setup-ntp busybox
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# this step is unnecessary for chroot and returns 1 when executed
|
||||
|
||||
#. Set up apk-repo. A list of available mirrors is shown.
|
||||
Press space bar to continue
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
setup-apkrepos
|
||||
|
||||
|
||||
#. Throughout this guide, we use predictable disk names generated by
|
||||
udev
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
apk update
|
||||
apk add eudev
|
||||
setup-devd udev
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# for some reason, udev is extremely slow in chroot
|
||||
# it is not needed for chroot anyway. so, skip this step
|
||||
|
||||
#. Target disk
|
||||
|
||||
List available disks with
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
find /dev/disk/by-id/
|
||||
|
||||
If virtio is used as disk bus, power off the VM and set serial numbers for disk.
|
||||
For QEMU, use ``-drive format=raw,file=disk2.img,serial=AaBb``.
|
||||
For libvirt, edit domain XML. See `this page
|
||||
<https://bugzilla.redhat.com/show_bug.cgi?id=1245013>`__ for examples.
|
||||
|
||||
Declare disk array
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
DISK='/dev/disk/by-id/ata-FOO /dev/disk/by-id/nvme-BAR'
|
||||
|
||||
For single disk installation, use
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
DISK='/dev/disk/by-id/disk1'
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# for github test run, use chroot and loop devices
|
||||
DISK="$(losetup -a| grep rhel | cut -f1 -d: | xargs -t -I '{}' printf '{} ')"
|
||||
|
||||
#. Set a mount point
|
||||
::
|
||||
|
||||
MNT=$(mktemp -d)
|
||||
|
||||
#. Set partition size:
|
||||
|
||||
Set swap size in GB, set to 1 if you don't want swap to
|
||||
take up too much space
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
SWAPSIZE=4
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# For the test run, use 1GB swap space to avoid hitting CI/CD
|
||||
# quota
|
||||
SWAPSIZE=1
|
||||
|
||||
Set how much space should be left at the end of the disk, minimum 1GB
|
||||
|
||||
::
|
||||
|
||||
RESERVE=1
|
||||
|
||||
#. Install ZFS support from live media::
|
||||
|
||||
apk add zfs
|
||||
|
||||
#. Install partition tool
|
||||
::
|
||||
|
||||
apk add parted e2fsprogs cryptsetup util-linux
|
||||
|
||||
System Installation
|
||||
---------------------------
|
||||
|
||||
#. Partition the disks.
|
||||
|
||||
Note: you must clear all existing partition tables and data structures from the disks,
|
||||
especially those with existing ZFS pools or mdraid and those that have been used as live media.
|
||||
Those data structures may interfere with boot process.
|
||||
|
||||
For flash-based storage, this can be done by uncommenting the blkdiscard command below:
|
||||
::
|
||||
|
||||
partition_disk () {
|
||||
local disk="${1}"
|
||||
#blkdiscard -f "${disk}"
|
||||
|
||||
parted --script --align=optimal "${disk}" -- \
|
||||
mklabel gpt \
|
||||
mkpart EFI 2MiB 1GiB \
|
||||
mkpart bpool 1GiB 5GiB \
|
||||
mkpart rpool 5GiB -$((SWAPSIZE + RESERVE))GiB \
|
||||
mkpart swap -$((SWAPSIZE + RESERVE))GiB -"${RESERVE}"GiB \
|
||||
mkpart BIOS 1MiB 2MiB \
|
||||
set 1 esp on \
|
||||
set 5 bios_grub on \
|
||||
set 5 legacy_boot on
|
||||
|
||||
partprobe "${disk}"
|
||||
}
|
||||
|
||||
for i in ${DISK}; do
|
||||
partition_disk "${i}"
|
||||
done
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
::
|
||||
|
||||
# When working with GitHub chroot runners, we are using loop
|
||||
# devices as installation target. However, the alias support for
|
||||
# loop device was just introduced in March 2023. See
|
||||
# https://github.com/systemd/systemd/pull/26693
|
||||
# For now, we will create the aliases maunally as a workaround
|
||||
looppart="1 2 3 4 5"
|
||||
for i in ${DISK}; do
|
||||
for j in ${looppart}; do
|
||||
if test -e "${i}p${j}"; then
|
||||
ln -s "${i}p${j}" "${i}-part${j}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
#. Setup encrypted swap. This is useful if the available memory is
|
||||
small::
|
||||
|
||||
for i in ${DISK}; do
|
||||
cryptsetup open --type plain --key-file /dev/random "${i}"-part4 "${i##*/}"-part4
|
||||
mkswap /dev/mapper/"${i##*/}"-part4
|
||||
swapon /dev/mapper/"${i##*/}"-part4
|
||||
done
|
||||
|
||||
#. Load ZFS kernel module
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
modprobe zfs
|
||||
|
||||
#. Create boot pool
|
||||
::
|
||||
|
||||
# shellcheck disable=SC2046
|
||||
zpool create -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 ashift=12 \
|
||||
-o autotrim=on \
|
||||
-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 \
|
||||
mirror \
|
||||
$(for i in ${DISK}; do
|
||||
printf '%s ' "${i}-part2";
|
||||
done)
|
||||
|
||||
If not using a multi-disk setup, remove ``mirror``.
|
||||
|
||||
You should not need to customize any of the options for the boot pool.
|
||||
|
||||
GRUB does not support all of the zpool features. See ``spa_feature_names``
|
||||
in `grub-core/fs/zfs/zfs.c
|
||||
<http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/fs/zfs/zfs.c#n276>`__.
|
||||
This step creates a separate boot pool for ``/boot`` with the features
|
||||
limited to only those that GRUB supports, allowing the root pool to use
|
||||
any/all features.
|
||||
|
||||
#. Create root pool
|
||||
::
|
||||
|
||||
# shellcheck disable=SC2046
|
||||
zpool create \
|
||||
-o ashift=12 \
|
||||
-o autotrim=on \
|
||||
-R "${MNT}" \
|
||||
-O acltype=posixacl \
|
||||
-O canmount=off \
|
||||
-O compression=zstd \
|
||||
-O dnodesize=auto \
|
||||
-O normalization=formD \
|
||||
-O relatime=on \
|
||||
-O xattr=sa \
|
||||
-O mountpoint=/ \
|
||||
rpool \
|
||||
mirror \
|
||||
$(for i in ${DISK}; do
|
||||
printf '%s ' "${i}-part3";
|
||||
done)
|
||||
|
||||
If not using a multi-disk setup, remove ``mirror``.
|
||||
|
||||
#. Create root system container:
|
||||
|
||||
- Unencrypted
|
||||
|
||||
::
|
||||
|
||||
zfs create \
|
||||
-o canmount=off \
|
||||
-o mountpoint=none \
|
||||
rpool/rhel
|
||||
|
||||
- Encrypted:
|
||||
|
||||
Pick a strong password. Once compromised, changing password will not keep your
|
||||
data safe. See ``zfs-change-key(8)`` for more info
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
zfs create \
|
||||
-o canmount=off \
|
||||
-o mountpoint=none \
|
||||
-o encryption=on \
|
||||
-o keylocation=prompt \
|
||||
-o keyformat=passphrase \
|
||||
rpool/rhel
|
||||
|
||||
You can automate this step (insecure) with: ``echo POOLPASS | zfs create ...``.
|
||||
|
||||
Create system datasets,
|
||||
manage mountpoints with ``mountpoint=legacy``
|
||||
::
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/ rpool/rhel/root
|
||||
zfs mount rpool/rhel/root
|
||||
zfs create -o mountpoint=legacy rpool/rhel/home
|
||||
mkdir "${MNT}"/home
|
||||
mount -t zfs rpool/rhel/home "${MNT}"/home
|
||||
zfs create -o mountpoint=legacy rpool/rhel/var
|
||||
zfs create -o mountpoint=legacy rpool/rhel/var/lib
|
||||
zfs create -o mountpoint=legacy rpool/rhel/var/log
|
||||
zfs create -o mountpoint=none bpool/rhel
|
||||
zfs create -o mountpoint=legacy bpool/rhel/root
|
||||
mkdir "${MNT}"/boot
|
||||
mount -t zfs bpool/rhel/root "${MNT}"/boot
|
||||
mkdir -p "${MNT}"/var/log
|
||||
mkdir -p "${MNT}"/var/lib
|
||||
mount -t zfs rpool/rhel/var/lib "${MNT}"/var/lib
|
||||
mount -t zfs rpool/rhel/var/log "${MNT}"/var/log
|
||||
|
||||
#. Format and mount ESP
|
||||
::
|
||||
|
||||
for i in ${DISK}; do
|
||||
mkfs.vfat -n EFI "${i}"-part1
|
||||
mkdir -p "${MNT}"/boot/efis/"${i##*/}"-part1
|
||||
mount -t vfat -o iocharset=iso8859-1 "${i}"-part1 "${MNT}"/boot/efis/"${i##*/}"-part1
|
||||
done
|
||||
|
||||
mkdir -p "${MNT}"/boot/efi
|
||||
mount -t vfat -o iocharset=iso8859-1 "$(echo "${DISK}" | sed "s|^ *||" | cut -f1 -d' '|| true)"-part1 "${MNT}"/boot/efi
|
||||
|
||||
System Configuration
|
||||
---------------------------
|
||||
|
||||
#. Download and extract minimal Rhel root filesystem::
|
||||
|
||||
apk add curl
|
||||
curl --fail-early --fail -L \
|
||||
https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-Container-Base-9.1-20230215.0.x86_64.tar.xz \
|
||||
-o rootfs.tar.gz
|
||||
curl --fail-early --fail -L \
|
||||
https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-Container-Base-9.1-20230215.0.x86_64.tar.xz.CHECKSUM \
|
||||
-o checksum
|
||||
|
||||
# BusyBox sha256sum treats all lines in the checksum file
|
||||
# as checksums and requires two spaces " "
|
||||
# between filename and checksum
|
||||
|
||||
grep 'Container-Base' checksum \
|
||||
| grep '^SHA256' \
|
||||
| sed -E 's|.*= ([a-z0-9]*)$|\1 rootfs.tar.gz|' > ./sha256checksum
|
||||
|
||||
sha256sum -c ./sha256checksum
|
||||
|
||||
tar x -C "${MNT}" -af rootfs.tar.gz
|
||||
|
||||
#. Enable community repo
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
sed -i '/edge/d' /etc/apk/repositories
|
||||
sed -i -E 's/#(.*)community/\1community/' /etc/apk/repositories
|
||||
|
||||
#. Generate fstab::
|
||||
|
||||
apk add arch-install-scripts
|
||||
genfstab -t PARTUUID "${MNT}" \
|
||||
| grep -v swap \
|
||||
| sed "s|vfat.*rw|vfat rw,x-systemd.idle-timeout=1min,x-systemd.automount,noauto,nofail|" \
|
||||
> "${MNT}"/etc/fstab
|
||||
|
||||
#. Chroot
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cp /etc/resolv.conf "${MNT}"/etc/resolv.conf
|
||||
for i in /dev /proc /sys; do mkdir -p "${MNT}"/"${i}"; mount --rbind "${i}" "${MNT}"/"${i}"; done
|
||||
chroot "${MNT}" /usr/bin/env DISK="${DISK}" bash
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
cp /etc/resolv.conf "${MNT}"/etc/resolv.conf
|
||||
for i in /dev /proc /sys; do mkdir -p "${MNT}"/"${i}"; mount --rbind "${i}" "${MNT}"/"${i}"; done
|
||||
chroot "${MNT}" /usr/bin/env DISK="${DISK}" bash <<-'ZFS_ROOT_NESTED_CHROOT'
|
||||
|
||||
set -vxeuf
|
||||
|
||||
#. Unset all shell aliases, which can interfere with installation::
|
||||
|
||||
unalias -a
|
||||
|
||||
#. Install base packages
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
dnf -y install --allowerasing @core grub2-efi-x64 \
|
||||
grub2-pc grub2-pc-modules grub2-efi-x64-modules shim-x64 \
|
||||
efibootmgr kernel-core
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# skip installing firmware in test
|
||||
dnf -y install --allowerasing --setopt=install_weak_deps=False \
|
||||
@core grub2-efi-x64 \
|
||||
grub2-pc grub2-pc-modules grub2-efi-x64-modules shim-x64 \
|
||||
efibootmgr kernel-core
|
||||
|
||||
#. Install ZFS packages::
|
||||
|
||||
dnf install -y https://zfsonlinux.org/epel/zfs-release-2-2"$(rpm --eval "%{dist}"|| true)".noarch.rpm
|
||||
dnf config-manager --disable zfs
|
||||
dnf config-manager --enable zfs-kmod
|
||||
dnf install -y zfs zfs-dracut
|
||||
|
||||
#. Add zfs modules to dracut::
|
||||
|
||||
echo 'add_dracutmodules+=" zfs "' >> /etc/dracut.conf.d/zfs.conf
|
||||
echo 'force_drivers+=" zfs "' >> /etc/dracut.conf.d/zfs.conf
|
||||
|
||||
#. Add other drivers to dracut::
|
||||
|
||||
if grep mpt3sas /proc/modules; then
|
||||
echo 'force_drivers+=" mpt3sas "' >> /etc/dracut.conf.d/zfs.conf
|
||||
fi
|
||||
if grep virtio_blk /proc/modules; then
|
||||
echo 'filesystems+=" virtio_blk "' >> /etc/dracut.conf.d/fs.conf
|
||||
fi
|
||||
|
||||
#. Build initrd::
|
||||
|
||||
find -D exec /lib/modules -maxdepth 1 \
|
||||
-mindepth 1 -type d \
|
||||
-exec sh -vxc \
|
||||
'if test -e "$1"/modules.dep;
|
||||
then kernel=$(basename "$1");
|
||||
dracut --verbose --force --kver "${kernel}";
|
||||
fi' sh {} \;
|
||||
|
||||
#. For SELinux, relabel filesystem on reboot::
|
||||
|
||||
fixfiles -F onboot
|
||||
|
||||
#. Generate host id::
|
||||
|
||||
zgenhostid -f -o /etc/hostid
|
||||
|
||||
#. Install locale package, example for English locale::
|
||||
|
||||
dnf install -y glibc-minimal-langpack glibc-langpack-en
|
||||
|
||||
#. Set locale, keymap, timezone, hostname
|
||||
|
||||
::
|
||||
|
||||
rm -f /etc/localtime
|
||||
systemd-firstboot \
|
||||
--force \
|
||||
--locale=en_US.UTF-8 \
|
||||
--timezone=Etc/UTC \
|
||||
--hostname=testhost \
|
||||
--keymap=us
|
||||
|
||||
#. Set root passwd
|
||||
::
|
||||
|
||||
printf 'root:yourpassword' | chpasswd
|
||||
|
||||
Bootloader
|
||||
---------------------------
|
||||
|
||||
|
||||
#. Apply GRUB workaround
|
||||
|
||||
::
|
||||
|
||||
echo 'export ZPOOL_VDEV_NAME_PATH=YES' >> /etc/profile.d/zpool_vdev_name_path.sh
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/profile.d/zpool_vdev_name_path.sh
|
||||
|
||||
# GRUB fails to detect rpool name, hard code as "rpool"
|
||||
sed -i "s|rpool=.*|rpool=rpool|" /etc/grub.d/10_linux
|
||||
|
||||
This workaround needs to be applied for every GRUB update, as the
|
||||
update will overwrite the changes.
|
||||
|
||||
#. RHEL uses Boot Loader Specification module for GRUB,
|
||||
which does not support ZFS. Disable it::
|
||||
|
||||
echo 'GRUB_ENABLE_BLSCFG=false' >> /etc/default/grub
|
||||
|
||||
This means that you need to regenerate GRUB menu and mirror them
|
||||
after every kernel update, otherwise computer will still boot old
|
||||
kernel on reboot.
|
||||
|
||||
#. Install GRUB::
|
||||
|
||||
mkdir -p /boot/efi/rocky/grub-bootdir/i386-pc/
|
||||
for i in ${DISK}; do
|
||||
grub2-install --target=i386-pc --boot-directory \
|
||||
/boot/efi/rocky/grub-bootdir/i386-pc/ "${i}"
|
||||
done
|
||||
dnf reinstall -y grub2-efi-x64 shim-x64
|
||||
cp -r /usr/lib/grub/x86_64-efi/ /boot/efi/EFI/rocky/
|
||||
|
||||
#. Generate GRUB menu::
|
||||
|
||||
mkdir -p /boot/grub2
|
||||
grub2-mkconfig -o /boot/grub2/grub.cfg
|
||||
cp /boot/grub2/grub.cfg \
|
||||
/boot/efi/efi/rocky/grub.cfg
|
||||
cp /boot/grub2/grub.cfg \
|
||||
/boot/efi/rocky/grub-bootdir/i386-pc/grub2/grub.cfg
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
::
|
||||
|
||||
find /boot/efis/ -name "grub.cfg" -print0 \
|
||||
| xargs -t -0I '{}' grub2-script-check -v '{}'
|
||||
|
||||
#. For both legacy and EFI booting: mirror ESP content::
|
||||
|
||||
espdir=$(mktemp -d)
|
||||
find /boot/efi/ -maxdepth 1 -mindepth 1 -type d -print0 \
|
||||
| xargs -t -0I '{}' cp -r '{}' "${espdir}"
|
||||
find "${espdir}" -maxdepth 1 -mindepth 1 -type d -print0 \
|
||||
| xargs -t -0I '{}' sh -vxc "find /boot/efis/ -maxdepth 1 -mindepth 1 -type d -print0 | xargs -t -0I '[]' cp -r '{}' '[]'"
|
||||
|
||||
#. Exit chroot
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
exit
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# nested chroot ends here
|
||||
ZFS_ROOT_NESTED_CHROOT
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
::
|
||||
|
||||
# list contents of boot dir to confirm
|
||||
# that the mirroring succeeded
|
||||
find "${MNT}"/boot/efis/ -type d > list_of_efi_dirs
|
||||
for i in ${DISK}; do
|
||||
if ! grep "${i##*/}-part1/efi\|${i##*/}-part1/EFI" list_of_efi_dirs; then
|
||||
echo "disk ${i} not found in efi system partition, installation error";
|
||||
cat list_of_efi_dirs
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
#. Unmount filesystems and create initial system snapshot
|
||||
You can later create a boot environment from this snapshot.
|
||||
See `Root on ZFS maintenance page <../zfs_root_maintenance.html>`__.
|
||||
::
|
||||
|
||||
umount -Rl "${MNT}"
|
||||
zfs snapshot -r rpool@initial-installation
|
||||
zfs snapshot -r bpool@initial-installation
|
||||
|
||||
#. Export all pools
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
zpool export -a
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# we are now inside a chroot, where the export will fail
|
||||
# export pools when we are outside chroot
|
||||
|
||||
#. Reboot
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
reboot
|
||||
|
||||
#. For BIOS-legacy boot users only: the GRUB bootloader installed
|
||||
might be unusable. In this case, see Bootloader Recovery section
|
||||
in `Root on ZFS maintenance page <../zfs_root_maintenance.html>`__.
|
||||
|
||||
This issue is not related to Alpine Linux chroot, as Arch Linux
|
||||
installed with this method does not have this issue.
|
||||
|
||||
UEFI bootloader is not affected by this issue.
|
||||
|
||||
.. ifconfig:: zfs_root_test
|
||||
|
||||
# chroot ends here
|
||||
ZFS_ROOT_GUIDE_TEST
|
||||
|
||||
Post installaion
|
||||
---------------------------
|
||||
|
||||
#. Install package groups
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
dnf group list --hidden -v # query package groups
|
||||
dnf group install gnome-desktop
|
||||
|
||||
#. Add new user, configure swap.
|
||||
@@ -71,16 +71,6 @@ And for EL8 and newer, separately run::
|
||||
dnf install -y kernel-devel
|
||||
dnf install -y zfs
|
||||
|
||||
It might be necessary to rebuild the ZFS modules::
|
||||
|
||||
for directory in /lib/modules/*; do
|
||||
kernel_version=$(basename $directory)
|
||||
dkms autoinstall -k $kernel_version
|
||||
done
|
||||
|
||||
If for some reason, the ZFS kernel modules are not successfully built,
|
||||
you can also run the above command to debug the problem.
|
||||
|
||||
.. note::
|
||||
When switching from DKMS to kABI-tracking kmods first uninstall the
|
||||
existing DKMS packages. This should remove the kernel modules for all
|
||||
@@ -126,8 +116,8 @@ time you can create such configuration in ``/etc/modules-load.d``::
|
||||
Previous minor EL releases
|
||||
--------------------------
|
||||
|
||||
The current release package uses `$releasever` rather than specify a particular
|
||||
minor release as previous release packages did. Typically `$releasever` will
|
||||
The current release package uses `"${releasever}"` rather than specify a particular
|
||||
minor release as previous release packages did. Typically `"${releasever}"` will
|
||||
resolve to just the major version (e.g. `8`), and the resulting repository URL
|
||||
will be aliased to the current minor version (e.g. `8.7`), but you can specify
|
||||
`--releasever` to use previous repositories. ::
|
||||
@@ -175,15 +165,13 @@ And for EL8 and newer::
|
||||
Use *zfs-testing* for DKMS packages and *zfs-testing-kmod*
|
||||
for kABI-tracking kmod packages.
|
||||
|
||||
RHEL-based distro Root on ZFS
|
||||
-------------------------------
|
||||
Start from "Preparation".
|
||||
|
||||
Root on ZFS
|
||||
-----------
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
RHEL-based distro Root on ZFS/*
|
||||
*
|
||||
|
||||
.. _kABI-tracking kmod: https://elrepoproject.blogspot.com/2016/02/kabi-tracking-kmod-packages.html
|
||||
.. _DKMS: https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support
|
||||
|
||||
Reference in New Issue
Block a user