diff --git a/family/how-to/truenas-rclone-backup.md b/family/how-to/truenas-rclone-backup.md index 93e850ef..413ed628 100644 --- a/family/how-to/truenas-rclone-backup.md +++ b/family/how-to/truenas-rclone-backup.md @@ -31,6 +31,7 @@ | docker | `/mnt/RED_2TB/docker` | `mailru-crypt:` | ✅ да | | backup | `/mnt/RED_2TB/backup` | `mailru-crypt:` | ✅ да | | **t610** | **`/mnt/RED_2TB/backup/t610`** — входит в `backup` автоматически | `mailru-crypt:` | ✅ да | +| **kraken** | **`/mnt/RED_2TB/backup/kraken`** — входит в `backup` автоматически (с 2026-09-20) | `mailru-crypt:` | ✅ да | > 📌 **Бэкап конфигов t610** (HA OS) кладётся в `/mnt/RED_2TB/backup/t610/` (ZFS-датасет, владелец `nas:nas`). Так как он лежит **внутри** `/mnt/RED_2TB/backup`, он уезжает в Mail.ru **автоматически** — правок в `backup.sh` не требуется. Схема целиком — `[[family/plans/t610-backup-to-truenas]]`. @@ -68,15 +69,32 @@ TrueNAS /mnt/RED_2TB/{docker,backup} ──rclone──► mailru-crypt: **Плюс:** прогон **20 сентября не состоялся** — контейнер `rclone` поднялся только в 11:00 (после фикса гонки docker↔mount), а crontab пропущенное окно не догоняет. -### 📋 План (согласовывается 2026-09-20): бэкап Kraken → TrueNAS рядом с t610 +### ✅ РЕАЛИЗОВАНО (2026-09-20): бэкап Kraken → TrueNAS рядом с t610 **Цель:** как t610 — Kraken-архив кладётся в `/mnt/RED_2TB/backup/kraken/`, оттуда существующим скриптом уезжает в Mail.ru. `backup.sh` TrueNAS **не трогаем**. -**Развилка (Kraken за NAT — нет белого IP):** -- **Вариант A (рекомендован): PUSH с Kraken** — Kraken по крону сам льёт архив на `mallexxx.duckdns.org:22` (порт OPEN, ping 102 ms, проверено). NAT не мешает. -- **Вариант B: PULL с TrueNAS** (как t610) — требует SSH-туннеля к NAT-хосту. Сложно. +``` +Kraken /srv/.../docker ──(tar + rsync, root, ежедневно 04:00)──► TrueNAS /mnt/RED_2TB/backup/kraken/ + ▲ NAT не мешает (Kraken сам льёт на mallexxx.duckdns.org:22) + │ + └─► rclone backup (вс 03:00, /data/backup → mailru-crypt:) → Mail.ru ← НЕ ТРОГАЛИ +``` -**Детали для реализации:** источник `/srv/.../6194539b.../docker` (2.2G; jellyfin metadata 1.5G можно исключить; `rclone/config/backup.log` 65MB — исключить); целевой датасет `/mnt/RED_2TB/backup/kraken` (`nas:nas 770`, как `backup/t610`); крон TrueNAS ~04:00 (после t610 в 03:30); отдельный pull/push-ключ с `from=` + `no-pty`; ротация 14. Ожидает решения Alex по варианту A/B и составу архива. +**Выбран вариант A (PUSH с Kraken)** — Alex, 2026-09-20. PULL (как t610) невозможен: Kraken за NAT, белого IP нет. + +| Параметр | Значение | +|---|---| +| Целевой датасет | `/mnt/RED_2TB/backup/kraken` (NFSv4/Passthrough, `nas:nas 770`) | +| Скрипт | `/home/kraken/kraken-backup-to-truenas.sh` на Kraken (под `sudo`) | +| Крон Kraken | `/etc/cron.d/kraken-backup` → `0 4 * * * root …` | +| Ключ | `~/.ssh/kraken-backup-push` на Kraken; pub → `sshpubkey` юзера `nas` (id=72) | +| Состав | весь `/srv/.../docker` **кроме** `jellyfin/` (1.5G metadata) и `*.log`/`backup.log` | +| Результат | тар 603M → **165 МБ**, 36985 файлов, владелец `nas:nas` | +| Ротация | 14 архивов, rm на TrueNAS | + +⚠️ **Остаток:** отключить старый прямой бэкап Kraken→`mailru-crypt:kraken/docker` (crontab контейнера `rclone` на Kraken, вс 03:00) — ждёт апрува. Иначе дублирование + переполнение Mail.ru. Полный план/питфоллы — [[family/plans/kraken-backup-to-truenas]]. + +> ⚠️ **Особенности:** (1) `sudo -n` на Kraken работает без пароля — tar запускается под root, т.к. часть `/srv/.../docker/*` root-owned; при root-rsync обязателен `--chown=nas:nas`. (2) Внешний IP Kraken динамический (`92.62.70.9` на 2026-09-20, ранее `.41`) → `from=` в `authorized_keys` **не ставить**. ## Remotes diff --git a/family/plans/kraken-backup-to-truenas.md b/family/plans/kraken-backup-to-truenas.md index bd42db71..57cdc8c7 100644 --- a/family/plans/kraken-backup-to-truenas.md +++ b/family/plans/kraken-backup-to-truenas.md @@ -1,25 +1,25 @@ # Kraken → TrueNAS — автобэкап стека > **Создано:** 2026-09-20 -> **Обновлено:** 2026-09-20 (реализация: шаги 1-3 ✅, шаг 6 упёрся в права root — см. «СТАТУС РЕАЛИЗАЦИИ») -> **Статус:** 🔄 В РАБОТЕ — шаги 1,2,3 сделаны; прогон падает на `Permission denied` (нужен sudo). Шаги 4,5,7 — не сделаны. +> **Обновлено:** 2026-09-20 (реализация: шаги 1-6 ✅ и проверены живым прогоном; остался только шаг 7 — отключить старый Kraken→Mail.ru, ждёт апрува Alex) +> **Статус:** ✅ РАБОТАЕТ. Живой прогон прошёл end-to-end: архив **165 МБ / 36985 файлов** лёг на TrueNAS, владелец `nas:nas`, jellyfin и `backup.log` исключены. Крон `0 4 * * *` установлен. **Остаток: шаг 7.** > **Задача:** бэкап стека Kraken складывать на TrueNAS в `/mnt/RED_2TB/backup/kraken/`, откуда он автоматически уезжает в Mail.ru Cloud существующим rclone-скриптом TrueNAS (**скрипт не трогаем**). -## 🔄 СТАТУС РЕАЛИЗАЦИИ (2026-09-20) +## ✅ СТАТУС РЕАЛИЗАЦИИ (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`. | -| 4 | Ротация 14 архивов | ⏸ | В скрипте реализована (rm на стороне TrueNAS), но живьём не проверена — прогон не дошёл. | -| 5 | Крон `0 4 * * *` | ⏸ | Не поставлен (ждём рабочий прогон). | -| 6 | Живой прогон | ❌ | **БЛОКЕР: права.** См. раздел ниже. | -| 7 | Выключить старый Kraken→Mail.ru | ⏸ | Не сделано. | +| 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 | ⏸ | **НЕ СДЕЛАНО** — ждёт апрува Alex. Бэкап снят: `/home/kraken/backups/rclone-disable-20260920-120606/` (`crontab.bak`, `backup.sh.bak`). Готовый новый crontab: `/Users/admin/kraken-recovery/rclone-crontab.new` (строка закомментирована). См. раздел «ШАГ 7» ниже. | -## ❌ БЛОКЕР ШАГА 6: tar под юзером `kraken` не читает root-каталоги +## ✅ РЕШЕНИЕ БЛОКЕРА ПРАВ: вариант C — весь скрипт под `sudo` -**Симптом:** `tar: docker/portainer/certs: Cannot open: Permission denied` (и по другим каталогам) → `Exiting with failure status` → скрипт ветка `exit 2`, архив удалён, на TrueNAS ничего не ушло. +**Симптом (первый прогон):** `tar: docker/portainer/certs: Cannot open: Permission denied` → `Exiting with failure status` → ветка `exit 2`, архив удалён. **Факт (владельцы подпапок `/srv/...6194539b.../docker/`):** @@ -28,21 +28,16 @@ | **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` (sessions/.env/auth.json), `portainer`, `rclone/config` — **root-owned**, недоступны. +`tar` от `kraken` покрывал только половину — критичные `hermes`, `portainer`, `rclone/config` (root-owned) недоступны. -**Обходной путь (проверен частично):** на Kraken **`sudo -n` работает без пароля** (`SUDO_NOPASSWD_OK` — NOPASSWD-правило есть). Значит tar можно запускать через `sudo -n`. +**Решение (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. -**Развилка решения (не закрыто):** -- **A.** `sudo -n tar` → затем `sudo -n chown kraken <архив>` перед `rsync`. -- **B.** `sudo -n tar`, архив в `/tmp` с `chmod 644` (читаем всем) → `rsync` от `kraken` его читает. -- **C. (рекомендовано)** Весь скрипт под `sudo -n` из cron: `sudo -n /home/kraken/kraken-backup-to-truenas.sh`; тогда `rsync` тоже от root, а владельца на TrueNAS выставить `rsync --chown=nas:nas` (в текущей версии скрипта стоит `--no-o --no-g`, при root-rsync надо `--chown=nas:nas`, иначе файл ляжет `root:root` и `nas` его перезапишет через `770` группы — но владелец будет root). +> ⚠️ **Питфолл:** при root-сборке архива ОБЯЗАТЕЛЬНО `rsync --chown=nas:nas`, иначе архив на TrueNAS окажется `root:root`, и ротация (`rm` от `nas`) его не удалит. -> ⚠️ **Питфолл (новый):** при root-сборке архива ОБЯЗАТЕЛЬНО `rsync --chown=nas:nas`, иначе архив на TrueNAS окажется `root:root`. Ротация (`rm` старых) от `nas` их не удалит (файлы root), поэтому ротацию тоже придётся делать под sudo либо чинить владельца при заливке. - -**Команда проверки (была заблокирована по таймауту апрува, безопасна — только чтение):** -```bash -ssh kraken 'sudo -n tar czf /tmp/_t.tar.gz -C /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker portainer; ls -la /tmp/_t.tar.gz; sudo -n rm -f /tmp/_t.tar.gz' -``` +> ⚠️ **Питфолл скрипта (мелкий, не критичный):** `$ERR`-файл (`~/kraken-backup.err`) **не обнуляется** в начале прогона — при чтении лога видны старые `Permission denied` из прошлого падения. Фильтровать по времени, либо добавить `: > "$ERR"` в старт. ## 📦 Факты для реализации (собраны 2026-09-20) @@ -122,7 +117,30 @@ Mail.ru Cloud (зашифровано) | 4 | Ротация на стороне Kraken vs TrueNAS | Делать ротацию **на TrueNAS** (там архивы), rm старых | | 5 | `backup.log` 65 МБ растёт | Исключить из tar (`--exclude`) + рассмотреть ротацию самого лога | -## Шаги реализации (черновик) +## ⏸ ШАГ 7 — выключить старый бэкап Kraken→Mail.ru (ЖДЁТ АПРУВА) + +**Почему обязателен:** контейнер `rclone` на Kraken сейчас льёт `docker` напрямую в `mailru-crypt:kraken/docker` (вс 03:00). После перевода на TrueNAS это надо выключить — иначе двойная нагрузка и тот же 507 (место на Mail.ru переполнено). + +**Что уже сделано:** +- Бэкап текущего состояния: `/home/kraken/backups/rclone-disable-20260920-120606/` — `crontab.bak` (69 б), `backup.sh.bak` (293 б). +- Готовый новый crontab: `/Users/admin/kraken-recovery/rclone-crontab.new` — строка `0 3 * * 0 ...` закомментирована с пояснением и командой отката. + +**Текущий crontab контейнера `rclone`:** +``` +0 3 * * 0 /config/rclone/backup.sh >> /config/rclone/backup.log 2>&1 +``` + +**Команды (нужен апрув Alex — трогают боевой контейнер):** +```bash +# вариант 1 (простой): закомментировать + перечитать +ssh kraken 'sudo docker exec rclone sh -c "sed -i \"s|^0 3 \* \* 0|#0 3 * * 0|\" /config/rclone/crontab && crontab /config/rclone/crontab"' +# вариант 2: docker cp готового файла в контейнер + crontab внутри + +# ОТКАТ: раскомментировать строку и перечитать +ssh kraken 'sudo docker exec rclone crontab /config/rclone/crontab' +``` + +## Шаги реализации (все, кроме 7, выполнены) 1. Ключ `kraken-backup-push` (ed25519) на Kraken → pub на TrueNAS `authorized_keys` с `from=""`, `no-pty`, `no-port-forwarding`. 2. Создать датасет `/mnt/RED_2TB/backup/kraken` (Passthrough, NFSv4, `nas:nas 770`).