Собираем Samba NAS в Proxmox LXC. Часть 6: Immutable backup через ZFS snapshots
Настраиваем immutable backup для Samba NAS на Proxmox: ZFS snapshots, zfs hold, защита от удаления и health-check скрипт.
Задача
В предыдущих частях мы собрали Samba/NAS:
1
2
3
4
/srv/samba
├── public
├── share
└── secure
Теперь нужно решить главный вопрос:
1
как защитить данные от удаления, ошибки администратора и ransomware?
Обычный backup — это хорошо. Но если backup можно удалить так же легко, как обычный файл, то это не стратегия, а надежда.
В этой части сделаем immutable backup на уровне Proxmox/ZFS.
Backup без проверки и защиты от удаления — это не backup, а предположение, что всё будет хорошо.
Что такое immutable backup
Immutable backup — это резервная копия, которую нельзя изменить или удалить до снятия защиты.
Цель:
- пережить ошибочный
rm -rf; - пережить ransomware;
- защититься от случайного удаления;
- иметь точку восстановления;
- сделать backup независимым от LXC-контейнера.
Почему не внутри LXC
Если Samba работает в LXC, может возникнуть желание делать защиту внутри контейнера:
1
chattr +i backup.tar.zst
Это лучше, чем ничего, но это слабый уровень защиты.
Проблемы:
- root внутри контейнера может быть скомпрометирован;
chattr +iможно снять;- ransomware внутри контейнера видит файловую систему контейнера;
- контейнер не должен управлять своей единственной защитой.
Правильнее выносить immutable-слой на уровень Proxmox host.
Архитектура
Пример:
1
2
3
4
5
6
7
8
Proxmox host
└── ZFS pool: NAS
└── subvol-102-disk-0
└── LXC container: samba
└── /srv/samba
├── public
├── share
└── secure
Ключевая мысль:
1
2
LXC отдаёт файлы по SMB.
Proxmox/ZFS защищает snapshots.
Если snapshot создан на хосте и на него поставлен zfs hold, контейнер не сможет его удалить.
Варианты immutable-подхода
| Вариант | Где работает | Плюсы | Минусы |
|---|---|---|---|
chattr +i | ext4/xfs | просто | root может снять флаг |
| Btrfs read-only snapshots | btrfs | быстро, удобно | root может удалить snapshot |
| ZFS snapshots + hold | ZFS | лучший вариант для Proxmox | требует ZFS и дисциплины |
Для Proxmox с ZFS самый интересный вариант:
1
2
zfs snapshot pool/dataset@backup-YYYY-MM-DD
zfs hold immutable pool/dataset@backup-YYYY-MM-DD
Шаг 1. Найти dataset контейнера
На Proxmox host:
1
pct config 102
Пример:
1
rootfs: NAS:subvol-102-disk-0,size=30G
Значит dataset:
1
NAS/subvol-102-disk-0
Проверим:
1
zfs list | grep subvol-102-disk-0
Шаг 2. Создать snapshot
1
zfs snapshot NAS/subvol-102-disk-0@backup-$(date +%F)
Проверить:
1
zfs list -t snapshot | grep subvol-102-disk-0
Шаг 3. Поставить hold
1
zfs hold immutable NAS/subvol-102-disk-0@backup-$(date +%F)
Проверить:
1
zfs holds NAS/subvol-102-disk-0@backup-$(date +%F)
Ожидаемый смысл:
1
пока есть hold с тегом immutable, snapshot нельзя удалить
Шаг 4. Проверить защиту
Пробуем удалить snapshot:
1
zfs destroy NAS/subvol-102-disk-0@backup-$(date +%F)
Если всё правильно, ZFS не даст удалить snapshot и сообщит, что он удерживается hold.
Проверка удаления нужна не для того, чтобы сломать backup, а чтобы убедиться, что защита реально работает.
Скрипт создания immutable snapshot
Создадим скрипт на Proxmox host:
1
nano create-immutable-zfs-snapshot.sh
Содержимое:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env bash
set -Eeuo pipefail
# ============================================================
# SMB на bash. Часть 6. Immutable Backups
# Создание ZFS snapshot + hold для LXC dataset
# Запускать на Proxmox host, не внутри контейнера.
# ============================================================
DATASET="${DATASET:-NAS/subvol-102-disk-0}"
TAG="${TAG:-immutable}"
PREFIX="${PREFIX:-backup}"
DATE="$(date +%F)"
SNAP="${DATASET}@${PREFIX}-${DATE}"
require_root() {
if [[ "${EUID}" -ne 0 ]]; then
echo "Ошибка: запусти скрипт от root на Proxmox host"
exit 1
fi
}
check_dataset() {
if ! zfs list -H -o name "${DATASET}" >/dev/null 2>&1; then
echo "Ошибка: dataset не найден: ${DATASET}"
echo "Проверь: zfs list"
exit 1
fi
}
create_snapshot() {
if zfs list -H -t snapshot -o name | grep -qx "${SNAP}"; then
echo "Snapshot уже существует: ${SNAP}"
else
echo "==> Создаём snapshot ${SNAP}"
zfs snapshot "${SNAP}"
fi
}
apply_hold() {
if zfs holds "${SNAP}" | grep -q "${TAG}"; then
echo "Hold уже установлен: ${TAG}"
else
echo "==> Ставим hold ${TAG}"
zfs hold "${TAG}" "${SNAP}"
fi
}
verify() {
echo "==> Проверяем snapshot"
zfs list "${SNAP}" >/dev/null
echo "==> Проверяем hold"
zfs holds "${SNAP}" | grep -q "${TAG}"
echo
echo "Immutable snapshot готов:"
echo " ${SNAP}"
}
main() {
require_root
check_dataset
create_snapshot
apply_hold
verify
}
main "$@"
Запуск
1
2
chmod +x create-immutable-zfs-snapshot.sh
sudo DATASET="NAS/subvol-102-disk-0" ./create-immutable-zfs-snapshot.sh
Health-check immutable backup
Backup должен не только создаваться. Его нужно проверять.
Проверим:
- snapshot существует;
- snapshot имеет hold;
- ZFS pool без ошибок;
- snapshot не старше 24 часов.
Создай скрипт:
1
nano healthcheck-immutable-zfs-snapshot.sh
Содержимое:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env bash
set -Eeuo pipefail
# ============================================================
# Health-check immutable ZFS snapshot
# Запускать на Proxmox host.
# ============================================================
DATASET="${DATASET:-NAS/subvol-102-disk-0}"
TAG="${TAG:-immutable}"
PREFIX="${PREFIX:-backup}"
DATE="$(date +%F)"
SNAP="${DATASET}@${PREFIX}-${DATE}"
EXIT_OK=0
EXIT_WARN=1
EXIT_CRIT=2
echo "=== ZFS Immutable Backup Health Check ==="
echo "Dataset : ${DATASET}"
echo "Snapshot: ${SNAP}"
echo
if ! zfs list -H -t snapshot -o name | grep -qx "${SNAP}"; then
echo "CRITICAL: snapshot not found"
exit "${EXIT_CRIT}"
fi
echo "OK: snapshot exists"
if ! zfs holds "${SNAP}" | grep -q "${TAG}"; then
echo "CRITICAL: snapshot exists but hold '${TAG}' not found"
exit "${EXIT_CRIT}"
fi
echo "OK: snapshot is immutable"
POOL="$(echo "${DATASET}" | cut -d/ -f1)"
if ! zpool status "${POOL}" >/tmp/zpool-status.$$; then
echo "CRITICAL: cannot read zpool status for ${POOL}"
rm -f /tmp/zpool-status.$$
exit "${EXIT_CRIT}"
fi
if grep -q "errors: No known data errors" /tmp/zpool-status.$$; then
echo "OK: ZFS pool has no known data errors"
else
echo "WARNING: ZFS pool reports issues"
cat /tmp/zpool-status.$$
rm -f /tmp/zpool-status.$$
exit "${EXIT_WARN}"
fi
rm -f /tmp/zpool-status.$$
CREATION="$(zfs get -H -o value creation "${SNAP}")"
CREATION_TS="$(date -d "${CREATION}" +%s)"
NOW_TS="$(date +%s)"
AGE_HOURS="$(( (NOW_TS - CREATION_TS) / 3600 ))"
if [[ "${AGE_HOURS}" -gt 24 ]]; then
echo "WARNING: snapshot is older than 24 hours: ${AGE_HOURS}h"
exit "${EXIT_WARN}"
fi
echo "OK: snapshot age ${AGE_HOURS}h"
echo
echo "BACKUP HEALTH: OK"
exit "${EXIT_OK}"
Запуск health-check
1
2
chmod +x healthcheck-immutable-zfs-snapshot.sh
sudo DATASET="NAS/subvol-102-disk-0" ./healthcheck-immutable-zfs-snapshot.sh
Ожидаемый результат:
1
2
3
4
5
6
OK: snapshot exists
OK: snapshot is immutable
OK: ZFS pool has no known data errors
OK: snapshot age 0h
BACKUP HEALTH: OK
Как удалить immutable snapshot
Удалять такой snapshot нужно осознанно.
Сначала снять hold:
1
zfs release immutable NAS/subvol-102-disk-0@backup-2026-05-10
Потом удалить:
1
zfs destroy NAS/subvol-102-disk-0@backup-2026-05-10
Проверить:
1
zfs list -t snapshot | grep subvol-102-disk-0
Снятие hold — административное действие. Его стоит логировать и не делать автоматически без политики retention.
Retention-политика
На старте можно использовать простую схему:
1
2
3
daily snapshots → 7 дней
weekly snapshots → 4 недели
monthly snapshots → 6 месяцев
Но важно: если на snapshot стоит hold, его нельзя удалить обычной ротацией. Значит ротация должна:
- выбирать snapshot;
- проверять возраст;
- снимать hold только по политике;
- удалять snapshot;
- писать лог.
Это лучше вынести в отдельную статью, чтобы не смешивать создание backup и retention.
Что получилось в серии
Мы собрали Samba/NAS по частям:
| Часть | Результат |
|---|---|
| 1 | Архитектура public/share/secure/backup |
| 2 | Рабочая шара [share] |
| 3 | Защищённая шара [secure] |
| 4 | Audit-логирование для [secure] |
| 5 | Public read-only шара [public] |
| 6 | Immutable backup на Proxmox/ZFS |
Итог
Immutable backup лучше делать не внутри Samba-контейнера, а на уровне Proxmox/ZFS.
Итоговая схема:
1
2
3
4
5
6
7
Samba LXC
└── отдаёт файлы по SMB
Proxmox host
└── создаёт ZFS snapshots
└── ставит zfs hold
└── защищает backup от удаления
Такой подход заметно повышает устойчивость к ошибкам, ransomware и случайному удалению данных.
