Arch Linux на ZFS для людей: новый TUI-установщик archinstall_zfs
Установка Arch Linux на ZFS всегда была не очень тривиальным делом: нужно знать много тонкостей, прочитать кучу статей и различные вики, разобраться с флагами создания датасетов и пула, с конфигурацией initramfs и с тем, какие systemd сервисы стоит включать, с параметрами командной строки ядра и правильными конфигами. Если ставить вручную, то установка занимает целый вечер, с вдумчивым раскуриванием мануалов перед черной консолью. (Небольшой лайфхак: если у вас есть второй компьютер, гораздо приятнее ставить арч с него, подключившись к таргету по ssh, именно из-за возможности копипастинга команд).
Несколько лет назад я начал работать над автоматизацией этого процесса: написал несколько скриптов на bash, которые делают всё за меня. Это было не очень стабильно: они периодически ломались, гибкостью настройки там и не пахло: скрипт был жёстко прибит к моей конфигурации, и когда кто-то из друзей просил помочь с установкой Arch Linux на ZFS, обычно я просто делал новую ветку репозитория, подстраивая скрипт под нужную конфигурацию. Всё изменилось зимой прошлого года, когда мне захотелось в очередной раз поставить чистую систему для экспериментов на новый SSD. Я всерьез задумался о новом установщике, который предоставлял бы гибкое меню с конфигурацией в виде TUI. У меня была идея написать инструмент с нуля на Rust, используя ratatui, но масштаб работы для написания гибкого и надёжного проекта, сравнимого по функционалу с archinstall, начал меня немного пугать. Следующей мыслью было попробовать форкнуть archinstall. В процессе чтения его исходного кода и документации я понял: мне не нужно его форкать, я могу использовать его как библиотеку.
Так и родился archinstall_zfs - установщик, который использует archinstall как библиотеку, но при этом переопределяет ключевые компоненты. Я взял от archinstall то, что работает хорошо: TUI компоненты (SelectMenu, EditMenu), систему конфигурации, установку пакетов. Но разметку диска пришлось делать с нуля - archinstall просто не умеет работать с ZFS. Поэтому я написал свой DiskManager, который через sgdisk создаёт нужные разделы, а также GlobalConfigMenu - полностью кастомное меню вместо стандартного. А для самой установки создал ZFSInstaller, который наследует от archinstall.Installer, но умеет работать с ZFS-специфичными пакетами и конфигурацией.
Получилось именно то, что я хотел: гибкий TUI-интерфейс, где можно выбрать нужные параметры, а всю грязную работу инструмент сделает сам. Теперь установка Arch на ZFS занимает не вечер с мануалами, а 15-20 минут с чашкой чая.
Но прежде чем рассказывать о возможностях установщика, давайте разберёмся, почему вообще стоит заморачиваться с ZFS.
Почему ZFS?
ZFS - это не просто файловая система, это целая философия управления данными. Представьте, что вы обновили систему, что-то сломалось, и теперь не загружается графическая оболочка. С обычной файловой системой вы бы лезли за LiveUSB, arch-chroot, диагностика, исправление неполадок. Либо, если вы новичок, то дело может дойти до переустановки. С ZFS, снэпшотами и ZFSBootMenu вы просто перезагружаетесь, выбираете предыдущее состояние системы из меню и продолжаете работать. А потом спокойно разбираетесь, что пошло не так.
Или другой пример: хотите попробовать Wayland вместо X11? Создаёте клон текущего датасета, загружаетесь в него, экспериментируете. Не понравилось - откатились за секунду. Никаких "ой, а как же вернуть как было".
Кроме того, если у вас есть домашний сервер с ZFS, вы можете отправлять туда инкрементальные снепшоты время от времени
Три режима установки
Я долго думал, какие сценарии установки нужно поддержать. В итоге получилось три основных режима:
1. Full Disk - для тех, кто хочет отдать весь диск под ZFS. Тут я реализовал полную автоматизацию разметки через sgdisk. Установщик сначала очищает GPT и MBR сигнатуры (привет, проблемы с остатками старых разделов!), затем создаёт свежую GPT таблицу и нарезает разделы: EFI-раздел на 500MB, опционально swap-раздел в конце диска, а всё остальное - под ZFS.
2. New Pool - для dual-boot сценариев. У вас уже есть Windows на первой половине диска? Не проблема! Укажите свободный раздел, установщик создаст на нём ZFS pool и установит туда систему. EFI-раздел можно использовать существующий или создать новый.
3. Existing Pool - моя любимая фича! У вас уже есть ZFS pool с данными или другими системами? Установщик создаст новый boot environment и установит туда свежий Arch, не трогая существующие данные. Идеально для экспериментов и мультибута разных дистрибутивов.
Кто такие эти ваши Boot Environments?
Boot Environments (BE) — это способ держать несколько независимых систем на одном ZFS‑пуле. Каждая система размещается в своём корневом датасете и выбирается при загрузке через ZFSBootMenu. Для мультибута вы можете поставить несколько дистрибутивов в один пул — каждый станет отдельным BE.
Реальный пример с моего ноутбука (с комментариями):
❯ zfs list
NAME USED AVAIL REFER MOUNTPOINT
novafs 1.09T 361G 192K none
# Текущий активный BE "arch0" (контейнер, сам не монтируется)
novafs/arch0 609G 361G 192K none
novafs/arch0/data 421G 361G 192K none
novafs/arch0/data/home 421G 361G 344G /home # /home датасет для arch0
novafs/arch0/data/root 120M 361G 45.3M /root # данные пользователя root текущего BE
novafs/arch0/root 170G 361G 142G / # корневая ФС активного BE
novafs/arch0/vm 18.8G 361G 18.8G /vm # отдельный датасет для VM
# Предыдущий BE "archold" (не активен, но готов к загрузке)
novafs/archold 227G 361G 192K none
novafs/archold/data 143G 361G 192K none
novafs/archold/data/home 141G 361G 119G /home # /home датасет для archold
novafs/archold/data/root 1.81G 361G 1.81G /root # данные root второго BE
novafs/archold/root 83.7G 361G 83.7G / # корень второго BE
# Глобальные датасеты (вне BE, монтируются всеми boot environments)
novafs/tmp_zfs 7.08G 361G 7.08G /tmp_zfs # временные данные
ZFSBootMenu - загрузчик, который понимает ZFS
Забудьте про GRUB с его костылями для ZFS. ZFSBootMenu - это загрузчик, созданный специально для ZFS. В отличие от традиционных загрузчиков, он нативно понимает структуру ZFS и может показывать список boot environments в красивом ncurses-меню, делать снапшоты и клонировать boot environments прямо при загрузке. Нужно откатиться на снапшот недельной давности? Просто выбираете его из меню, и система загружается именно в том состоянии. Хотите поэкспериментировать, не ломая текущую систему? Клонируете boot environment прямо из загрузчика и загружаетесь в копию. Интересный факт: на самом деле этот загрузчик - это полноценный Linux, который при загрузке загружает вашу систему использую системный вызов kexec.
Нативное шифрование ZFS
Поддерживается нативное шифрование ZFS без необходимости в LUKS-контейнерах - ZFS шифрует данные сам. При этом доступны следующие варианты:
- Без шифрования.
- Шифрование всего пула (зашифрованы все датасеты включая корневую систему)
- Шифрование отдельного boot environment
В текущей версии поддерживаются только plain text ключи (пароли), без более сложных схем аутентификации. За расшифровку отвечает хук zfs в initramfs, который запрашивает пароль на ранней стадии загрузки.
Dracut vs mkinitcpio - выбор за вами
Arch традиционно использует mkinitcpio для создания initramfs. Но я предпочитаю dracut - его хук zfs лучше работает с нативным шифрованием ZFS. Установщик поддерживает оба варианта, и тут есть интересные технические детали.
Для mkinitcpio я добавляю хук zfs в нужное место (после keyboard, но до filesystems), прописываю правильные модули. А вот с dracut пришлось повозиться больше: нужно было написать собственные pacman хуки, которые автоматически пересобирают initramfs при обновлении ядра. Стандартные хуки пакмана не подходят - они не знают про dracut.
Загрузка и boot environments: ZFSBootMenu, zfs-mount-generator и кастомный ZED‑хук
Коротко о том, как устроена загрузка:
- В качестве загрузчика используется ZFSBootMenu: при выборе boot environment он запускает ядро Linux через системный вызов kexec и передаёт параметры командной строки ядра.
- Корневая ФС монтируется хуком zfs в initramfs, согласно параметру командной строки: с dracut это
root=ZFS=...
, с mkinitcpio — черезzfs=...
- Импорт пула выполняет systemd: включён
zfs-import-scan.service
; для пула заданоzpool set cachefile=none <pool>
, чтобы полностью отказаться отzpool.cache
(устаревшийzfs-import-cache.service
не используется). - Остальные датасеты монтируются уже systemd’ом через
zfs-mount-generator
(а неzfs-mount.service
), который читает/etc/zfs/zfs-list.cache/<pool>
и на лету генерирует unit‑файлы.
Проблема BE в том, что «по умолчанию» ZFS видит все датасеты пула, из‑за чего systemd может попытаться примонтировать чужие файловые системы (например, /home из соседнего boot environment). Это решает мой кастомный ZED‑хук history_event-zfs-list-cacher.sh
: он отслеживает события ZFS, определяет активный boot environment, фильтрует датасеты (оставляя только датасеты, принадлежащие текущему BE и общие вроде pool/tmp_zfs
) и атомарно обновляет кеш. Скрипт сделан иммутабельным (chattr +i
), чтобы обновления не затирали его.
Swap, ZRAM и ZSWAP
Можно вовсе обойтись без swap, можно включить ZRAM — это сжатый swap в RAM через systemd-zram-generator
, и в этом режиме я специально отключаю zswap. По умолчанию используется zram-size = min(ram / 2, 4096)
в /etc/systemd/zram-generator.conf
.
Если нужен классический swap на диске — выбирайте режим «ZSWAP + swap‑раздел»: zswap включается, а сам swap живёт на отдельном разделе. При полном стирании диска задаёте размер раздела под swap; в остальных сценариях просто выбираете существующий раздел в TUI. Для незашифрованного варианта установщик делает mkswap
и явно добавляет строку с UUID=
в /etc/fstab
(genfstab не включает неактивный swap). Для шифрованного — прописывает cryptswap
через PARTUUID
в /etc/crypttab
и монтирует /dev/mapper/cryptswap
в fstab
.
Примечание: swap на ZFS (zvol/swapfile) не поддерживается — см. раздел ArchWiki «ZFS → Swap volume». Гибернация в текущем релизе тоже не поддерживается.
Валидация совместимости ядра и ZFS
Одна из ключевых проблем при работе с ZFS на Arch - совместимость версий ядра и модулей ZFS. Precompiled модули ZFS в репозитории archzfs часто отстают от последних версий ядра, а DKMS может не компилироваться с bleeding-edge ядрами.
Для решения этой проблемы я написал систему валидации, которая определяет диапазон совместимых ядер для текущей версии ZFS. Система работает следующим образом:
- Парсит release notes на https://github.com/openzfs/zfs/releases для определения поддерживаемых версий ядра
- Сопоставляет эти данные с актуальными версиями ядер (linux, linux-lts, linux-zen) в репозиториях Arch
- Проверяет доступность precompiled ZFS модулей для каждого ядра
- Анализирует возможность DKMS-сборки с конкретными версиями ядра
- Предупреждает о потенциальных проблемах и предлагает альтернативы
Эта валидация используется в двух местах:
- В установщике - при выборе ядра показываются только совместимые варианты
- При сборке ISO - скрипт
iso_builder.py
автоматически проверяет совместимость перед созданием образов
Как это выглядит на практике?
Процесс установки сводится к нескольким простым шагам — выберите удобный способ запуска установщика.

Вариант A: готовый ISO (рекомендуется)
- Скачать последний ISO из релизов проекта и загрузиться в режиме UEFI. Примечание: если вы используете Ventoy, при выборе образа нужно выбрать GRUB2 режим загрузки.
- Подключить сеть.
- Запустить установщик:
./installer
# или
cd /root/archinstall_zfs && python -m archinstall_zfs
Вариант B: официальный Arch ISO (Этот вариант занимает больше времени из-за установки ZFS модулей в ISO.)
# 1) Загрузитесь с официального Arch ISO и подключите сеть
pacman -Sy git
# 2) Получите установщик
git clone --depth 1 https://github.com/okhsunrog/archinstall_zfs
cd archinstall_zfs
python -m archinstall_zfs
Этот вариант занимает больше времени, так как ZFS модули устанавливаются на лету.
Далее в TUI пройдите короткий визард: выберите режим установки → диски → имя пула → параметры системы. После подтверждения установщик автоматически настроит ZFSBootMenu, подберёт совместимую связку ядро/ZFS, соберёт initramfs (dracut или mkinitcpio) и включит необходимые сервисы ZFS: zfs.target
, zfs-import.target
, zfs-volumes.target
, zfs-import-scan.service
, zfs-zed.service
. В конце — предложение зайти в chroot и перезагрузка в свежий Arch на ZFS.
Подробнее о коде
Всё написано на Python 3.13+ с использованием archinstall как библиотеки, но архитектуру пришлось делать с нуля. Стандартные меню archinstall не подошли — сделал своё, чтобы контролировать весь процесс установки. Для разметки диска тоже реализовал отдельный класс, потому что archinstall не умеет работать с ZFS.
Установка ZFS идёт через собственный класс (наследник archinstall.Installer): он добавляет нужные пакеты, правильно собирает initramfs (dracut или mkinitcpio) и учитывает все нюансы ZFS. Валидация совместимости ядра и ZFS вынесена в отдельный модуль — он парсит репозитории, релизы ZFS и проверяет, что всё совместимо. Для конфигов используется Pydantic, чтобы не было магии с dict'ами.
Профиль для ISO собирается через шаблоны Jinja2 — так проще поддерживать разные варианты (DKMS или precompiled модули, разные хуки и сервисы, разные наборы пакетов включаются условно). Всё максимально типизировано, чтобы не ловить баги на ровном месте.
Сборка ISO: just, Justfile и Jinja2
Сборочные сценарии полностью оркестрируются через just
(рецепты описаны в justfile
). Это позволяет быстро собирать разные варианты ISO и управлять параметрами сборки.
- Посмотреть доступные команды:
just --list
- Типовые сборки:
# Релизные ISO (полный набор пакетов)
just build-main pre # Precompiled ZFS + linux-lts (рекомендуется)
just build-main dkms linux # DKMS + linux
just build-main dkms linux-lts # DKMS + linux+lts (самый надёжный вариант, если версии пакетов zfs и ядер рассинхронизированы)
# Ускоренные сборки для разработки (минимальный набор пакетов)
just build-test pre # Минимальный пакетный набор + precompiled ZFS
just build-test dkms linux-zen # Минимальный пакетный набор + DKMS + linux-zen
just list-isos # Показать собранные ISO
Ключевые различия между build-main
и build-test
:
build-main
— создаёт релизные ISO с полным набором пакетов (включая диагностические инструменты, сетевые утилиты, редакторы и т.д.). Используетsquashfs
для сжатия, что даёт меньший размер ISO.build-test
— создаёт тестовые ISO с минимальным набором пакетов (только базовые утилиты и установщик). Используетerofs
для более быстрого сжатия, отключает таймауты загрузки и включает вывов в serial console для удобства загрузки в qemu, автоматически поднимает ssh и разрешает логин от рута. Идеально подходит для быстрого тестирования изменений в установщике в qemu.
Профиль archiso
генерируется из шаблонов на Jinja2, что даёт гибкую конфигурацию без копипасты:
- Переменные шаблонов:
kernel
— целевой вариант ядраuse_precompiled_zfs
/use_dkms
— способ установки ZFSinclude_headers
— включать ли headers для ядраfast_build
— минимальный пакетный набор для быстрых тестов
- Ключевые шаблоны:
packages.x86_64.j2
— список пакетовprofiledef.sh.j2
— метаданные ISO, флаги сборки, разрешения файловpacman.conf.j2
— конфигурация репозиториев
Скрипт iso_builder.py
формирует профиль ISO на основе этих шаблонов и параметров, а результаты складываются в gen_iso/out/
. Сами профильные файлы, сервисы и хуки лежат в gen_iso/profile/
.
Дополнительные возможности установщика
- Сжатие ZFS (настраиваемо): выбор алгоритма в TUI —
off
,lz4
(по умолчанию),zstd
,zstd-5
,zstd-10
. Выбранное значение применяется на уровне пула/датасетов и наследуется, а в initramfs отключается лишняя компрессия, чтобы избежать двойного сжатия. - zrepl: генерация
/etc/zrepl/zrepl.yml
с снапшотами каждые 15 минут и ретеншном4×15m (keep=all) | 24×1h | 3×1d
. - AUR‑интеграция: установка пакетов из AUR через временного пользователя (
aurinstall
) иyay-bin
с безопасной очисткой.
Что ожидать в следующем релизе?
- Поддержка Secure Boot (подпись ZFSBootMenu, управление ключами)
- Локальная сборка ZFSBootMenu, используя системное ядро и dracut / mkinitcpio, вместо готовых EFI-файлов, для большей кастомизации
- Более умная генерация hostid (на основе имени хоста)
- Возможно, добавлю русскую локализацию, если будет интерес
Пара слов о CI
За сборку отвечает GitHub Actions: раз в месяц он автоматически собирает свежие образы, а ещё он запускается при пуше нового тега и формирует релиз с ISO-образами в качестве артифактов. Перед сборкой пайплайн проверяет совместимость: сначала пробует предсобранные ZFS‑модули, и если версии не совпадают, автоматически переключается на DKMS. Благодаря этому образ с linux-lts
получается практически всегда, а linux
в редких случаях, если текущая версия ядра ещё не поддерживается проектом OpenZFS, просто пропускается.
ZFS - это мощный инструмент, но сложность её настройки отпугивает многих. Я надеюсь, что archinstall_zfs сделает эту файловую систему доступнее для обычных пользователей Arch Linux. Больше не нужно быть гуру, чтобы получить все преимущества ZFS - снапшоты, boot environments, компрессию и надёжность.
Проект активно развивается, поэтому баги возможны. Но я сам использую его для всех своих установок и пока полёт нормальный 😃
Если у вас есть идеи по улучшению или вы нашли баг - welcome в issues на GitHub! А если проект оказался полезным - поставьте звёздочку, это мотивирует развивать его дальше.
Ссылка на репозиторий: https://github.com/okhsunrog/archinstall_zfs