[2026-09-20] eagle: family/how-to/truenas-rclone-backup.md family/plans/kraken-backup-to-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-20 12:10:11 +06:00
1 parent 49e1c1a11f
commit 6cb187cee5
2 files changed
+64 -28

No files matched your search

+23 -5
View File
@@ -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
+41 -23
View File
@@ -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="<IP Kraken>"`, `no-pty`, `no-port-forwarding`.
2. Создать датасет `/mnt/RED_2TB/backup/kraken` (Passthrough, NFSv4, `nas:nas 770`).