Привет! Меня зовут Денис, я 3D-художник и Linux-энтузиаст. Более 8 лет Arch Linux является моей основной и единственной операционной системой. Мне не удалось найти ни одного приличного гайда по установке Arch на ZFS. Где-то была устаревшая информация, где-то использовался плохо подходящий для ZFS GRUB, где-то ядро ставилось на FAT. Хороший повод написать новый гайд.
Почему ZFS? Однажды я решил собрать stripe (RAID0) на ноутбуке с двумя дисками. Хотелось сохранить привычную структуру директорий и не думать о том, на каком диске что лежит.
На тот момент я уже использовал ZFS на файловом сервере, а на ноутбуках - Btrfs + LUKS2. Загрузить Arch Linux с RAID на Btrfs у меня не получилось. С ZFS, напротив, не возникло никаких трудностей.
Почему страйп а не зеркало? Ноутбук ношу с собой, ноутбук можно потерять, забыть в кафе, ноутбуки воруют. Все важное в любом случае бекапится на сервер, поэтому избыточность на ноутбуке мне не нужна. На сервере ZFS, поэтому Btrfs на ноутбуке мне не подходит.
Задача:
ZFS stripe из двух дисков
Полное шифрование
Ядро на ZFS
Установочный образ archiso не имеет поддержки ZFS. Нам придётся добавить zfs модуль в archiso самостоятельно.
Ставим пакет archiso и копируем дефолтный профиль для дальнейшего редактирования.
pacman -Syu archiso cp -r /usr/share/archiso/configs/releng/ ~/archlive
Из файла ~/archlive/packages.x86_64 удаляем linux и broadcom-wl и добавляем пакеты:
linux-lts linux-lts-headers libunwind zfs-utils zfs-dkms
В ~/archlive/pacman.conf добавляем репозиторий archzfs:
[archzfs] SigLevel = Never Server = https://github.com/archzfs/archzfs/releases/download/experimental
Ставим LTS ядро для лучшей совместимости с ZFS. Заменяем vmlinuz-linux и initramfs-linux.img на vmlinuz-linux-lts и initramfs-linux-lts.img в следующих конфигах:
archlive/airootfs/etc/mkinitcpio.d/linux.preset archlive/efiboot/loader/entries/01-archiso-linux.conf archlive/syslinux/archiso_sys-linux.cfg archlive/grub/loopback.cfg archlive/grub/grub.cfg
Собираем образ. Затем пишем на флешку и грузимся.
mkdir isobuild mkarchiso -v -r -w /tmp/archiso-tmp -o isobuild ~/archlive
На дисках создаём таблицу разделов GPT и следующую разметку:
nvme0n1p1 - 256 Mb - EFI System
nvme0n1p2 - всё свободное место - Solaris Root
nvme1n1p1 - весь диск - Solaris Root
Тут подойдет любая программа для разметки диска, например cfdisk.
На EFI-разделе будет находиться только загрузчик ZFSBootMenu, поэтому большой раздел нам не нужен. Ядро и система будут храниться непосредственно на ZFS.
Создаем ZFS пул:
zpool create -f -o ashift=12 \
-O acltype=posixacl \
-O relatime=on \
-O xattr=sa \
-O dnodesize=auto \
-O normalization=formD \
-O mountpoint=none \
-O canmount=off \
-O devices=off
-o autotrim=on \
-R /mnt \
-O compression=lz4 \
-O encryption=aes-256-gcm \
-O keyformat=passphrase \
-O keylocation=prompt \
zroot /dev/nvme0n1p2 /dev/nvme1n1p1
Несколько важных опций:
compression=lz4- практически бесплатное сжатиеencryption=aes-256-gcm- встроенное шифрование ZFSkeyformat=passphrase- парольная фразаkeylocation=prompt- пароль вводится при загрузке
Создаем датасеты:
zfs create -o mountpoint=none zroot/data zfs create -o mountpoint=none zroot/ROOT zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/default zfs create -o mountpoint=/home zroot/data/home
После создания датасетов необходимо заново импортировать пул:
zpool export zroot zpool import -d /dev/nvme0n1p2 -R /mnt zroot -N zfs load-key zroot zfs mount zroot/ROOT/default zfs mount -a
Указываем загрузочный датасет:
zpool set bootfs=zroot/ROOT/default zroot
Монтируем EFI раздел для загрузчика:
mkdir -p /mnt/efi mkfs.vfat -F32 -n EFI /dev/nvme0n1p1 mount /dev/nvme0n1p1 /mnt/efi
Ставим базовую систему:
pacstrap /mnt base linux-lts linux-lts-headers neovim base-devel iwd sudo
Генерируем fstab:
genfstab -U -p /mnt > /mnt/etc/fstab
После этого удаляем из /mnt/etc/fstab всё, кроме EFI-раздела. ZFS монтируется самостоятельно.
Чрутимся:
arch-chroot /mnt
Добавляем archzfs репозиторий в /etc/pacman.conf:
[archzfs] Server = https://github.com/archzfs/archzfs/releases/download/experimental Server = https://mirrors.uni-plovdiv.net/archzfs/experimental
Добавляем ключ:
pacman-key --init pacman-key --recv-keys 3A9917BF0DED5C13F69AC68FABEC0A1208037BE9 pacman-key --lsign-key 3A9917BF0DED5C13F69AC68FABEC0A1208037BE9
Ставим ZFS:
pacman -S zfs-utils zfs-dkms
ZFS модули привязаны к определённой версии ядра. Если при обновлении ядра модули не собираются, ядро необходимо откатить и подождать, пока обновятся модули.
Альтернатива - использовать репозитории CachyOS, где есть ядра со встроенной поддержкой ZFS. Последние полгода я использую linux-cachyos-zfs.
Редактируем /etc/mkinitcpio.conf.
Добавляем модуль:
MODULES=(zfs)
Правим HOOKS:
HOOKS=(base udev ... keyboard zfs filesystems)
Пересобираем initramfs:
mkinitcpio -P
Важно:
zfsдолжен идти передfilesystemskeyboard- передzfsесли используется
systemd, его нужно заменить наbase udev
Базовая настройка системы:
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen locale-gen echo "LANG=en_US.UTF-8" > /etc/locale.conf echo "KEYMAP=us" > /etc/vconsole.conf echo "somename" > /etc/hostname zgenhostid $(hostid)
Только ZFSBootMenu умеет нормально грузить ядро с ZFS, так что выбор загрузчика очевиден.
Скачиваем загрузчик:
mkdir -p /efi/EFI/zbm wget https://get.zfsbootmenu.org/latest.EFI -O /efi/EFI/zbm/zfsbootmenu.EFI
Создаём EFI-запись:
efibootmgr --disk /dev/nvme0n1 --part 1 --create --label "ZFSBootMenu" --loader '\EFI\zbm\zfsbootmenu.EFI' --unicode "spl_hostid=$(hostid) zbm.timeout=3 zbm.prefer=zroot zbm.import_policy=hostid" --verbose
Важно:
--disk /dev/nvme0n - диск, где находится загрузчик
--part 1 - номер раздела на этом диске
Параметры загрузки ядра:
zfs set org.zfsbootmenu:commandline="noresume init_on_alloc=0 rw spl.spl_hostid=$(hostid) zswap.enabled=0" zroot/ROOT
Параметр zswap.enabled=0 нужен если планируется использовать zram.
Проверяем:
zfs get org.zfsbootmenu:commandline zroot/ROOT
Включаем сервисы ZFS:
systemctl enable zfs.target systemctl enable zfs-import.target systemctl enable zfs-volumes.target systemctl enable zfs-import-scan.service
Настраиваем zfs-mount-generator:
mkdir /etc/zfs/zfs-list.cache ln -s /usr/lib/zfs/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d systemctl enable zfs-zed.service touch /etc/zfs/zfs-list.cache/zroot
Создаём пароль root:
passwd
Создаём пользователя:
useradd -m -G wheel username passwd username
Разрешаем sudo. Добавляем в /etc/sudoers:
%wheel ALL=(ALL) ALL
Завершаем установку:
exit umount /mnt/efi zfs umount -a zpool export zroot
Настройка после установки.
Чтобы не вводить пароль дважды при загрузке, можно добавить ключ в initramfs.
Создаём файл ключа:
echo '' > /etc/zfs/zroot.key chmod 000 /etc/zfs/zroot.key zfs set keylocation=file:///etc/zfs/zroot.key zroot
Добавляем ключ в /etc/mkinitcpio.conf:
FILES=(/etc/zfs/zroot.key)
Пересобираем initramfs:
mkinitcpio -P
Проверяем:
zfs get keylocation,keyformat zroot