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

284 lines
26 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, done]
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)
```
cron TrueNAS (юзер nas, 03:30 ежедневно)
└─ /mnt/RED_2TB/backup/t610/backup-t610.sh
└─ ssh t610-backup "tar czf - <14 путей>" → 605 КБ архив
└─ /mnt/RED_2TB/backup/t610/t610-config-<ts>.tar.gz (ротация 14)
└─ rclone (вс 03:00, контейнер) → mailru-crypt: (Mail.ru, шифровано)
```
### Что сделано
| # | Шаг | Статус | Детали |
|---|-----|--------|--------|
| 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/backup/t610/.ssh/id_ed25519`** (+ `config` с алиасом `t610-backup`), `nas:nas 600`. ⚠️ Итоговое место — **внутри `backup/t610`**, НЕ в `~nas/.ssh` (см. питфолл №9) |
| 7 | Скрипт бэкапа | ✅ | `/mnt/RED_2TB/backup/t610/backup-t610.sh` (v3, `nas:nas 755`) |
| 8 | Крон-задача под `nas` | ✅ | `cronjob` **id=3**, user=`nas`, `30 3 * * *`, enabled=true |
| 9 | Живой прогон + проверка архива | ✅ | 2 прогона: `OK ... (605504 bytes)`, `OK ... (605873 bytes)`, `.err` пустой |
| 10 | Проверка состава архива | ✅ | **111 файлов**; ключевые на месте: `configuration.yaml`, `automations.yaml`, `go2rtc.yaml`, `secrets.yaml`, `.storage/http` (фикс `trusted_proxies`), `addons/modbus-bridge/data/config.template.tmpl` (реле slave 104), `nodered/flows.json` |
| 11 | Выход в облако | ✅ | `run_sync "backup" /data/backup "mailru-crypt:"` в `backup.sh`; контейнер `rclone``Up 5 days`; правок не требовалось |
**Путь для архивов на TrueNAS:** `/mnt/RED_2TB/backup/t610/t610-config-<YYYYmmdd-HHMMSS>.tar.gz`, лог — `backup.log` рядом.
### Как проверять (без ожидания 03:30)
```bash
# лог + список архивов
ssh truenas_admin@mallexxx.duckdns.org 'cat /mnt/RED_2TB/backup/t610/backup.log; ls -la /mnt/RED_2TB/backup/t610/'
# статус задачи
ssh truenas_admin@mallexxx.duckdns.org 'midclt call cronjob.query "[[\"id\",\"=\",3]]" | jq -r ".[] | {id,user,enabled,command,schedule}"'
```
> ⚠️ **НЕ проверять через `midclt call cronjob.run`** — даёт ложный `exit 137`/`143`. См. питфолл №10.
### ⚠️ НЕ ЗАКРЫТО — что ещё стоит добавить в архив (обсуждалось 2026-09-14, вечер-15)
Alex задал вопрос: «что НЕ входит в архив, но что мы задолбаемся восстанавливать?». Ответ (проверено на живом t610):
| # | Что | Где лежит | Почему критично |
|---|-----|-----------|-----------------|
| 1 | 🔴 **Опции всех 11 аддонов** | `/data/options.json` внутри контейнера аддона + Supervisor API `/addons/<slug>/options` | mbusd (привязка `by-path`, гнездо 4), modbus-bridge (`usb-0:3`, **пароль mosquitto `mqtt1z3$`**, ZONT host/slave), zigbee2mqtt (**`network_key`** + порт `/dev/ttyACM0`), Node-RED (**крипто-секрет `0ce08a59caa2077e607b5f34044af0b0c`**, пароль админки), Mosquitto (user/pass), Terminal&SSH (`authorized_keys`) |
| 2 | 🔴 **Zigbee `network_key`** | в **опциях** аддона zigbee2mqtt (не в `/config/zigbee2mqtt/`) | `coordinator_backup.json` в архиве есть, но без `network_key` сеть **не поднять** — все устройства перепаривать |
| 3 | 🔴 **Node-RED `flows_cred.json`** | `/addon_configs/a0d7b954_nodered/` (не читается обычным листингом; секрет `$` — в опциях) | без крипто-секрета креды не расшифруются → **все ноды HA подключать заново** |
| 4 | 🟡 `home-assistant_v2.db` (9.2M) + `-wal` (4.1M) | `/config/` | история сенсоров, **статистика энергии**, климат. Бэкапить на живой системе рискованно (неконсистентность) — через SQLite backup API |
| 5 | 🟡 Файлы `*.bak-*` | `/config/` (6 config + 4 automations) | точки отката миграции, размер мизерный |
**Полный список аддонов t610 (проверено через Supervisor API):** `core_ssh`, `core_mosquitto`, `a0d7b954_nodered`, `core_samba` (stopped), `core_configurator`, `45df7312_zigbee2mqtt`, `local_mbusd`, `local_modbus-bridge`, `local_ustreamer` (stopped), `a889bffc_go2rtc` (stopped), `a889bffc_go2rtc-hardware`.
**Не нужно бэкапить:** `/config/.cache`, `deps`, `tts`, `.cloud` (пустые/кеш), `.HA_VERSION`, `home-assistant_v2.db-shm`.
**Решение (предложено, ожидает ответа Alex):** добавить в `backup-t610.sh` выгрузку опций аддонов через Supervisor API в JSON перед `tar`. Целевой размер архива ~10–15 МБ.
## Ключевые питфоллы (найдены в этой сессии)
### 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** (путь к конфигу — итоговый, см. питфолл №9):
```bash
ssh -F /mnt/RED_2TB/backup/t610/.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` — итог: ключ держим в `backup/t610/.ssh` (см. №9)
`~nas` = `/mnt/RED_2TB/storage/nas`. Промежуточная попытка класть ключ туда **провалилась** (см. №9) — итоговое место ключа: **`/mnt/RED_2TB/backup/t610/.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, пароль не нужен).
> 📌 Alex работает под root по SSH сам — **не предлагать ему WebUI-инструкции**, если он уже сказал, что у него есть root-shell.
### 9. 🔴 Ключ класть в `backup/t610/.ssh`, НЕ в `~nas/.ssh` — родительский `storage/` непроходим для `nas`
**Симптом:** `Can't open user config file /mnt/RED_2TB/storage/nas/.ssh/config: Permission denied` — при том что сам `.ssh` был `nas:nas 700`.
**Причина:** `nas` не может пройти **сквозь родителей**:
```
/mnt/RED_2TB/storage drwxr-x--- truenas_admin:truenas_admin ← nas не владелец, группы хватает только на r-x
/mnt/RED_2TB/storage/nas drwxrwx--- truenas_admin:truenas_admin ← nas не владелец и не в группе → нет x
/mnt/RED_2TB/storage/nas/.ssh drwx------ nas:nas ← сам в порядке, но путь закрыт
```
`truenas_admin`**не владелец** `~nas` (после chown), а группа имеет только `r-x`**создавать там файлы нельзя** (`mkdir: Permission denied`).
**Решение (root НЕ нужен):** `/mnt/RED_2TB/backup/t610``nas:nas 770`, группа имеет `rwx`, `truenas_admin` в группе `nas` → пишет свободно. Ключ и `config` кладутся туда, затем `chown nas:nas` (работает **без root**, т.к. `truenas_admin` — владелец созданных файлов):
```bash
mkdir -p /mnt/RED_2TB/backup/t610/.ssh
cp /tmp/bk_key /mnt/RED_2TB/backup/t610/.ssh/id_ed25519
# ... config ...
chown nas:nas /mnt/RED_2TB/backup/t610/.ssh/{config,id_ed25519} # ← БЕЗ root, работает
```
> 💡 **Урок:** `chown nas:nas` на **свои** файлы проходит без root. Root нужен только для чужих. Прежде чем просить Alex'а — проверить `ls -ld` по всей цепочке родителей и `touch` на запись.
### 10. 🔴 `midclt call cronjob.run` даёт ЛОЖНЫЙ `exit 137`/`exit 143` — не признак поломки скрипта
**Симптом:** задача падает за ~1 сек с `CronTask "..." exited with 137 (non-zero) exit status` — хотя скрипт рабочий.
**Причина:** middleware прибивает таск (SIGKILL=137 / SIGTERM=143), когда родительский job `cronjob.run` завершается раньше дочернего процесса. Это баг API-пути, а не скрипта.
**Как отличить:** смотреть **несколько** job'ов и **файловый лог скрипта**. Реальные ошибки скрипта видны как его собственные коды (`exit 2`, `exit 3`) + запись в `backup.log`/`.err`.
**Правильная проверка:** ставить задачу на `* * * * *`, **ждать реального срабатывания** и смотреть появившийся архив, потом вернуть расписание:
```bash
midclt call cronjob.update 3 '{"schedule":{"minute":"30","hour":"3","dom":"*","month":"*","dow":"*"}}'
```
> ⚠️ Не «проверять» циклом `sleep` вслепую — узнавать по факту появления файла/записи в логе.
### 11. 🔴 Список путей для `tar` через ssh: не передавать многострочной переменной
**Симптом:** `tar: empty archive` + `bash: line N: config/configuration.yaml: Permission denied` (пути выполняются как команды).
**Причина:** многострочная `$FILES`, подставленная в ssh-команду, интерпретируется **на удалённой стороне** как отдельные команды.
**Фикс:** список путей — **одной строкой прямо в ssh-команде**:
```sh
ssh -F "$SSHCFG" "$SSHHOST" 'tar czf - -C / config/configuration.yaml config/automations.yaml ...' > "$OUT"
```
### 12. `scp` поверх чужого файла не работает, но `mv` в групповом `rwx`-каталоге — работает
`scp` даёт `Permission denied` при перезаписи файла, принадлежащего `nas`. Обход: положить под новым именем и сделать `mv` (каталог `770` даёт группе `rwx`). ⚠️ После `mv` владелец/права **сбрасываются** на копирующего → обязателен `chmod 755` + `chown nas:nas`.
### 13. `cronjob.run` вызывается кроном как `midclt call cronjob.run <id> true` — задачи от `nas` работают
Проверено: `/etc/cron.d/middlewared` содержит `* * * * * root ... midclt call cronjob.run 2 true`. Системный `cron -f` + `busybox crond -f` живут. Задачи от `nas` **выполняются штатно** (job state=SUCCESS, файлы появляются) — «крон не работает» было ложной тревогой от проверки файла до первой минуты.
### 14. `set -u` + `exit` в циклах на zsh-стороне ломает проверки
Проверки через `ssh ... 'ls /path/*.tar.gz'` на **zsh**-цели дают `zsh:1: no matches found` и рвут цикл (скрипт выходит до `sleep`). Использовать `bash -c` на удалённой стороне или `test -f` / `ls -1 ... 2>/dev/null`.
## Команды (итоговые, воспроизведение)
```bash
# ─── 1. Создание ключа (Mac) ───
ssh-keygen -t ed25519 -N '' -C 't610-backup-pull' -f ~/tmp-t610/backup-key/t610_backup_ed25519
# fingerprint: SHA256:PKDB/sTjM8WFitIjSG+vT27x1TOY3F2Vi6y8YFwK5wo
# ─── 2. Публичный ключ на t610 (с ограничениями по IP и без шелла) ───
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'
# ─── 3. Приватный ключ на TrueNAS в backup/t610/.ssh (НЕ в ~nas/.ssh — см. питфолл 9) ───
scp ~/tmp-t610/backup-key/t610_backup_ed25519 truenas_admin@mallexxx.duckdns.org:/tmp/bk_key
ssh truenas_admin@mallexxx.duckdns.org '
mkdir -p /mnt/RED_2TB/backup/t610/.ssh
cp /tmp/bk_key /mnt/RED_2TB/backup/t610/.ssh/id_ed25519
chmod 600 /mnt/RED_2TB/backup/t610/.ssh/id_ed25519
cat > /mnt/RED_2TB/backup/t610/.ssh/config <<EOF
Host t610-backup
HostName 192.168.2.176
User root
Port 22
IdentityFile /mnt/RED_2TB/backup/t610/.ssh/id_ed25519
IdentitiesOnly yes
StrictHostKeyChecking no
EOF
chmod 600 /mnt/RED_2TB/backup/t610/.ssh/config
chown nas:nas /mnt/RED_2TB/backup/t610/.ssh /mnt/RED_2TB/backup/t610/.ssh/config /mnt/RED_2TB/backup/t610/.ssh/id_ed25519
'
# ─── 4. Под ROOT (ТОЛЬКО этот шаг требует root) ───
mkdir -p /mnt/.ix-apps/app_configs # лечит UI «Failed to load datasets»
chown nas:nas /mnt/RED_2TB/backup/t610 && chmod 770 /mnt/RED_2TB/backup/t610
groupmod -n nas -m truenas_admin 2>/dev/null || usermod -a -G nas truenas_admin # truenas_admin в группу nas
# ─── 5. SMB-шара (от truenas_admin, midclt) ───
midclt call sharing.smb.query > /mnt/RED_2TB/storage/shares-before-$(date +%Y%m%d-%H%M%S).json # ДАМП ПЕРЕД
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}'
# ─── 6. Скрипт бэкапа (v3) + права ───
scp ~/tmp-t610/backup-t610-v3.sh truenas_admin@mallexxx.duckdns.org:/mnt/RED_2TB/backup/t610/backup-t610.sh
ssh truenas_admin@mallexxx.duckdns.org '
chmod 755 /mnt/RED_2TB/backup/t610/backup-t610.sh
chown nas:nas /mnt/RED_2TB/backup/t610/backup-t610.sh'
# ─── 7. Крон-задача (id=3, юзер nas, 03:30 ежедневно) ───
midclt call cronjob.create '{"user":"nas","command":"/mnt/RED_2TB/backup/t610/backup-t610.sh",
"description":"Backup t610 HA configs","enabled":true,
"schedule":{"minute":"30","hour":"3","dom":"*","month":"*","dow":"*"},
"stdout":false,"stderr":false}'
# ─── 8. Проверка pull-ключа — ТОЛЬКО С TrueNAS ───
ssh -F /mnt/RED_2TB/backup/t610/.ssh/config t610-backup 'echo ok'
```
## Состав бэкапа t610 (✅ фактический — 111 файлов, ~605 КБ)
Из `/config`: `configuration.yaml`, `automations.yaml`, `scripts.yaml`, `scenes.yaml`, `secrets.yaml`, `.storage/` (**без** `home-assistant_v2.db*`), `go2rtc.yaml`, `zigbee2mqtt/`, `www/`.
Плюс `/addons/{mbusd,modbus-bridge,ustreamer}` (код + `data/config.template.tmpl` — правка реле slave 104), `/addon_configs/{45df7312_zigbee2mqtt,a0d7b954_nodered}` (flows/settings).
**Ротация:** `KEEP=14` архивов (`t610-config-<ts>.tar.gz`).
> ⚠️ НЕ входит (и стоит добавить): **опции аддонов**, `network_key` Zigbee, `flows_cred.json`, `home-assistant_v2.db`. Детали — раздел «НЕ ЗАКРЫТО» выше.
### Скрипт (суть)
```sh
DEST=/mnt/RED_2TB/backup/t610 ; SSHCFG=$DEST/.ssh/config ; SSHHOST=t610-backup ; KEEP=14
# tar собирается НА t610, пути — ОДНОЙ СТРОКОЙ (питфолл 11)
ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=15 "$SSHHOST" \
'tar czf - -C / config/configuration.yaml config/automations.yaml ... ' > "$OUT" 2> "$DEST/.err"
# проверка размера <1024 → .BAD + exit 2 ; ssh-ошибка → exit 3 ; ротация до KEEP
```
Скрипт на Mac (рабочие копии): `~/tmp-t610/backup-t610-v3.sh`, `~/tmp-t610/backup-t610.sh`.
Бэкап-ключ на Mac: `~/tmp-t610/backup-key/t610_backup_ed25519`. Скрипты: `mk_backup_key.sh`, `add_backup_key_t610.sh`, `push_backup_key_truenas.sh`, `move_key_to_backup.sh`, `cleanup_backup.sh`, `phase1_diag.sh`, `phase2_key.sh`, `wait_archive.sh`.
## Связанный синк в 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 без токена**.