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

171 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: t610 → TrueNAS автобэкап конфигов
created: 2026-09-14
updated: 2026-09-14
type: tech
namespace: family
tags: [truenas, t610, backup, smb, ssh, cron, ha-os]
related:
- "[[family/plans/t610-home-automation]]"
- "[[family/how-to/truenas-access]]"
- "[[family/how-to/truenas-rclone-backup]]"
- "[[family/how-to/gitea-config]]"
---
# t610 → TrueNAS — автобэкап конфигов
> **Задача (п.8 / A3 плана [[family/plans/t610-home-automation]]):** конфиги t610 (HA OS) регулярно складывать на TrueNAS, откуда они автоматически уезжают в Mail.ru Cloud через уже существующий rclone-бэкап TrueNAS.
## Схема (принята 2026-09-14)
```
t610 (/config, /addons, /addon_configs)
│ tar
TrueNAS pull (крон от юзера nas, ssh с ключом)
/mnt/RED_2TB/backup/t610/ ← ZFS-датасет, владелец nas:nas, 770
│ SMB-шара "t610" (id=3) — для ручного доступа Alex с Mac/телефона
rclone backup.sh (воскресенье 03:00, контейнер rclone)
│ run_sync "backup" /data/backup "mailru-crypt:"
Mail.ru Cloud (зашифровано)
```
**Ключевые решения и почему так:**
1. **Транспорт — PULL с TrueNAS, а не push с t610.** На t610 не надо ставить креды TrueNAS и держать лишние журналы; TrueNAS знает, где лежит архив. Крон TrueNAS работает под юзером **`nas`**, не под `truenas_admin` и не под root.
2. **Пользователь `nas` (uid 1000) — владелец датасета и ключа.** `truenas_admin` — админ (`zsh`, `builtin_administrators`) — держать его ключ на чужом хосте неправильно (Alex: «думаешь админом бэкап делать?»). `nas` — штатный NAS-юзер, `nas_users` gid=3000.
3. **Целевой датасет — `/mnt/RED_2TB/backup/t610`** (именно датасет, не папка). Причина: он **попадает внутрь `/mnt/RED_2TB/backup`**, который уже целиком уходит в rclone (`run_sync "backup" /data/backup "mailru-crypt:"`). **Ничего в `backup.sh` править не надо** — файлы уезжают в облако автоматически. (Альтернативы `storage/` или `docker/` требовали бы правки root-owned `backup.sh`.)
4. **SMB-шара `t610`** — не для доставки (HA OS не умеет SMB-пуш), а **для ручного доступа Alex** к бэкапам с Mac/телефона без ssh.
5. **Ключ ограничен** на стороне t610: `from="192.168.2.197"` + `no-port-forwarding,no-pty,no-X11-forwarding,no-agent-forwarding`. Т.е. даже при утечке — только стянуть архив, шелла нет.
## Что сделано (2026-09-14)
| # | Шаг | Статус | Детали |
|---|-----|--------|--------|
| 1 | Датасет `RED_2TB/backup/t610` | ✅ | UI → Storage → Datasets → Add Dataset; parent `/mnt/RED_2TB/backup`, Name `t610`, Type Filesystem |
| 2 | Права датасета | ✅ | `chown nas:nas` + `chmod 770` (Alex, System → Shell) |
| 3 | SMB-шара | ✅ | `id=3 name=t610 path=/mnt/RED_2TB/backup/t610 enabled=true ro=false` |
| 4 | ssh-ключ для pull | ✅ | Создан на Mac: `~/tmp-t610/backup-key/t610_backup_ed25519` (+`.pub`), ed25519, без пароля, comment `t610-backup-pull`, fingerprint `SHA256:PKDB/sTjM8WFitIjSG+vT27x1TOY3F2Vi6y8YFwK5wo` |
| 5 | Публичный ключ на t610 | ✅ | `/root/.ssh/authorized_keys` (+1 строка, было 1 — ключ Alex). Бэкап: `authorized_keys.bak-20260914-210532` |
| 6 | Приватный ключ на TrueNAS | ✅ | `/mnt/RED_2TB/storage/nas/.ssh/id_ed25519` (+ `config` с хостом-алиасом `t610-backup`), права `nas:nas 600` |
| 7 | Скрипт бэкапа | ⏳ | Не написан |
| 8 | Крон-задача под `nas` | ⏳ | Не создана (`midclt call cronjob.create`, сейчас cron-задач на TrueNAS **нет**) |
| 9 | Живой прогон + проверка архива | ⏳ | Не делался |
**Путь для архива на TrueNAS:** `/mnt/RED_2TB/backup/t610/` (пока пусто).
## Ключевые питфоллы (найдены в этой сессии)
### 1. 🔴 `from="192.168.2.197"` — Mac НЕ подходит для проверки ключа
Mac заходит на t610 как **`192.168.2.157`** (через NAT Rasputin), а не как `.197`. Поэтому `ssh -i <ключ> root@192.168.2.176` **с Mac всегда даёт `Permission denied (publickey)`** — это **правильное поведение** ограничения, а не поломка ключа. Проверять pull-ключ **только с TrueNAS**:
```bash
ssh -F /mnt/RED_2TB/storage/nas/.ssh/config t610-backup 'echo ok'
```
> ⚠️ Это тот же питфолл `.157` = NAT Rasputin, что уже задокументирован для логов HA.
### 2. 🔴 `Failed to load datasets: /mnt/.ix-apps/app_configs` — ломает ВЕСЬ UI датасетов
**Симптом:** UI TrueNAS (Storage → Datasets, Apps, Datasets) — «Failed to load datasets», дерево датасетов не открывается, невозможно создать датасет/шару.
**Причина:** после пересоздания пула (2026-08-21) каталог `app_configs` внутри датасета `ix-apps` не был создан. UI на старте **безусловно** читает `/mnt/.ix-apps/app_configs` и валит всё дерево.
**Факты:** `RED_2TB/ix-apps` (8.29G) существует, смонтирован на `/mnt/.ix-apps`, `docker.config``pool=RED_2TB, dataset=RED_2TB/ix-apps` (пул Apps выбран корректно). Внутри был только `docker/` (`drwx--x--- root root`). Choose Pool → **не помогло**.
**Фикс (под root, WebUI → System → Shell):**
```bash
mkdir -p /mnt/.ix-apps/app_configs
```
> 📌 **Проверено:** фикс сработал, UI ожил. `mkdir` — shell-команда, не действие в UI.
### 3. 🔴 `aclmode: DISCARD aclmode may not be set for NFSv4 acl type` при создании датасета
**Причина:** в форме создания датасета выставлен ACL Mode = `DISCARD`, что **запрещено** при `acltype=NFSv4` (весь пул RED_2TB на NFSv4).
**Фикс:** **ACL Mode = `Passthrough`** (или пусто — подставится `passthrough`), ACL Type = `NFSv4`. Результат: `RED_2TB/backup/t610``aclmode=passthrough, acltype=nfsv4`.
### 4. 🔴 POSIX `setfacl` на NFSv4-датасете НЕ работает
```
setfacl -m user:truenas_admin:rwx /mnt/RED_2TB/backup/t610
→ setfacl: Operation not supported
```
При `acltype=nfsv4` POSIX-setfacl не поддерживается. Менять владельца/права — только **`chown` под root** или **UI → Datasets → Edit → Permissions/ACL** (NFSv4-редактор).
### 5. Шары SMB на TrueNAS хранятся в registry, НЕ в `/etc/smb4.conf`
`/etc/smb4.conf` содержит только `[global]` + `include = registry` + `registry shares = True`. Поэтому `grep имя_шары /etc/smb4.conf` и `testparm` **ничего не находят** — это не признак, что шара не создалась. Проверять через `midclt call sharing.smb.query`.
> `testparm`/`smbclient -L` от `truenas_admin` дают `regdb_init: Permission denied` на `/var/run/samba-cache/registry.tdb` — проверка от непривилегированного юзера **неинформативна**.
### 6. `zfs`/`zpool` не в PATH у `truenas_admin`
`zfs list` → пусто/`command not found`. Вызывать по абсолютному пути: **`/sbin/zfs`**, **`/sbin/zpool`**. (Иначе можно ошибочно решить, что датасетов нет.)
### 7. `truenas_admin` не может писать в `~nas` — и `.ssh` надо чинить chown'ом
`~nas` = `/mnt/RED_2TB/storage/nas` (`drwxrwx--- truenas_admin`). `truenas_admin` файлы туда **положить может**, но создаёт их владельцем `truenas_admin``nas` их не прочитает. Поэтому после укладки ключа обязателен `chown -R nas:nas ~nas/.ssh`.
### 8. Пароль `1316261` — ❌ НЕ от TrueNAS
В доке `[[family/how-to/truenas-access]]` строка «Пароль root: `1316261`» **ошибочна** для TrueNAS. Alex: «Это не пароль от truenas». `1316261` — пароль от OpenWrt-роутера `192.168.2.2` (там он и правильный). **Для TrueNAS root-операций использовать WebUI → System → Shell** (работает под root, пароль не нужен).
## Команды (для воспроизведения)
```bash
# ─── Создание ключа (Mac) ───
ssh-keygen -t ed25519 -N '' -C 't610-backup-pull' -f ~/tmp-t610/backup-key/t610_backup_ed25519
# ─── Публичный ключ на t610 (с ограничениями) ───
KEYBODY=$(awk '{print $2}' ~/tmp-t610/backup-key/t610_backup_ed25519.pub)
ENTRY="from=\"192.168.2.197\",no-port-forwarding,no-pty,no-X11-forwarding,no-agent-forwarding ssh-ed25519 ${KEYBODY} t610-backup-pull"
ssh root@192.168.2.176 'cp -a /root/.ssh/authorized_keys /root/.ssh/authorized_keys.bak-$(date +%Y%m%d-%H%M%S)'
printf '%s\n' "$ENTRY" | ssh root@192.168.2.176 'cat >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys'
# ─── Приватный ключ на TrueNAS в ~nas/.ssh ───
scp ~/tmp-t610/backup-key/t610_backup_ed25519 truenas_admin@mallexxx.duckdns.org:/tmp/
ssh truenas_admin@mallexxx.duckdns.org '
cp /tmp/t610_backup_ed25519 /mnt/RED_2TB/storage/nas/.ssh/id_ed25519
cat > /mnt/RED_2TB/storage/nas/.ssh/config <<EOF
Host t610-backup
HostName 192.168.2.176
User root
Port 22
IdentityFile /mnt/RED_2TB/storage/nas/.ssh/id_ed25519
IdentitiesOnly yes
StrictHostKeyChecking no
EOF'
# ─── Под ROOT (WebUI → System → Shell) ───
mkdir -p /mnt/.ix-apps/app_configs
chown nas:nas /mnt/RED_2TB/backup/t610 && chmod 770 /mnt/RED_2TB/backup/t610
chown -R nas:nas /mnt/RED_2TB/storage/nas/.ssh && chmod 700 /mnt/RED_2TB/storage/nas/.ssh \
&& chmod 600 /mnt/RED_2TB/storage/nas/.ssh/id_ed25519 /mnt/RED_2TB/storage/nas/.ssh/config
# ─── SMB-шара (от truenas_admin, midclt) ───
midclt call sharing.smb.create '{"purpose":"DEFAULT_SHARE","path":"/mnt/RED_2TB/backup/t610",
"name":"t610","comment":"Backup t610 (HA OS) configs","ro":false,"browsable":true,
"guestok":false,"timemachine":false,"enabled":true}'
# ─── Дамп шар ПЕРЕД правкой (обязательно) ───
midclt call sharing.smb.query > /mnt/RED_2TB/storage/shares-before-$(date +%Y%m%d-%H%M%S).json
# ─── Проверка pull-ключа — ТОЛЬКО С TrueNAS ───
ssh -F /mnt/RED_2TB/storage/nas/.ssh/config t610-backup 'echo ok'
```
## Состав бэкапа t610 (план)
Из `/config`: `configuration.yaml`, `automations.yaml`, `scripts.yaml`, `scenes.yaml`, `secrets.yaml`, `.storage/` (**без** `home-assistant_v2.db*` — это большая БД), `go2rtc.yaml`, `zigbee2mqtt/`.
Плюс `/addons/{mbusd,modbus-bridge,ustreamer}` (код + `data/config.template.tmpl` — там правка реле slave 104), `/addon_configs/{zigbee2mqtt,nodered}` (flows/settings).
Плюс локально `Caddyfile` (root-owned, лежит на Mac в `~/tmp-caddy/Caddyfile.new`).
**Ротация:** хранить N последних архивов (N согласовать).
## Связанный синк в git (сделан в этой же сессии)
Репозиторий **`~/Automation/HA-ZONT-Modbus`** → Gitea (`git_admin/HA-ZONT-Modbus`, private).
Коммит **`9d31118`** «Sync from t610 prod: automations device_ids, go2rtc camera, bridge relay» — запушен, remote SHA = local SHA.
| Файл | Что синкнуто |
|---|---|
| `homeassistant/configuration.yaml` | http-блок убран (перенесён в `.storage/http`); **`modbus.host` `192.168.2.197``192.168.2.176`** |
| `homeassistant/automations.yaml` | перегенерированы `device_id` (миграция на t610), `light.0xa4c13882a4b42db0``light.bed_dimmer`, +триггер `illuminance`, +условие `is_occupied` (ночной свет душевой) |
| `homeassistant/go2rtc.yaml` | **НОВЫЙ** — камера go2rtc-hardware, ffmpeg H.264 + `rotate=90` |
| `config.yml` | +«Boiler controller power (Zigbee relay)» slave 104 / рег 1 |
| `modbus_ha_bridge.py` | уже совпадал (sha идентичен) |
| `scripts.yaml` | уже совпадал (sha идентичен) |
> 📌 Паттерн: **сначала сравнить прод↔репо по sha256, потом тащить только изменившееся.** Креды Gitea — `~/.git-credentials` (chmod 600) + `credential.helper=store`, remote — **чистый URL без токена**.