root on ZFS on LUKS (on arch)
Mon 03 October 2016Update 2018-05-22: Inzwischen gibt es über archzfs fertige Pakete und Tools, alles hier ist vermutlich obsolet.
Mir fiel kürzlich ein Thinkpad T430 in die Hände. Da inzwischen natürlich sämtliche verbaute Hardware in den gängigen Linuxen einfach[tm] funktioniert muss ich halt mit Software basteln. Ausserdem fasst der Rechner zusätzlich zur SSD noch große Mengen drehenden Rost, daher der Wunsch nach einem ordentlichen Dateisystem.
Damit ich mich nächstes Jahr noch erinnere was ich da verbastelt habe, hier also mein kleines Rezept:
/ auf ZFS auf LUKS
Im Grunde wird dieser Artikel ein Mix aus folgenden Ressourcen. Ein Blick lohnt sich, vermutlich sind die Informationen dort ab nächster Woche aktueller als hier:
Installationsmedium
Überraschungsfrei: Image herunterladen (https://www.archlinux.org/download/), auf USB-Stick schreiben, von diesem booten. Man könnte jetzt schon die benötigten ZFS-Packages in ein eigenes Image bauen, ich machte das aber nachher im gebooteten Live-System. NB: Ich musste im BIOS einstellen das EFI-Boot vorgezogen wird, sonst wurde das Live-System im legacy-modus gestartet.
Live-System starten
Nach dem Boot vom Stick geht es wie gewohnt weiter:
Keyboard-Layout:
# loadkeys de-latin1
WIFI per netctl (netctl – ArchWiki):
# cp /etc/netctl/examples/wireless-wpa /etc/netctl/wifi
# vim /etc/netctl/wifi # Interface-Namen nicht vergessen!
# netctl start wifi
Ich machte die Installation von einem anderen Rechner aus per SSH, also sshd starten und ein Passwort für root setzen:
# systemctl start sshd.service
# passwd
Um den ganzen ZFS-Kram im Live-System installieren zu können braucht es etwas mehr "Platten"platz:
# mount -o remount,size=2G /run/archiso/cowspace
Partitionierung
Der Rechner kam mit Windows 7 auf legacy-partitionierter SSD. Aber das ist man ja schnell los:
# dd if=/dev/zero of=/dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06 status=progress
(NB: Wer noch in /dev/sdX denkt, ls -al /dev/disk/by-id gibt die Übersetzung dazu aus. Allzu viele Platten tummeln sich im Laptop ja auch üblicherweise nicht...)
Danach frische Partitionen anlegen:
# gdisk /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06
Wurde nicht die ganze Disk genullt: Auf die Nachfrage ob eine neue GPT erstellt werden soll ist die Antwort natürlich ja:
1 - Use current GPT
2 - Create blank GPT
Your answer: *2*
Command (? for help):
Ich lege auf der SSD 3 Partitionen an, EFI+/boot, Swap, ZFS-root.
Zuerst also die EFI-System-Partition, mit 2 GB Platz mehr als zu groß (Details: ESP – ArchWiki):
Command (? for help): n
Partition number (1-128, default 1): 1
First sector (34-250069646, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-250069646, default = 250069646) or {+-}size{KMGTP}: +2G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI System'
Als nächstes swap, ausreichend groß für hibernate, and them some:
Command (? for help): n
Partition number (2-128, default 2):
First sector (34-250069646, default = 4196352) or {+-}size{KMGTP}:
Last sector (4196352-250069646, default = 250069646) or {+-}size{KMGTP}: +32G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8200
Changed type of partition to 'Linux swap'
Den Rest des Platzes bekommt die ZFS-Partition, der Typ ist im Prinzip egal. Ich nehme bf00, Solaris root. Weil, warum nicht…
Und zuletzt das Dateisystem für die EFI System Partition:
# mkfs.fat -F32 /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part1
Crypto
Swap + ZFS-root werden vor der Dateisystem-Erzeugung verschlüsselt.
# cryptsetup luksFormat /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part2
# cryptsetup luksFormat /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part3
Und danach gleich wieder öffnen:
# cryptsetup luksOpen /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part2 crypt_swap
# cryptsetup luksOpen /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part3 crypt_zroot
Swapspace erstellen und einhängen:
# mkswap /dev/disk/by-id/dm-name-crypt_swap
# swapon /dev/disk/by-id/dm-name-crypt_swap
Installation von ZFS im Live-System
Um die ZFS-Module zu bauen braucht es ein wenig Vorbereitung. Zuerst das build-system installieren:
# pacman -Sy base-devel git kernel-headers
Mein Archiso-Image war schon ein paar Tage alt, daher habe ich mir die passenden Kernel-Header aus dem Arch Linux Archive holen müssen.
Build-User anlegen:
# useradd -m -s /bin/zsh build
# visudo # Da build kein Passwort hat bietet sich NOPASSWD an. ;)
Und dann mit diesem die Module holen und bauen:
# sudo -i -u build
% curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/spl-dkms.tar.gz
% tar xzf spl-dkms.tar.gz
% cd spl-dkms
% makepkg -dri
% cd ~
% curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/zfs-dkms.tar.gz
% tar xzf zfs-dkms.tar.gz
% cd zfs-dkms
% makepkg -dri
Nun kann ich ZFS laden und die Dateisysteme anlegen:
# modprobe zfs
# zpool create -f zroot /dev/disk/by-id/dm-name-crypt_zroot
# zfs create -o mountpoint=none zroot/data
# zfs create -o mountpoint=none zroot/ROOT
# zfs create -o compression=lz4 -o mountpoint=/ zroot/ROOT/default
# zfs create -o compression=lz4 -o mountpoint=/home zroot/data/home
Die dabei ausgegebenen Fehlermeldungen das die Dateisysteme nicht gemountet werden können sind zu erwarten. Es läuft ja noch das Livesystem...
Bootflag für das root-System:
# zpool set bootfs=zroot/ROOT/default zroot
Und den Pool unter /mnt für die Installation reimportieren:
# zpool export zroot
# zpool import -d /dev/disk/by-id -R /mnt zroot
Und das Cache-File ins Zielsystem kopieren:
# mkdir -p /mnt/etc/zfs
# cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache
Weiter geht es quasi mit der normalen Installationsprozedur:
# mkdir /mnt/boot
# mount /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part1 /mnt/boot
# pacstrap /mnt base base-devel linux-headers git vim
Danach einmal die fstab generieren lassen, und gleich wieder ausleeren, da die ZFS-Dateisysteme sowieso automatisch gemountet werden.
# genfstab -U /mnt >> /mnt/etc/fstab
# vim /mnt/etc/fstab
Übrig bleiben:
# cat /mnt/etc/fstab
zroot/ROOT/default / zfs rw,relatime,xattr,noacl0 0
UUID=C4E9-3C43 /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2
/dev/disk/by-id/dm-name-crypt_swap none swap defaults 0 0
Damit swap auch beim booten entschlüsselt wird:
# echo "crypt_swap /dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part2 none luks" >> /mnt/etc/crypttab
Zeit für den Wechsel ins zu installierende System:
# arch-chroot /mnt
[root@archiso /]#
Und weiter mit der Installation nach Handbuch:
# vi /etc/locale.gen
# locale-gen
# ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime
# hwclock --systohc --utc
# echo LANG=en_US.UTF-8 > /etc/locale.conf
# echo KEYMAP=de-latin1 > /etc/vconsole.conf
# echo euterpe.zknt.org > /etc/hostname
# echo 127.0.0.1 euterpe euterpe.zknt.org >> /etc/hosts
# pacman -S netctl wpa_supplicant # netctl-profil kann aus dem live-system kopiert werden
(nochmal) ZFS installieren
Im Zielsystem müssen auch nochmal die zfs-packages installiert werden, gleiche Anleitung wie oben. Ob nochmal mit build-User oder ob gleich der richtige Nutzeraccount angelegt wird ist Geschmackssache...
initrd und bootloader
Als letzte Schritte sind noch init und der bootloader zu konfigurieren.
Zuerst den Bootloader installieren:
# bootctl --path=/boot install
# echo -e "default arch\ntimeout 3\neditor 1" > /boot/loader/loader.conf
Wenn hinterher alles funktioniert kann editor hier auf 0 gesetzt werden. Erstmal bleibt er zur Sicherheit an.
Und /boot/loader/entries/arch.conf entsprechend anpassen:
# cat /boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options cryptdevice=/dev/disk/by-id/ata-C400-MTFDDAK128MAM_00000000122603410E06-part3:crypt_zroot zfs=
bootfs zfs=zroot rw
mkinitcpio.conf anpassen:
# vi /etc/mkinitcpio.conf
...
HOOKS="base udev autodetect modconf block encrypt zfs filesystems keyboard fsck"
...
# mkinitcpio -p linux
Zeit fürs Root-Passwort setzen und Neustart!
# passwd
# exit
# umount /mnt/boot
# zfs umount -a
# zpool export zroot
# reboot
Nach dem ersten Boot # zpool set cachefile=/etc/zfs/zpool.cache zroot # systemctl enable zfs.target