Якщо ви будуєте сервер Linux під дані або бекапи, OpenZFS — майже мрія: перевірки цілісності, миттєві снапшоти, стиснення й навіть дедуплікація. Нижче — мій дружній, але технічно точний гайд, де ми створимо пул, ввімкнемо потрібні властивості, налаштуємо снапшоти й зробимо автоматичну ротацію через systemd timers. Поїхали! 🚀
Що знадобиться і важливі застереження
Потрібен сучасний дистрибутив з підтримкою OpenZFS (Ubuntu/Debian/RHEL-похідні). Для продакшену бажано мати ECC-пам'ять, але це не жорстка вимога. Пам’ятайте: дедуплікація ZFS дуже вимоглива до RAM, увімкніть її тільки за підтвердженої вигоди (типово для VM-образів чи шаблонів контейнерів). І, так — резервне копіювання системи ніхто не скасовував.
Встановлення ZFS
Ubuntu / Debian
sudo apt update
# Ubuntu
sudo apt install -y zfsutils-linux
# Debian (за потреби ядро/модуль DKMS)
sudo apt install -y zfs-dkms zfsutils-linux
# Перевірка
modprobe zfs
zpool version
zfs version
RHEL / Rocky / AlmaLinux (через репозиторій OpenZFS)
# Додайте офіційний репозиторій OpenZFS для вашої версії дистрибутива (див. інструкції OpenZFS)
# Приклад далі припускає, що репозиторій уже підключено:
sudo dnf install -y kernel-devel zfs
sudo modprobe zfs
zpool version
How-to: створюємо пул, датасети, снапшоти і ротацію
Підготовка дисків і стабільні ідентифікатори
Рекомендовано використовувати шляхи /dev/disk/by-id/ — вони стабільні навіть після перезавантаження.
ls -l /dev/disk/by-id | grep -E "(sdb|sdc)$"
Якщо диск новий або ви згодні стерти таблицю розділів:
sudo wipefs -a /dev/sdb
sudo wipefs -a /dev/sdc
Створення пулу ZFS із корисними властивостями
Приклад: дзеркальний пул tank з автотрімом, стисненням lz4, вимкненим atime й коректними xattr/ACL:
sudo zpool create \
-o ashift=12 -o autotrim=on \
-O compression=lz4 -O atime=off -O xattr=sa -O acltype=posixacl \
tank mirror \
/dev/disk/by-id/XXXXXXXX_sdb \
/dev/disk/by-id/XXXXXXXX_sdc
# Перевірка стану
zpool status -v tank
zfs list -r tank
Параметр ashift=12 підходить для сучасних дисків із 4K-секторами. Змінити його після створення пулу не можна.
Датасети: гнучкі точки монтування
# Створимо датасет під дані застосунку
sudo zfs create -o mountpoint=/srv/data tank/data
# Для VM-образів — окремий датасет
sudo zfs create -o mountpoint=/srv/vmstore tank/vmstore
Дедуплікація (обережно!)
Увімкніть дедуплікацію лише там, де реально є дублікати блоків і достатньо RAM (орієнтир — гігабайти на кожен терабайт унікальних даних). Краще вмикати на конкретному датасеті, а не на всьому пулі:
# Ввімкнути дедуплікацію лише для VM-сховища
sudo zfs set dedup=on tank/vmstore
# Перевірити
zfs get dedup tank/vmstore
Снапшоти вручну
Снапшоти в ZFS миттєві й копіюють лише метадані. Створимо рекурсивний снапшот для всього піддерева:
# Ім'я включає час для сортування
sudo zfs snapshot -r tank/data@manual-$(date +%F-%H%M)
# Список снапшотів
zfs list -t snapshot -r tank/data
# Відкат до останнього снапшоту (обережно, це зітре новіші зміни)
sudo zfs rollback -r tank/data@manual-2026-07-22-1200
Автоматична ротація через systemd
Ми реалізуємо автоматизацію задач: щогодини/щодня/щотижня створюємо снапшоти і видаляємо старі понад ліміт. Це зручно, надійно та краще, ніж cron — адже cron та systemd timers у systemd мають опцію Persistent=true (надолужують виконання після простою).
Позначаємо датасети для автоснапів
sudo zfs set com.kernelka:autosnap=on tank/data
sudo zfs set com.kernelka:autosnap=on tank/vmstore
Скрипт ротації /usr/local/bin/zfs-snap-rotate
sudo tee /usr/local/bin/zfs-snap-rotate >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
CLASS="${1:-hourly}" # hourly|daily|weekly
HOURLY_KEEP="${HOURLY_KEEP:-24}"
DAILY_KEEP="${DAILY_KEEP:-14}"
WEEKLY_KEEP="${WEEKLY_KEEP:-8}"
PREFIX="${PREFIX:-autosnap}"
keep() {
case "$CLASS" in
hourly) echo "$HOURLY_KEEP";;
daily) echo "$DAILY_KEEP";;
weekly) echo "$WEEKLY_KEEP";;
*) echo "Use: hourly|daily|weekly" >&2; exit 2;;
esac
}
datasets=$(zfs get -H -o name,value com.kernelka:autosnap 2>/dev/null | awk '$2=="on"{print $1}')
[ -n "$datasets" ] || { echo "No datasets tagged for autosnap"; exit 0; }
ts=$(date +%F-%H%M)
for ds in $datasets; do
zfs snapshot -r "${ds}@${PREFIX}-${CLASS}-${ts}"
snaps=$(zfs list -H -t snapshot -o name -S creation | grep "^${ds}@${PREFIX}-${CLASS}-" || true)
cnt=0
while read -r snap; do
[ -n "$snap" ] || continue
cnt=$((cnt+1))
if [ $cnt -gt "$(keep)" ]; then
zfs destroy -r "$snap"
fi
done <<< "$snaps"
Done
done
echo "Done $CLASS snapshots: $(date -Is)"
EOF
sudo chmod +x /usr/local/bin/zfs-snap-rotate
Сервіс і три таймери systemd
# Сервіс-шаблон
sudo tee /etc/systemd/system/zfs-snap@.service >/dev/null <<'EOF'
[Unit]
Description=ZFS autosnap (%i)
Requires=zfs.target
After=zfs.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/zfs-snap-rotate %i
[Install]
WantedBy=multi-user.target
EOF
# Таймери
sudo tee /etc/systemd/system/zfs-snap@hourly.timer >/dev/null <<'EOF'
[Unit]
Description=ZFS autosnap hourly
[Timer]
OnCalendar=hourly
Persistent=true
Unit=zfs-snap@hourly.service
[Install]
WantedBy=timers.target
EOF
sudo tee /etc/systemd/system/zfs-snap@daily.timer >/dev/null <<'EOF'
[Unit]
Description=ZFS autosnap daily
[Timer]
OnCalendar=daily
Persistent=true
Unit=zfs-snap@daily.service
[Install]
WantedBy=timers.target
EOF
sudo tee /etc/systemd/system/zfs-snap@weekly.timer >/dev/null <<'EOF'
[Unit]
Description=ZFS autosnap weekly
[Timer]
OnCalendar=Sun 03:00
Persistent=true
Unit=zfs-snap@weekly.service
[Install]
WantedBy=timers.target
EOF
# Активуємо
sudo systemctl daemon-reload
sudo systemctl enable --now zfs-snap@hourly.timer zfs-snap@daily.timer zfs-snap@weekly.timer
# Перевірка
systemctl list-timers 'zfs-snap@*.timer'
journalctl -u zfs-snap@hourly.service --since today -e
Альтернативні способи
- Sanoid/Syncoid: готовий інструмент політик снапшотів і реплікацій. На Debian/Ubuntu:
sanoïdу репозиторіях. Мінімум команд — максимум контролю, зручно для сервер Linux у продакшені. - zrepl: сучасна реплікація через потоки з YAML-конфігами — чудово для офсайт-бекапів.
# Приклад швидкого старту Sanoid (Debian/Ubuntu)
sudo apt install -y sanoid
sudo cp /usr/share/sanoid/sanoid.conf.example /etc/sanoid/sanoid.conf
# Відредагуйте політики для tank/data, потім:
sudo systemctl enable --now sanoid.timer
GUI-спосіб (якщо хочеться «віконець»)
Для повноцінного графічного керування ZFS найзручніше використати TrueNAS SCALE — це окрема Linux-система з OpenZFS і веб-інтерфейсом для пулів, снапшотів і реплікацій. На існуючому дистрибутиві можна встановити Cockpit, щоб мати веб-доступ до логів і сервісів (у т.ч. наших таймерів), а сам ZFS адмініструвати з терміналу Linux — це компроміс між зручністю і контролем.
# Cockpit для огляду системи і юнітів systemd
sudo apt install -y cockpit || sudo dnf install -y cockpit
sudo systemctl enable --now cockpit.socket
# Веб: https://<ip-сервера>:9090
FAQ
Чи вмикати дедуплікацію скрізь?
Ні. Увімкніть лише там, де вигода очевидна (VM-образи, шаблони). Дедуп потребує багато RAM, а вигода на мішаних даних невелика. Спочатку покладіться на compression=lz4.
Яке значення ashift обрати?
Для сучасних HDD/SSD зазвичай ashift=12 (4K). Змінити пізніше не можна, тож краще одразу правильно.
Як замінити диск у mirror?
zpool status -v tank
# Додаємо новий диск і замінюємо старий
a) sudo zpool replace tank <old-disk-by-id> <new-disk-by-id>
# Після resilver перевіряємо стан
zpool status -v tank
Як розширити пул?
Додайте новий vdev (наприклад, ще один mirror) або послідовно замініть диски на більші у vdev з подальшим розширенням. Просте додавання одного диска до mirror неможливе — це інша топологія.
Як робити офсайт-бекапи?
Ставте реплікацію: zfs send | zfs receive, або скористайтеся syncoid/zrepl. Це доповнює локальні снапшоти і зміцнює резервне копіювання системи.
Моніторинг стану?
zpool status -x # проблеми пулів
zpool list # ємність, фрагментація
zfs list -o space # розподіл простору за датасетами
sudo zpool scrub tank # раз на місяць — корисно для перевірки цілісності
Пул не змонтувався після перезавантаження
Переконайтеся, що модуль zfs завантажується і служби ввімкнені. Перевірте імпорт:
sudo zpool import -aN
systemctl status zfs-import-cache.service zfs-mount.service
Помилка "unsupported feature" при імпорті
Імпортуйте лише для читання, збережіть дані, оновіть OpenZFS на цільовій системі:
sudo zpool import -o readonly=on tank
Порада від Kernelka
🧠 Давайте снапшотам чіткий префікс (autosnap-hourly-YYYY-MM-DD-HHMM), вмикайте автоснапи тільки на потрібних датасетах (через властивість com.kernelka:autosnap=on) і не поспішайте з дедуплікацією — спершу зберіть метрики: RAM, профіль даних, реальну економію від compression=lz4. Менше магії — більше контрольованого результату.
Підсумок
- Встановили OpenZFS і створили пул із правильними опціями.
- Організували дані у датасетах для зручного керування політиками.
- Налаштували снапшоти та безпечний відкат змін.
- Зробили автоматичну ротацію через systemd timers із прозорими лімітами.
- Розглянули альтернативи (Sanoid/zrepl) та варіанти з GUI.
- Не забуваємо про scrub і зовнішню реплікацію для справжньої надійності. 🙂