Arch auf ZFS
Dieser Artikel beschreibt die Schritte, um Arch Linux auf einem verschlüsselten ZFS-Dateisystem zu installieren.
Anmerkung zu dieser Anleitung
Da Grub der OpenZFS-Entwicklung hinterher hängt, müssen einige Funktionen von ZFS auf dem Pool, von dem GRUB booten wird, deaktiviert werden. Daher ist es ratsam einen seperaten Pool zu erstellen der auf /boot gemountet wird.
Momentan behandelt diese Anleitung ausschließlich booten via EFI . Außerdem wird der ZFS-root-Pool verschlüsselt.
Siehe #Todo.
Warnung: Die Befehle in diesem Wiki blind zu kopieren wird gegebenenfalls nur eingeschränkt zu einem funktionstüchtigen System führen. Es ist notwendig sich die Zeit zu nehmen den Boot-Prozess, ZFS-Pools und -Datasets zu verstehen. Hier gibt es einige Links zum Nachschlagen: #Weblinks
Vorbereitung
Allgemeines
Das neueste ISO-Abbild kann von der Arch-Linux Downloadseite heruntergeladen werden.
Das ISO-Abbild beinhaltet nur die nötigen Programme, um ein minimales GNU/Linux Grundsystem zu installieren. Als Nächstes muss das ISO-Abbild geprüft und auf eine CD/DVD gebrannt oder einen USB-Stick übertragen werden (Anleitung für Einsteiger). Nach dem Booten von CD/DVD/USB-Stick muss eine Internetverbindung hergestellt werden (Ethernet/WLAN).
Zuerst wird die Tastaturbelegung geändert:
loadkeys de
Sollte eine WLAN-Verbindung aufgebaut werden, kann dies mit iwd erfolgen:
iwctl devices list station <device> scan station <device> get-networks station <device> connect <ssid>
Hierbei muss <device> und <ssid> entsprechend ersetzt werden.
ZFS Modul nachladen
Neben der, unten erörterten Möglichkeit, ein selbsterstelltes archiso mit integriertem ZFS zu erstellen, wird hier das ZFS-Modul mithilfe eines Skripts in die laufende archiso-Instanz nachgeladen. Für Details siehe https://github.com/eoli3n/archiso-zfs .
curl -s https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init | bash
Alternativ: ISO-Datei mit integriertem ZFS erstellen
Hier wird auf einer bestehenden Arch-Linux-Installation gearbeitet.
Vorbereitung
Installation des archiso-Pakets:
sudo pacman -S archiso
Als Basis für das Abbild wird das bestehende Profil "releng" (mit welchem auch die offiziellen monatlichen ISO-Dateien erstellt werden) herhalten. Hierzu wird das Profil in ein für uns beschreibbares Verzeichnis kopiert (zum Beispiel unser home-Verzeichnis):
cp -r /usr/share/archiso/configs/releng archisozfs cd archisozfs
Modifikation der Konfiguration
Als Erstes wird in der pacman.conf
-Datei im archisozfs
-Verzeichnis das archzfs-Repository eingefügt (an den bisherigen Inhalt anhängen):
[archzfs] Server = http://archzfs.com/$repo/x86_64 SigLevel = Optional TrustAll
Nun wird in der packages.x86_64
-Datei das entsprechende Paket eingefügt (ebenfalls an den bestehenden Inhalt anhängen):
archzfs-linux
pacman.conf mit archzfs-Repository ins Image einfügen
Zuerst wird die aktuelle pacman.conf in das Image eingefügt:
cp /etc/pacman.conf ./airootfs/etc
Sollte diese das archzfs-Repository noch nicht enthalten, wird auch dieses an das Ende von ./airootfs/etc/pacman.conf
angefügt:
[archzfs] Server = http://archzfs.com/$repo/x86_64 SigLevel = Optional TrustAll
Optional: ISO-Metadaten anpassen
Wenn gewünscht, können die Metadaten dieses Profils in der Datei profiledef.sh
angepasst werden. Hier ein Beispiel wie die geänderten Zeilen aussehen könnten:
iso_name="archlinux-zfs" iso_publisher="Ein Name <mail@adresse.de>" iso_application="Arch Linux Live/Rescue CD with integrated ZFS"
ISO-Datei bauen
Zuerst muss das Arbeitsverzeichnis vorbereitet werden, in welchem mkarchiso
die in der ISO-Datei benötigten Pakete herunterladen, vorbereiten etc. wird:
mkdir work
Als Nächstes wird das Bauen der ISO-Datei angestoßen (dies kann je nach Hardware eine ganze Zeit dauern und benötigt auch etwas freie Festplattenkapazität):
sudo mkarchiso -v -w ./work .
Hier steht -v
für verbose (detailierte Ausgabe), -w
für den Pfad zum Arbeitsverzeichnis und .
für den Pfad zum Profil. Optional kann mit -o
ein Ausgabe-Pfad für die ISO-Datei angegeben werden. Falls kein Ausgabe-Pfad angegeben wird, wird die ISO-Datei in den Ordner out
geschrieben.
Test der ISO-datei
Falls auf dem Computer die Pakete edk2-ovmf
und qemu
installiert sind, kann die erstellte ISO in einer virtuellen Umgebung getestet werden:
run_archiso -i ./out/datei.iso -u
Hier muss datei.iso
mit dem tatsächlichen Namen der ISO-Datei ersetzt werden (abhängig von den im Profil definierten Name und des Datums ändert sich der Name). -i
bewirkt, dass im Testvorgang via UEFI gebootet wird.
Aufräumen des Arbeitsverzeichnis
Zuletzt kann das Arbeitsverzeichnis wieder gelöscht werden (bitte darauf achten, dass dies im richtigen Verzeichnis ausgeführt wird):
sudo rm -rf ./work
Partitionierung
ZFS unterstützt sowohl GTP als auch MBR Partitionstabellen und verwaltet seine Partitionen selbst. Daher wird nur eine minimale Partitionstabelle benötigt.
Die Trennung zwischen der 1 GB Partition für /boot
und der restlichen Größe für /
ist dem geschuldet, dass GRUB2 nicht alle Feature/Funktionen von ZFS unterstützt.
Alternativen wären entweder GRUB nicht auf einem ZFS-Pool zu installieren (was dazu führt, dass von /boot
keine Snapshots angefertigt werden können und evtl. auch nicht von alten Snapshots gebootet werden kann) oder auf dem Wurzeldateisystem /
auf viele ZFS-Funktionen zu verzichten. Da beides nicht wünschenswert ist, werden hier 2 ZFS-Pools erstellt; einen mit eingeschränkten Features für GRUB und ein Pool mit allen ZFS-Features für das restliche Dateisystem.
Für Festplatten welche größer als 2 TB sind, wird eine GPT-Partitionstabelle benötigt.
In dieser Anleitung wird folgendes Partitionsschema benutzt:
Part Size Type ---- ---- ------------------------------- 1 1G EFI System (ef00) 2 1G Solaris /usr & Apple ZFS (BF01) 3 XXXG Solaris Root (bf00)
Für die Arbeit mit ZFS müssen die Festplatten/Partitionen anstatt mit Festplatten-Identifiern wie /dev/sdX
mit der ID angesprochen werden /dev/disk/by-id
.
Die Zuordnung zwischen beiden Adressierungsmöglichkeiten kann durch
ls -la /dev/disk/by-id
eingesehen werden.
Um die Arbeit zu erleichtern, wird der entsprechende Pfad in einer Variable gespeichert:
DISK=/dev/disk/by-id/<DISK>
Warnung: Alle auf der Festplatte gespeicherten Daten gehen verloren.
Die Partitionierung kann nach o.g. Tabelle einfach in cfdisk angelegt werden.
Alternativ kann das Partitionsschema wie folgt angelegt werden:
sgdisk --zap-all $DISK sgdisk -n1:1M:+1G -t1:EF00 $DISK sgdisk -n2:0:+1G -t2:BF01 $DISK sgdisk -n3:0:0 -t3:BF00 $DISK
Sollten früher bereits ZFS-Pools auf der Festplatte angelegt worden sein, kann es nötig sein die ersten und letzten Sektoren der Festplatte zu überschreiben.
Pool-Erstellung
Empfehlung
Für eine einfacherer Verwaltbarkeit mehrerer Festplatten (wenn man z.B. eine andere Festplatte mit weiteren ZFS-Pools anschließt), kann es ratsam sein anstatt der generischen Namen rpool
und bpool
eine zufällige ID anzuhängen, z.B. rpool_f6231d
. Dann ist es später möglich einen anderen ZFS-Pool einfach zu importieren ohne diesen umbenennen zu müssen. Für die Einfachheit und Übersichtlichkeit wird in diesem Artikel darauf verzichtet.
Pool: bpool
Dieser Pool dient hauptsächlich für die spätere Bereitstellung von /boot
. Hier können nur gewisse ZFS-Features aktiviert werden, da viele Features noch nicht von GRUB2 unterstützt werden.
zpool create \ -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=none -R /mnt \ bpool ${DISK}-part2
Pool: rpool
Dieser Pool wird später zur Bereitstellung des von /
genutzt werden. Hier werden alle Daten gespeichert (außer die zum Starten benötigten Verzeichnisse /boot
und /boot/efi
liegen). Dieser nutzt als Komprimierung lz4. Für eine höhere Komprimierungsrate bei niedrigerer Performance kann zum Beispiel auch zstd
genutzt werden. Weitere Informationen zu Komprimierung und Performance findet sich bei Fermilab .
Verschlüsselter rpool
Wird ein verschlüsselter Pool gewünscht, kann dieser wie folgt angelegt werden (empfohlen):
zpool create \ -o ashift=12 \ -O encryption=aes-256-gcm \ -O keylocation=prompt -O keyformat=passphrase \ -O acltype=posixacl -O canmount=off -O compression=lz4 \ -O dnodesize=auto -O normalization=formD -O relatime=on \ -O xattr=sa -O mountpoint=none -R /mnt \ rpool ${DISK}-part3
Alternativ: Nicht verschlüsselter rpool
Sollte keine Verschlüsselung auf dem Pool gewünscht sein, kann dieser wie folgt angelegt werden (ohne die folgenden Dateisystemeigenschaften, welche durch -O
spezifiziert werden: encryption
, keylocation
und keyformat
).
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=none -R /mnt \ rpool ${DISK}-part3
Dataset-Erstellung
Nun werden die Datasets erstellt. Die hier erstellten Datasets sind ein bisheriges "Best practice" und kann je nach Anforderungen angepasst werden.
Die hier vorgeschlagene Struktur sollte zu biaz und rozb3-pac kompatibel sein. Geprüft wurde dies vom Autor aber nicht.
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/default zfs create -o canmount=on -o mountpoint=/boot bpool/BOOT/default
zfs create -o canmount=off -o mountpoint=none rpool/HOME zfs create -o canmount=on -o mountpoint=/home rpool/HOME/default
zfs create -o canmount=on rpool/ROOT/default/usr zfs create -o canmount=on rpool/ROOT/default/var
zfs create -o canmount=on rpool/ROOT/default/usr/local zfs create -o canmount=on rpool/ROOT/default/var/log zfs create -o canmount=on rpool/ROOT/default/var/spool zfs create -o canmount=on rpool/ROOT/default/var/tmp
Nachträgliche Änderungen von Optionen
Sollten nachträgliche Anpassungen an Optionen wie zum Beispiel canmount
und mountpoint
notwendig sein, sind folgende Befehle hilfreich:
Beispiel: Auslesen der Option
zfs get mountpoint rpool/ROOT/default
Beipsiel: Setzen der Option
zfs set mountpoint=/ rpool/ROOT/default
Prüfung der Pools und Datasets
Nun werden die Pools einmal exportiert und wieder importiert um die Korrektheit zu prüfen:
zpool export rpool zpool export bpool
zpool import -R /mnt -N rpool zpool import -R /mnt -N bpool
Hierbei dient -R
dazu die angegebenen Mountpoints unter /mnt
anstatt /
einzuhängen und -N
verhindert ein automatisches mounten.
Nun muss die Verschlüsselung geöffnet werden (sofern diese denn beim anlegen des Pools aktiviert wurde):
zfs load-key rpool
Anschließend können wir die Partitionen mounten:
zfs mount rpool/ROOT/default zfs mount -a
Eine Auflistung, ob alle Mountpoints gemountet wurden, kann wie folgt stattfinden:
zfs mount
Um die Auflistung etwas übersichtlicher zu machen, kann auch folgender Befehl genutzt werden
zfs mount | column -t
Nun werden die Berechtigungen für /var/tmp
noch gesetzt:
chmod 1777 /mnt/var/tmp
Vorbereitung der EFI-Partition
Nun wird eine FAT-Partition für /boot/efi
erstellt und gemountet.
mkfs.vfat -n EFI $DISK-part1 mkdir /mnt/boot/efi mount $DISK-part1 /mnt/boot/efi
Arch-Installation
Diese Installation ist exemplarisch und enthält einige persönliche Preferenzen. Für weitere Informationen: #Siehe auch.
pacstrap
Nun findet, fast wie gewohnt, die Installation via pacstrap
statt:
pacstrap /mnt base base-devel linux-firmware linux linux-headers neovim nano grub efibootmgr \ sudo man networkmanager tmux zsh zsh-completions wget git rsync pacman-contrib pacstrap /mnt archzfs-dkms
Neben der DKMS-Variante, kann auch
linux-lts archzfs-linux-lts
oder linux archzfs-linux
genutzt werden. Hier kann es allerdings Probleme beim Aktualisieren des Systems geben, wenn ein neuer Linux-Kernel veröffentlicht wurde, welcher von archzfs noch nicht unterstützt wird. Hier würde dann bis zum Erscheinen ein --ignore linux-lts,linux-lts-headers,zfs-linux-lts
beim Aktualisieren helfen.
Bei der DKMS-Variante wird das ZFS-Modul automatisch neu gebaut, wenn ein neuer Kernel installiert wird. Dies braucht zum einen mehr Zeit bei Updates, aber kann natürlich auch zu Problemen führen wenn nicht-kompatible Änderungen im neuen Kernel enthalten sind.
Anmerkung zur ISO-Datei mit integriertem ZFS
Sofern die pacman.conf-Datei welche in die ISO-Datei gebaut wird, nicht angepasst wurde, muss das archzfs-Repository von nochmals in der Datei /etc/pacman.conf
eingefügt werden:
[archzfs] Server = http://archzfs.com/$repo/x86_64 SigLevel = Optional TrustAll
pacman.conf
Nun kopieren wir die bereits für archzfs angepasste pacman.conf-Datei:
cp /etc/pacman.conf /mnt/etc/pacman.conf
genfstab
Als nächstes wird die fstab-Datei generiert.
genfstab /mnt > /mnt/etc/fstab
Hierbei ist es wichtig in der generierten Datei alle Zeilen bis auf die /boot/efi
-Zeile zu entfernen:
vim /mnt/etc/fstab
arch-chroot
Jetzt wechseln wird in das neu installierte System gewechselt:
arch-chroot /mnt
Standard-Schritte
An dieser Stelle sollten die Standard-Installationsschritte wie Passwort-Änderung, Benutzererstllung, locale-gen, Zeitzoneneinstellungen etc. erfolgen.
Dies wird in dieser Anleitung nicht explizit erörtert.
mkinitcpio.conf
Nun wird die HOOKS
-Zeile der Datei /etc/mkinitcpio.conf
wie folgt angepasst:
HOOKS=(base udev autodetect modconf block keyboard zfs filesystems)
Als nächstes wird die ramdisk erstellt:
mkinitcpio -P
zpool.cache
Um die Pools später automatisch einbinden zu lassen wird die Datei /etc/zfs/zpool.cache
benötigt.
Diese wirde wie folgt für die Pools generiert:
zpool set cachefile=/etc/zfs/zpool.cache rpool zpool set cachefile=/etc/zfs/zpool.cache bpool
ZFS-Dienste/Targets aktivieren
Als nächstes aktivieren wir die benötigten systemd-Dienste/Targets:
systemctl enable zfs-import-cache zfs-import.target zfs-mount zfs-zed zfs.target
GRUB
default-Datei
Zuerst passen wir in der Datei /etc/default/grub
folgende Zeile an:
GRUB_CMDLINE_LINUX="root=ZFS=rpool/ROOT/default"
Installation
Die GRUB-Installation/-Konfiguration schlägt mit dem Fehler error: failed to get canonical path of
fehl.
Um dies zu umgehen muss die Umgebungsvariable ZPOOL_VDEV_NAME_PATH=1
gesetzt sein.
Daher wird folgender Befehl ausgeführt:
ZPOOL_VDEV_NAME_PATH=1 grub-install
Konfiguration
Als nächstes wird die Konfiguration für GRUB erstellt:
ZPOOL_VDEV_NAME_PATH=1 grub-mkconfig -o /boot/grub/grub.cfg
Boot
Nun kann in das neue System gebootet werden und die weitere Einrichtung von dort erfolgen.
Es empfiehlt sich dazu nach dem Verlassen der chroot:
exit
und vor dem Neustart die Installationspfade auszuhängen und die ZFS Pools zu exportieren:
umount /mnt/boot/efi zfs umount -a zpool export rpool zpool export bpool
reboot
Snapshot
Um einen Snapshot von der initialen Grundinstallation zu haben werden folgende Befehle ausgeführt:
zfs snapshot -r rpool@install zfs snapshot -r bpool@install
-r
steht hier für eine rekursive Durchführung der Snapshots auf den untergeordneten Datasets.
Die bestehenden Snapshots können mit
zfs list -t snapshot
aufgelistet werden.
Troubleshooting
ISO-Erstellung: Fehler "Could not statisfy dependency 'linux[...]' required by zfs-linux
Falls beim Ausführen die hierstehende oder ähnliche Fehlermeldung auftritt, gibt es noch keine Veröffentlichung von archzfs-linux welche zu dem aktuellen Kernel (linux-Paket) passt.
error: failed to prepare transaction (could not satisfy dependencies) :: unable to satisfy dependency 'linux=5.10.8.arch1-1' required by zfs-linux
Eine Alternative ist dann in packages.x86_64
den Eintrag archzfs-linux
mit archzfs-dkms
zu ersetzen.