Files
obsidian-vault/family/plans/kraken-backup-to-truenas.md

19 KiB
Executable File
Raw Permalink Blame History

Kraken → TrueNAS — автобэкап стека

Создано: 2026-09-20 Обновлено: 2026-09-20 (✅ ВСЕ 7 ШАГОВ ВЫПОЛНЕНЫ И ПРОВЕРЕНЫ) Статус: ✅ РАБОТАЕТ END-TO-END. Архив 165 МБ / 36985 файлов лёг на TrueNAS (nas:nas), jellyfin и backup.log исключены. Крон 0 4 * * * установлен. Старый бэкап Kraken→Mail.ru отключён. Задача: бэкап стека Kraken складывать на TrueNAS в /mnt/RED_2TB/backup/kraken/, откуда он автоматически уезжает в Mail.ru Cloud существующим rclone-скриптом TrueNAS (скрипт не трогаем).

✅ СТАТУС РЕАЛИЗАЦИИ (2026-09-20)

# Шаг Статус Факт
1 SSH-ключ kraken-backup-push + pub на TrueNAS ✅ Ключ на Kraken ~/.ssh/kraken-backup-push (ed25519, fp SHA256:hpatuPO7Yyf+/OryR1dokDmmUXAY7Ei4dWvL1pfsvLQ). Pub записан в sshpubkey юзера nas (id=72) через midclt call user.update 72. Проверено живьём: ssh -i kraken-backup-push nas@mallexxx.duckdns.org → CONNECTED_AS=nas.
2 Датасет /mnt/RED_2TB/backup/kraken ✅ Создан через midclt call pool.dataset.create (NFSV4/PASSTHROUGH). Права 1000:1000 (nas) 770 — выставлены через midclt call filesystem.setperm (обычный chown от truenas_admin → Operation not permitted). Проверено: Kraken пишет туда (WRITE_OK/CLEANUP_OK).
3 Скрипт на Kraken ✅ /home/kraken/kraken-backup-to-truenas.sh (755, bash -n OK). Лог ~/kraken-backup.log, err ~/kraken-backup.err. Рабочая копия на Mac: /Users/admin/kraken-recovery/kraken-backup-to-truenas.sh. Запускается под sudo (см. ниже), rsync с --chown=nas:nas.
4 Ротация 14 архивов ✅ Реализована: ls -1t kraken-docker-*.tar.gz | tail -n +15 | rm на стороне TrueNAS. В прогоне отработала (архив один → удалять нечего, шаг прошёл без ошибок).
5 Крон 0 4 * * * ✅ Поставлен: /etc/cron.d/kraken-backup (root:root 644), строка 0 4 * * * root /home/kraken/kraken-backup-to-truenas.sh. cron активен. Не конфликтует с root-crontab (sd-backup.sh 03:00 вс, timemachine).
6 Живой прогон ✅ Проверено end-to-end: tar 603M → 165 МБ, rsync 52 с, размер совпал (165704366 == 165704366), лог === KRAKEN BACKUP DONE ===. На TrueNAS: /mnt/RED_2TB/backup/kraken/kraken-docker-20260920-115925.tar.gz, 36985 файлов, владелец nas:nas.
7 Выключить старый Kraken→Mail.ru ✅ СДЕЛАНО. Строка 0 3 * * 0 в /config/rclone/crontab закомментирована, применено (crontab /config/rclone/crontab). Проверено: активных задач в контейнере нет (crontab -l | grep -v '^#' пусто), crond жив, контейнер Up. Бэкап для отката: /home/kraken/backups/rclone-disable-20260920-120606/.

✅ РЕШЕНИЕ БЛОКЕРА ПРАВ: вариант C — весь скрипт под sudo

Симптом (первый прогон): tar: docker/portainer/certs: Cannot open: Permission denied → Exiting with failure status → ветка exit 2, архив удалён.

Факт (владельцы подпапок /srv/...6194539b.../docker/):

Владелец Каталоги
root (0:0) cloudflared, hermes-build, hermes, homeassistant, jellyfin, portainer, rclone, scripts, watchtower
1000:1000 (kraken) media-pipeline, prowlarr, radarr, sonarr, transmission

tar от kraken покрывал только половину — критичные hermes, portainer, rclone/config (root-owned) недоступны.

Решение (Alex: «ну конечно sudo cron должен быть») — вариант C:

  • Скрипт запускается целиком под sudo (sudo -n работает без пароля, NOPASSWD есть).
  • В скрипте: rsync -a --no-o --no-g --chown=nas:nas — владелец архива на TrueNAS принудительно nas:nas, несмотря на root на отправляющей стороне.
  • Крон-строка в /etc/cron.d/kraken-backup уже идёт от root → sudo внутри скрипта не нужен, tar и так root.

⚠️ Питфолл: при root-сборке архива ОБЯЗАТЕЛЬНО rsync --chown=nas:nas, иначе архив на TrueNAS окажется root:root, и ротация (rm от nas) его не удалит.

⚠️ Питфолл скрипта (мелкий, не критичный): $ERR-файл (~/kraken-backup.err) не обнуляется в начале прогона — при чтении лога видны старые Permission denied из прошлого падения. Фильтровать по времени, либо добавить : > "$ERR" в старт.

📦 Факты для реализации (собраны 2026-09-20)

  • Размер стека: /srv/.../docker = 2.2G, без jellyfin и *.log = 603M (сжимается).
  • /tmp на Kraken = tmpfs 2.0G → места под архив хватает.
  • rsync/tar на Kraken есть: /usr/bin/rsync, /usr/bin/tar.
  • Внешний IP Kraken = 92.62.70.9 (⚠️ динамический — в доке фигурировал .41). Следствие: from= в authorized_keys для push-ключа не ставить — IP сменится и бэкап умрёт. Ограничить только no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding. (Через API user.update ограничения всё равно не выставить — ключ пишется «голым»; если нужны ограничения, править ~nas/.ssh/authorized_keys под root.)
  • Бэкап-скрипт на Mac (рабочая копия): /Users/admin/kraken-recovery/kraken-backup-to-truenas.sh.
  • Дампы перед изменениями (TrueNAS): /home/truenas_admin/kraken-backup-setup-20260919-223211/ — nas-user-before.json, cronjobs-before.json, smb-before.json. ⚠️ /mnt/RED_2TB/backup/ — root:root, truenas_admin не может создавать там папки (бэкапы держать в ~).

Питфоллы TrueNAS, подтверждённые в этой сессии

  • chown/chmod от truenas_admin на root-owned датасете → Operation not permitted. Рабочий путь: midclt call filesystem.setperm '{"path":...,"mode":"770","uid":1000,"gid":1000}' (возвращает job id, применяется асинхронно — подождать 3-5 с и проверить ls -ldn). Это не требует root-шелла, в отличие от chown.
  • midclt call pool.dataset.create с aclmode=PASSTHROUGH + acltype=NFSV4 — сработало (обход питфолла №3 из family/plans/t610-backup-to-truenas про DISCARD).
  • Ключ юзера nas класть через midclt call user.update 72 '{"sshpubkey":"..."}' — TrueNAS сам создаёт ~nas/.ssh/authorized_keys с правильными правами, обходя питфолл №9 (непроходимые родители ~nas).

Почему появилась задача

2026-09-20 при разборе падения vless reverse proxy и cloudflared ssh tunnel выяснилось:

  • Бэкап Kraken был — контейнер rclone на Kraken, вс 03:00, /data/docker → mailru-crypt:kraken/docker.
  • Но последний успешный прогон — до 13.09.2026. 13-го прогон упал с 292 ошибками: сначала 507 Insufficient Storage (место на Mail.ru кончилось), затем 400 Bad Request.
  • Прогон 20.09 не состоялся вообще — контейнер rclone не был запущен (docker-гонка: dockerd стартовал раньше монтирования USB-диска, см. personal/tech/docker-data-root-mount-race). Crontab пропущенное окно не догоняет.
  • rclone sync при ошибках не удаляет → в облаке застряло неполное состояние.

Решение Alex (2026-09-20): перенастроить так, чтобы бэкап Kraken шёл на TrueNAS в общую папку backup/, рядом с t610, и уезжал в Mail.ru существующим скриптом. Часть «TrueNAS → Mail.ru» не трогать.

Схема (принята 2026-09-20)

Kraken: /srv/dev-disk-by-uuid-6194539b-.../docker   (весь стек конфигов)
   │  tar czf -   (собирается НА Kraken, локально)
   │  rsync/scp  ──────────►  mallexxx.duckdns.org:22  (порт открыт, ping ~102ms)
   ▼
TrueNAS: /mnt/RED_2TB/backup/kraken/kraken-docker-<ts>.tar.gz
   │  ротация N архивов
   ▼
rclone backup.sh (вс 03:00, контейнер rclone)   ← ⛔ НЕ ТРОГАЕМ
   │  run_sync "backup" /data/backup "mailru-crypt:"
   ▼
Mail.ru Cloud (зашифровано)

Ключевой принцип: /mnt/RED_2TB/backup/* уже целиком уходит в mailru-crypt: строкой run_sync "backup" /data/backup "mailru-crypt:". Значит всё, положенное в backup/kraken/, уезжает в облако автоматически — правок в backup.sh не требуется. Тот же приём, что у family/plans/t610-backup-to-truenas.

Решения и обоснование

  1. Вариант A — PUSH с Kraken (выбрал Alex 2026-09-20). Почему не PULL (как у t610): Kraken за NAT, белого IP нет → TrueNAS не может к нему подключиться. PULL потребовал бы SSH-туннель. PUSH работает через уже открытый порт mallexxx.duckdns.org:22. Минус PULL-схемы t610 здесь непреодолим: у t610 адрес в локалке TrueNAS (192.168.2.176), у Kraken — другая сеть (192.168.1.x) + NAT.

  2. Что бэкапим: весь /srv/dev-disk-by-uuid-6194539b-.../docker (2.2G), кроме:

    • docker/jellyfin/ (1.5G) — метаданные/картинки, перекачиваемы. Alex: «метаданные не надо».
    • docker/rclone/config/backup.log (65 МБ) — растущий лог самого бэкапа, бессмысленно таскать в архив. Итого к бэкапу ≈ 700 МБ минус логи. Состав, который уезжает: hermes (249M — данные Hermes-агента: sessions, .env, auth.json, cron), radarr 119M, media-pipeline 90M, sonarr 82M, rclone/config 63M (минус лог), prowlarr 56M, transmission 12M, homeassistant 6.6M, portainer, scripts, hermes-build, cloudflared, watchtower, compose.sh.
  3. Целевой датасет: /mnt/RED_2TB/backup/kraken — внутри backup, уезжает в Mail.ru автоматически. ⚠️ Создавать как t610: parent /mnt/RED_2TB/backup, ACL Mode = Passthrough (не DISCARD!), ACL Type = NFSv4, права nas:nas 770.

  4. Расписание: крон на Kraken, ежедневно, время после t610 (03:30) — предлагается 04:00. Ротация 14 архивов. ⚠️ Питфолл: crontab не догоняет пропущенное окно. Если Kraken лежал — бэкап за тот день потерян. Вариант улучшения: @reboot + проверка «архив за сегодня есть?» (обсуждаемо).

  5. Транспорт: rsync c SSH-ключом. Отдельный pull/push-ключ (ограничить from= + no-pty на стороне TrueNAS). Ключ хранить в /mnt/RED_2TB/backup/kraken/.ssh/ (владелец nas, как t610 — питфолл №9: ~nas/.ssh недоступен). ⚠️ Kraken пишет как юзер в authorized_keys TrueNAS. Нужен юзер с правом записи в backup/kraken (или nas).

  6. Скрипт: на Kraken (/home/kraken/backup-to-truenas.sh), tar + rsync. Лог рядом.

⚠️ Проблемы, которые надо решить при реализации

# Проблема Решение
1 nas (uid 1000 на TrueNAS) vs юзер на Kraken — разные uid Ключ с from= + запись в backup/kraken от нужного владельца; либо chown nas:nas
2 У Kraken нет ключа для TrueNAS (в ~/.ssh только id_ed25519 от другого) Сгенерировать отдельный ключ kraken-backup-push, pub → authorized_keys TrueNAS
3 Mail.ru переполнен Не блокирует доставку на TrueNAS. Разбираться отдельно (вне этой задачи)
4 Ротация на стороне Kraken vs TrueNAS Делать ротацию на TrueNAS (там архивы), rm старых
5 backup.log 65 МБ растёт Исключить из tar (--exclude) + рассмотреть ротацию самого лога

✅ ШАГ 7 — ВЫПОЛНЕН (2026-09-20)

Сделано: строка 0 3 * * 0 /config/rclone/backup.sh ... в /config/rclone/crontab контейнера rclone закомментирована (#0 3 * * 0 ...), применено через crontab /config/rclone/crontab.

Проверено:

  • docker exec rclone crontab -l → строка с #
  • crontab -l | grep -v '^#' | grep -v '^$' → пусто (активных задач нет)
  • Контейнер rclone — Up, crond -f -l 8 жив
  • backup.sh не тронут (только расписание отключено) — при необходимости легко вернуть

Откат: снять # + sudo docker exec rclone crontab /config/rclone/crontab. Бэкап: /home/kraken/backups/rclone-disable-20260920-120606/.

Причина отключения: устранение дублирования и переполнения Mail.ru (507). Теперь Kraken идёт в облако только через TrueNAS.

🔁 Проверка reboot-безопасности (2026-09-20, после фикса гонки)

Alex выключил Kraken (sudo shutdown -h now). Фикс mount-race подтверждён живым reboot'ом: после включения все контейнеры поднялись сами — docker ps не пуст (12 Up, включая cloudflared, xray-reverse-bridge, rclone, jellyfin). Ручных docker start не потребовалось.

Что проверять после каждого reboot:

ssh kraken 'docker ps -q | wc -l'          # ожидаем ~12, не 0

Если 0 — гонка вернулась, смотреть systemctl show docker -p RequiresMountsFor (должно быть непусто).

⚠️ Крон не догоняет пропущенное окно. Пока Kraken лежал, прогон 04:00 пропускается без компенсации. Если это критично — добавить @reboot-строку с проверкой «есть ли архив за сегодня».

Шаги реализации (все 7 выполнены)

  1. ✅ Ключ kraken-backup-push (ed25519) на Kraken → pub на TrueNAS через midclt call user.update 72.
  2. ✅ Датасет /mnt/RED_2TB/backup/kraken (Passthrough, NFSv4, nas:nas 770).
  3. ✅ Скрипт на Kraken (/home/kraken/kraken-backup-to-truenas.sh): tar (exclude jellyfin, *.log) → rsync на TrueNAS.
  4. ✅ Ротация 14 архивов (на TrueNAS).
  5. ✅ Крон на Kraken: /etc/cron.d/kraken-backup, 0 4 * * * root.
  6. ✅ Живой прогон (165 МБ, 36985 файлов, размер совпал).
  7. ✅ Старый бэкап Kraken → Mail.ru отключён.

Примечание про from= в authorized_keys: изначально планировалось ограничить ключ по IP, но внешний IP Kraken динамический (92.62.70.9, в доке был .41) → from= не ставить, иначе бэкап умрёт при смене IP. Ограничения через API user.update всё равно не выставляются — ключ пишется «голым».

Проверка результата

# 1) архив появился на TrueNAS
ssh truenas_admin@mallexxx.duckdns.org 'ls -la /mnt/RED_2TB/backup/kraken/'
# 2) лог прогона (на Kraken)
ssh kraken 'sudo tail -20 /home/kraken/kraken-backup.log'
# 3) уезжает в облако (после вс 03:00)
ssh truenas_admin@mallexxx.duckdns.org 'docker exec rclone tail -30 /config/rclone/backup.log'

Открытые вопросы (не блокируют бэкап)

  • Mail.ru переполнен (507 Insufficient Storage с 13.09). backup/kraken доедет до облака только после освобождения места. TrueNAS-часть работает независимо от этого.
  • Лог backup.log контейнера rclone = 65 МБ и растёт — исключён из архива, но стоит рассмотреть ротацию самого лога.

Связанные заметки