Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/Getting Started/Alpine Linux/Alpine Linux Root on ZFS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Alpine Linux Root on ZFS
========================
`Start here <Root%20on%20ZFS/1-preparation.html>`__.

Contents
--------
.. toctree::
:maxdepth: 2
:glob:

Root on ZFS/*
84 changes: 84 additions & 0 deletions docs/Getting Started/Alpine Linux/Root on ZFS/1-preparation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
.. highlight:: sh

Preparation
======================

.. contents:: Table of Contents
:local:

#. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled.
#. Download latest extended variant of `Alpine Linux live image
<https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/>`__ and boot from it.
#. Login as root user. There is no password.
#. Configure Internet::

setup-interfaces -r
# example:
network interface: wlan0
WiFi name: <ssid>
ip address: dhcp
<enter done to finish network config>
manual netconfig: n

#. Configure SSH server::

setup-sshd
# example:
ssh server: openssh
allow root: "prohibit-password" or "yes"
ssh key: "none" or "<public key>"

Configurations set here will be copied verbatim to the installed system.

#. Set root password or ``/root/.ssh/authorized_keys``.

#. Connect from another computer::

ssh root@192.168.1.19

#. Throughout this guide, we use predictable disk names generated by udev::

apk add eudev
setup-udev

It can be removed after reboot with ``setup-devd mdev && apk del eudev``.

#. Target disk

List available disks with::

ls /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'

#. Configure NTP client for time synchronization::

setup-ntp chrony

#. Pick a mirror from `Alpine Mirrors <https://mirrors.alpinelinux.org/>`__
and add it to package manager configuration::

tee -a /etc/apk/repositories <<EOF
https://dl-5.alpinelinux.org/alpine/latest-stable/community/
https://dl-5.alpinelinux.org/alpine/latest-stable/main/
EOF

#. Install ZFS support and partition tool::

apk update
apk add zfs zfs-lts sgdisk e2fsprogs
modprobe zfs

Many errors about firmware will appear. They are safe to ignore.

#. Install bootloader for both legacy boot and UEFI::

apk add grub-bios grub-efi
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
.. highlight:: sh

System Installation
======================

.. contents:: Table of Contents
:local:

#. Partition the disks::

for i in ${DISK}; do

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

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
done

#. Probe new partitions::

for i in ${DISK}; do
partprobe $i
done
udevadm settle
sync

#. Create boot partition::

for i in ${DISK}; do
mkfs.ext4 -F $i-part2
done

#. 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``.

#. This section implements dataset layout as described in `overview <1-preparation.html>`__.

Create root system container:

- Unencrypted::

zfs create \
-o canmount=off \
-o mountpoint=none \
rpool/alpine

- Encrypted::

zfs create \
-o canmount=off \
-o mountpoint=none \
-o encryption=on \
-o keylocation=prompt \
-o keyformat=passphrase \
rpool/alpine

#. Create datasets::

zfs create -o canmount=on -o mountpoint=/ rpool/alpine/root
zfs create -o canmount=on -o mountpoint=/home rpool/alpine/home
zfs create -o canmount=off -o mountpoint=/var rpool/alpine/var
zfs create -o canmount=on rpool/alpine/var/lib
zfs create -o canmount=on rpool/alpine/var/log

#. Mount /boot::

mkdir -p /mnt/boot
mount -t ext4 $(echo $DISK | cut -f1 -d\ )-part2 /mnt/boot/

#. Format and mount ESP::

mkdir -p /mnt/boot/efi
mount -t vfat $(echo $DISK | cut -f1 -d\ )-part1 /mnt/boot/efi

#. By default ``setup-disk`` command does not support zfs and will refuse to run,
add zfs support::

sed -i 's|supported="ext|supported="zfs ext|g' /sbin/setup-disk

#. Workaround for GRUB to recognize predictable disk names::

export ZPOOL_VDEV_NAME_PATH=YES

#. Install system to disk::

BOOTLOADER=grub setup-disk -v /mnt

GRUB installation will fail and will be reinstalled later.

#. Chroot::

m='/dev /proc /sys'
for i in $m; do mount --rbind $i /mnt/$i; done

chroot /mnt /usr/bin/env DISK=$DISK sh

#. 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

sed -i "s|rpool=.*|rpool=rpool|" /etc/grub.d/10_linux

sed -i 's|stat -f -c %T /|echo zfs|' /usr/sbin/grub-mkconfig

This workaround needs to be applied for every GRUB update, as the
update will overwrite the changes.

#. Generate GRUB menu::

grub-mkconfig -o /boot/grub/grub.cfg

#. Rebuild initrd::

mkdir -p /etc/zfs
rm -f /etc/zfs/zpool.cache
touch /etc/zfs/zpool.cache
chmod a-w /etc/zfs/zpool.cache
chattr +i /etc/zfs/zpool.cache

sed -i 's|zfs|nvme zfs|' /etc/mkinitfs/mkinitfs.conf
for directory in /lib/modules/*; do
kernel_version=$(basename $directory)
mkinitfs $kernel_version
done

#. Enable dataset mounting at boot::

rc-update add zfs-mount sysinit

#. Replace predictable disk path with traditional disk path:

For SATA drives::

sed -i 's|/dev/disk/by-id/ata-.*-part|/dev/sda|' /etc/fstab

For NVMe drives::

sed -i 's|/dev/disk/by-id/nvme-.*-part|/dev/nvme0n1p|' /etc/fstab

#. Mount datasets with zfsutil option::

sed -i 's|,posixacl|,zfsutil,posixacl|' /etc/fstab

#. Install GRUB::

export ZPOOL_VDEV_NAME_PATH=YES
for i in ${DISK}; do
grub-install --target=i386-pc $i
done
grub-install --target x86_64-efi --bootloader-id alpine --removable

#. Unmount filesystems::

exit
cut -f2 -d\ /proc/mounts | grep ^/mnt | tac | while read i; do umount -l $i; done
zpool export -a

#. Reboot::

poweroff

Disconnect the live media and other non-boot storage devices.
Due to missing support of predictable device names in initrd,
Alpine Linux will mount whichever disk appears to be /dev/sda or /dev/nvme0
at /boot and /boot/efi at boot.

Root filesystem at / is ZFS and imported via pool name thus not affected by the above restriction.

#. Post-install:

#. Setup mirroring of /boot partition and /boot/efi via dd.
#. Setup swap.
38 changes: 38 additions & 0 deletions docs/Getting Started/Alpine Linux/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Alpine Linux
============

Contents
--------
.. toctree::
:maxdepth: 1
:glob:

*

Installation
------------

Note: this is for installing ZFS on an existing Alpine
installation. To use ZFS as root file system,
see below.

#. Install ZFS package::

apk add zfs zfs-lts

#. Load kernel module::

modprobe zfs

Root on ZFS
-----------
ZFS can be used as root file system for Fedora.
An installation guide is available.

`Start here <Root%20on%20ZFS/1-preparation.html>`__.

.. toctree::
:maxdepth: 1
:glob:

Root on ZFS/*
1 change: 1 addition & 0 deletions docs/Getting Started/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ documentation <https://pthree.org/2012/04/17/install-zfs-on-debian-gnulinux/>`__
:maxdepth: 3
:glob:

Alpine Linux/index
Arch Linux/index
Debian/index
Fedora/index
Expand Down