Files
obsidian-vault/family/how-to/truenas-infrastructure.md
T

642 lines
72 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.
# TrueNAS — инфраструктура
> ✅ **ДОМАШНЯЯ АВТОМАТИЗАЦИЯ ПЕРЕНЕСЕНА НА HP t610 (2026-09-14).** HA, zigbee2mqtt, mosquitto, mbusd, modbus-bridge **и flows Node-RED** переехали на **t610** (HA OS, `192.168.2.176`). Единый документ по t610 — [[family/plans/t610-home-automation]]. **✅✅ TrueNAS-стек автоматизации ПОГАШЕН 2026-09-14 (ночная сессия, §5-кватер-Л плана):** `homeassistant`, `mbusd`, `mosquitto`, `nodered`, `zigbee2mqtt`, `modbus-bridge`, `ser2net` → `docker stop` + `docker update --restart=no` (**НЕ удалены**, папки `docker/*` целы — откат = `docker start` + `--restart=unless-stopped`). Проверено: порты 502/1883/8123/1880 свободны, `mallexxx.*` = 200, MQTT на t610 живой. Причина переноса: TrueNAS на пределе RAM (17/21 ГБ).
>
> **2026-09-14 (вечер-2, обновлено вечер-13) — Caddy ПЕРЕКЛЮЧЁН, Node-RED ПЕРЕНЕСЁН:**
> - **Caddy НЕ переносился и не будет:** 17 из 20 доменов `*.mallexxx.duckdns.org` — сервисы самого TrueNAS (immich, gitea, jellyfin, radarr, webdav, transmission, portainer…). Перенос Caddy на t610 положил бы их при падении t610. **✅ ПРАВКА ЗАВЕРШЕНА (факт-проверка 2026-09-14 вечер-13):** в `Caddyfile` остался **ОДИН** upstream на t610 — `mallexxx.duckdns.org` → `192.168.2.176:80` (HA, HTTP 200 ✅). **УБРАНЫ совсем:** `cam.mallexxx.duckdns.org` (камера на t610 по RTSP — домен не нужен) и `nodered.mallexxx.duckdns.org` (Node-RED — через ingress HA, решение Alex «оставляем так»). Caddyfile: `/mnt/RED_2TB/docker/caddy/Caddyfile` (root-owned — агент только стейджит в `/tmp/`, подменяет Alex), бэкап `Caddyfile.bak-20260914`. Порты контейнера: `8088:80`, `8443:443`; DNAT на роутере `192.168.2.2`: `wan:80→192.168.2.197:8088`, `wan:443→192.168.2.197:8443`.
> - **Node-RED flows перенесены на t610** (`/addon_configs/a0d7b954_nodered/flows.json`, 68 узлов, узел `server` → `addon: true`). **Наружу НЕ выпущен** (порт-маппинг при `host_network: true` глушится, снимается только в UI) — доступ через ingress HA. Node-RED в докере TrueNAS (`/mnt/RED_2TB/docker/nodered/`) **✅ ПОГАШЕН 2026-09-14** (`stop` + `--restart=no`; папка цела, откат = `docker start nodered` + `--restart=unless-stopped`).
> - **🔴 Важно про доступ к HA извне:** `/config/.storage/http` на t610 требовал `trusted_proxies += 192.168.2.197/32`, иначе Caddy с другого хоста даёт **400** (HA `use_x_forwarded_for: true`). Обобщение: **IP любого внешнего reverse-proxy обязан быть в `trusted_proxies`.**
> **2026-09-14 (вечер-3) — ZONT MQTT ПЕРЕНАПРАВЛЕН НА t610:**
> - DNAT на роутере `192.168.2.2`: `firewall.@redirect[0]` (name `MQTT`) и `firewall.@rule[3]` (name `allow-1883`) — `dest_ip` `192.168.2.197` → **`192.168.2.176`**. `uci commit firewall` + `/etc/init.d/firewall reload`. Бэкап: `/root/firewall.bak-20260914-092555`.
> - **Результат:** ZONT пишет в mosquitto-**аддон на t610** (живой поток `modbus/sensors/kids/*`, `bedroom/*`). В настройках ZONT ничего не менялось (`mqtt://…@192.168.0.10:1883`, где `.0.10` = wan-интерфейс роутера `192.168.2.2`, не отдельный GPON-роутер).
> - ✅ **`dining/*` тоже публикуется (2026-09-14, позже):** прежняя версия «ZONT не публикует / мёртвый upstream» — **❌ ОПРОВЕРГНУТА**. Причина была в **баге сборки RTU-кадров в `modbus-bridge`** (19-байтный кадр гостиной рвался), фикс `3748feb` → все 7 полей `dining` живы. Подробно — [[family/plans/t610-home-automation]] §5-кватер-З.
> - **⚠️ «Камера на TrueNAS» — ИСПРАВЛЕНО (2026-09-14, вечер-10) + ✅ РЕШЕНО ОКОНЧАТЕЛЬНО (вечер-13):** прежняя запись «камера = USB-вебка на t610, upstream `cam.*:8090` к камере отношения не имеет» — **❌ НЕВЕРНА**. Поиск в `Caddyfile.bak` доказал: **`cam.mallexxx.duckdns.org → 192.168.2.197:8090` — ЭТО И БЫЛА камера** на TrueNAS: отдельный HTTP-MJPEG-сервис (`ustreamer`/`mjpg-streamer`, порт 8090 — канон для «USB-вебка → MJPEG»). **Контейнер УТРАЧЕН** при пересоздании пула (локальный образ не пережил `.ix-apps`; из живого Caddyfile строка удалена — `cam.*` больше нет). **✅ ФИНАЛ (вечер-13):** вебка `046d:0825` физически в **t610**, работает через **аддон `a889bffc_go2rtc-hardware`** → RTSP H.264 `rtsp://192.168.2.176:8554/usb_camera_h264` → **Generic Camera** `camera.192_168_2_176` (зона `kotelnaia`, `unique_id`, **WebRTC работает**, поворот `#rotate=90`). Схема `camera: platform: ffmpeg` в Core — **❌ ОТВЕРГНУТА** (`Resource busy` + нет `unique_id`). Подробно — [[family/plans/t610-home-automation]] §5-кватер-И-3/И-6.
> - **Не перенесено с TrueNAS:** ~~погашение TrueNAS-стека (Этап 4 п.6 — заблокировано: Caddy на TrueNAS держит точку входа)~~ → **✅ ЗАКРЫТО 2026-09-14 (ночь): стек автоматизации ПОГАШЕН, Caddy остался на TrueNAS (так и задумано).** См. §5-кватер-Л в [[family/plans/t610-home-automation]].
> Обновлено: 2026-09-02 (vpn.mallexxx:443 = РАБОЧИЙ Xray-сервер, проверено end-to-end; vless-proxy outbound мёртв)
> ## ⚠️ ПРИОРИТЕТ 2026-09-01: VPS qentra.top УДАЛЁН → vless-proxy и сетевые туннели сломаны
> - **VPS `91.207.28.205` больше НЕ существует** (вся его Xray/OpenVPN/WG-инфраструктура утрачена). Подробно: [[family/how-to/vps-qentra]].
> - **Контейнер `vless-proxy`** (teddysun/xray): inbound SOCKS `0.0.0.0:1080` + HTTP `0.0.0.0:1081`, но **outbound ⇒ мёртвый `v.qentra.top:443`** (VLESS+WS+TLS, path `/qentra`, id `2D9F24C4-21FE-4784-9843-F11C384DA67A`). ⇒ Hermes-Taiga (ходит через `vless-proxy:1080`) **сейчас БЕЗ рабочего прокси**. **Уточнено 2026-09-02:** `v.qentra.top` по-прежнему ресолвится, но в **Cloudflare IP** (`104.21.54.239`, `2606:4700:...`) — DNS-запись на qentra.top осталась в Cloudflare, хотя VPS сам удалён; origin'а за ней нет, поэтому трафик через прокси не идёт. Контейнер `vless-proxy` сам ЖИВ (Up 8 days), путь через его SOCKS наружу не проходит.
> - **⚠️ На корневом `mallexxx.duckdns.org:443` НЕ Xray**, а обычный **Caddy/nginx с валидным Let's Encrypt сертификатом** (проверено `openssl s_client` 2026-09-01). **НО на поддомене `vpn.mallexxx.duckdns.org:443` — РАБОЧИЙ Xray-сервер** (см. раздел `xray-admin` ниже, проверено end-to-end 2026-09-02).
> - **Наружу открыты только 22 (SSH) и 443 (HTTPS/TLS)** с Kraken; `8443/8964/8080/9000` closed.
> - **План замены** (выход клиентов сети TrueNAS через Kraken, Xray reverse — НЕ внедрён): [[personal/tech/xray-reverse-tunnel-kraken-truenas]].
> ## ✅ СТАТУС на 2026-08-25: пул ONLINE, docker поднят, почти все контейнеры Up
> **Пул RED_2TB пересоздан (2026-08-21) и работает:** `zpool status` ONLINE, rsync возврата данных завершён, `/mnt/RED_2TB/` смонтирован.
> **Docker: ПОДНЯТ на 2026-08-25.** Почти все контейнеры Up (zigbee2mqtt, webdav, vless-proxy, homeassistant, caddy, transmission, syncthing, mosquitto, nodered, immich*, gitea, filebrowser, portainer*, hermes-taiga и др.). ✅ **cups-splix поднят 2026-08-26** — образ собран заново (`docker build -t cups-splix .`), контейнер запущен `docker compose up -d`, порт 631 открыт, принтер `Samsung_CLX-216x_Series` активен (USB `04e8:3425`). Причина былого падения: образ локальный, потерян при восстановлении пула (`.ix-apps` не переносился), вручную не пересобирали. Рецепт — ниже, раздел «Печать / cups-splix». Ещё не подняты (проверить при надобности): inpxer/inpx-web/arr/ser2net.
> **⚠️ ИСТОРИЧЕСКАЯ проблема modbus-bridge/mbusd — гонка с udev при рестарте TrueNAS (❌ БОЛЬШЕ НЕАКТУАЛЬНА):**
> - ~~После перезагрузки docker стартует раньше udev, поэтому `/dev/ttyZONT` и `/dev/ttyVent` на момент старта контейнеров ещё не существуют.~~
> - **✅ НЕАКТУАЛЬНО с 2026-09-14:** USB-адаптеры (CH340 ZONT/вентиляция) **физически перенесены на t610** → на TrueNAS узлов `/dev/ttyZONT` / `/dev/ttyVent` **нет вообще**, а сами контейнеры `mbusd`, `modbus-bridge`, `ser2net` **погашены** (`stop` + `--restart=no`). Проверка: `ls /dev/ttyUSB*` → пусто; `/sys/bus/usb/devices` содержит только принтер Samsung `04e8:3425` (**`lsusb` на TrueNAS не установлен** — использовать `/sys/bus/usb/devices`).
> - **Актуальная гонка udev живёт на t610** — см. [[family/how-to/zont-modbus-bridge-udev-race-protection]].
> - ⚠️ **Историческая справка (если когда-нибудь откатывать):** `restart: unless-stopped` НЕ перезапускает контейнер, упавший на `start` из-за отсутствующего device-узла (отказ до старта процесса, ExitCode 128/255, RestartCount=0); лечилось ручным `docker start modbus-bridge mbusd` после готовности симлинков.
> **⚠️ ДРУГОЕ (открытое):** пул `DEST` (IronWolf) на 2026-08-24 `DEGRADED` — разобраться, почему (отвалился mirror-член). TimeMachine (~277G) не возвращён (бэкапы macOS, вероятно не нужен — решение Alex не подтверждено). SSH с Mac по 192.168.2.197 нестабилен — использовать `mallexxx.duckdns.org`.
> ## 🔒 ИСТОРИЯ: статус до восстановления (2026-08-24)
> **Пул RED_2TB пересоздан и УЖЕ зареган в TrueNAS** — `zpool status` ONLINE (`mirror-0{sdc,sdf}`+`mirror-1{sde,sdd}`), `midclt call pool.query` id=1 RED_2TB ONLINE. rsync возврата данных ЗАВЕРШЁН (storage 3.29T, immich 353G, backup 287G, Edu 214G, Photos 146G, old-bu 65G, docker, docker.bak, system — все смонтированы).
> **`.ix-apps` датасет (docker storage, был 24G) НЕ перенесён** — rsync шёл из `/mnt/RED_2TB/*` и не включал монтируемый в `/mnt/.ix-apps` системный датасет. Образы = кеш → перекачаются из registry сами; конфиги целы в `/mnt/RED_2TB/docker/<app>`.
> **Контейнеры запускались через `docker-compose`, НЕ через TrueNAS Apps (TrueCharts/Custom App).** daemon.json `data-root:/mnt/.ix-apps/docker`. `.ix-apps` = просто data-root docker, не TrueNAS Apps.
> **⚠️ ДРУГОЕ (проверено 2026-08-24):** пул `DEST` (IronWolf, источник спасения) на момент проверки `DEGRADED` в `zpool list` — стоит разобраться, почему (вероятно отвалился mirror-член). Также SSH с Mac к TrueNAS по 192.168.2.197 нестабилен (`Connection reset/reset by peer`, `kex_exchange_identification read`), возможен конфликт сессий при активном входе на консоль — использовать `mallexxx.duckdns.org` и ретраи.
> ## ⚠️ СТАТУС на 2026-08-21: пул RED_2TB — данные СПАСЕНЫ, пул OFFLINE, пересоздаём
> **Выгрузка успешно завершена** (подтверждено Alex): данные RED_2TB (4.56T) на IronWolf (пул `DEST`, `/mnt/IRONWOLF`). **Пул RED_2TB — статус OFFLINE** в БД TrueNAS, НЕ импортирован. Конфиги docker (caddy, transmission, HA, immich и т.д.), Obsidian vault и git-репо спасены на `/mnt/IRONWOLF` (`system/`, `docker.bak/`, `docker/`, `storage/obsidian`, `storage/git`).
> **ПЛАН (следующий шаг):** пересоздать пул RED_2TB с новой топологией `mirror {sdc,sdf}` + `mirror {sde,sdd}` (включаем WD2TB#2 зеркалом к WD2TB#1). Команды `zpool labelclear` + `zpool create` — в `family/how-to/truenas-sata-ports-and-zfs-pools.md` (раздел «Пересоздание пула 2026-08-21»). Затем вернуть данные rsync с IronWolf и восстановить инфраструктуру.
> **ПРОТОКОЛ ПОВРЕЖДЕНИЯ (история):** пул паниковал на rw-импорте (`adding existent segment to range tree`, повреждённая space map). Работал только `zpool import -o readonly=on`. In-place починки нет (mav/iXsystems) — только спасать данные и пересоздавать. Полный рецепт — в `family/how-to/truenas-sata-ports-and-zfs-pools.md`.
## Доступ
- **Host (external):** `mallexxx.duckdns.org` (DuckDNS) — **единственный способ** SSH/API из 192.168.1.x
- **SSH:** `truenas_admin@mallexxx.duckdns.org -i ~/.ssh/id_rsa`
- **Web UI:** http://truenas.mallexxx.duckdns.org
- **Portainer:** https://portainer.mallexxx.duckdns.org
- **Host (local network):** `192.168.2.197` — ⚠️ ИСПОЛЬЗОВАТЬ `ssh truenas_admin@mallexxx.duckdns.org`. НЕ ИСПОЛЬЗОВАТЬ локальный IP для SSH доступа!
- ⚠️ Eagle (Mac, 192.168.1.x) и Kraken (192.168.1.15) находятся в **другой подсети**
- ⚠️ Кра́кен и TrueNAS — **разные сети** (192.168.1.x vs 192.168.2.x). Доступ с Кракена на TrueNAS по локальному IP **не работает**
**⚠️ Измеренный потолок канала Mac/ТВ (192.168.1.x) → TrueNAS (192.168.2.x) — 2026-09-02:**
**⚠️ Измеренный потолок канала Mac/ТВ (192.168.1.x) → TrueNAS (192.168.2.x) — 2026-09-02, ПЕРЕСМОТРЕНО:**<br>Между этими двумя сетями нет LAN — только обход через внешку провайдеров (ТТК дом A ↔ Ростелеком дом B). Замерено:
- **Single TCP flow ≈ 28 Мбит/с**, но **4 параллельных потока ≈ 51 Мбит/с** (агрегат РАСТЁТ с параллельностью) → это **per-TCP-flow / BDP-штраф за ~104 мс RTT**, а **НЕ лимит линии TrueNAS**.
- ⚠️ **ПОЗДНЕЙШИЙ ЗАМЕР С САМОГО NAS ОПРОВЕРГ раннюю запись «ап-линия TrueNAS ~30 Мбит/с»**: NAS → Cloudflare даёт **~184 Мбит/с down / ~117 Мбит/с up** (`curl https://speed.cloudflare.com/__down?bytes=50000000` и POST `__up`). ovh/tele2 speedtest из RU заблокированы — юзать Cloudflare-эндпоинты.
- **~104 мс RTT**, из них ~50 мс на **одном межоператорском хопе** `194.186.168.65` (TTK 3–6 мс → прыжок до ~54 мс). Per-hop loss: моя ISP-грань чиста (0%, 3 мс); дальние хопы дают спорадич. LOSS (ICMP-деприоритизация, не устойчивые потери). Re-route 104мс полностью не уберёт (пиринг/география).
- Следствие: **высокобитрейтный медиа-плейбек (720p BluRay и выше) через jellyfin на этом пути тормозит/грузится кусками** (HLS одним TCP + 104мс RTT, single-flow ~2851 Мбит впритык к пикам файла). НЕ транскодинг (direct-play). **Jellyfin не умеет мультистримить один плейбек.**
- Пересмотренный разбор + команды: `family/how-to/arr-stack-taiga.md` → «Плейбек по сети → per-TCP-flow/BDP». Решения: дать локальный маршрут (если TrueNAS в одном здании/роутере), ограничить jellyfin-битрейт < ~20 Мбит, или прокси с мульти-TCP-загрузкой файла, или WireGuard-туннель через VPS.
## Пользователи и группы (ключевые)
| uid | Имя | gid | Назначение |
|-----|-----|-----|------------|
| 950 | truenas_admin | 950 | SSH-пользователь, управление docker |
| 911 | transdamon | 911 | Процесс Transmission внутри контейнера |
| 921 | transmission | 921 | Старый пользователь (не используется контейнером) |
| 3000 | nas_users | 3000 | Общая группа доступа к NAS |
## Структура папок
```
/mnt/RED_2TB/
├── docker/ ← конфиги docker-контейнеров (бэкапятся → mailru-crypt:)
│ ├── caddy/
│ ├── filebrowser/
│ ├── ha/ ← Home Assistant
│ ├── hermes/ ← Hermes-Taiga
│ ├── homeassistant/
│ ├── immich/
│ ├── inpx-web/
│ ├── inpxer/
│ ├── mbusd/
│ ├── modbus-bridge/
│ ├── mosquitto/
│ ├── nodered/
│ ├── portainer/
│ ├── python/
│ ├── rclone/
│ ├── ser2net/
│ ├── transmission/ ← конфиг Transmission (settings.json, torrents, resume...)
│ ├── vless-proxy/
│ ├── watchtower/
│ ├── webdav/
│ └── zigbee2mqtt/
├── storage/
│ ├── Downloads/ ← данные торрентов (монтируется в контейнер как /mnt/storage)
│ │ ├── transmission/ ← старый путь конфига (больше не используется)
│ │ └── [медиафайлы]
│ └── obsidian/ ← vault (read-only для hermes-taiga)
├── backup/ ← ручные бэкапы (бэкапятся → mailru-crypt:)
│ └── transmission-config/ ← снапшот конфига от 2026-04-30
├── Photos/ ← фото (бэкапятся → mailru:Photos/Photos)
├── old-bu/ ← старый архив (бэкапятся → mailru:Photos/old-bu)
└── immich-photos-upload/ ← библиотека Immich (бэкапятся → mailru:Photos/immich)
```
## NFSv4 ACL — важно
TrueNAS использует **NFSv4 ACL**, а не стандартный POSIX chmod/chown.
- `ls -la` показывает `----------` даже если ACL есть → всегда проверять через `midclt call filesystem.getacl <path>`
- Добавить запись: `midclt call filesystem.setacl '{...}'`
- `truenas_admin` не имеет passwordless sudo → root-операции только через midclt или TrueNAS UI
## Docker-контейнеры
| Контейнер | Image | Порт | Домен |
|-----------|-------|------|-------|
| transmission | linuxserver/transmission:latest | 9091, 51413 | transmission.mallexxx.duckdns.org |
| hermes-taiga | hermes-taiga:latest | — | — |
| vless-proxy | teddysun/xray:latest | — | — |
| filebrowser | filebrowser/filebrowser:latest | — | — |
| webdav | hacdias/webdav:latest | — | webdav.mallexxx.duckdns.org |
| ~~homeassistant~~ ⛔ | home-assistant:stable | ~~8123~~ | **ПОГАШЕН 2026-09-14** — переехал на t610 |
| immich-server | immich-app/immich-server:release | 2283 | immich.mallexxx.duckdns.org |
| immich-postgres | tensorchord/pgvecto-rs:pg14-v0.2.0 | — | — |
| immich-redis | redis:7 | — | — |
| ~~nodered~~ ⛔ | nodered/node-red:latest | ~~1880~~ | **ПОГАШЕН 2026-09-14** — flows на t610 (ingress) |
| ~~mosquitto~~ ⛔ | eclipse-mosquitto:latest | ~~1883~~ | **ПОГАШЕН 2026-09-14** — брокер на t610 |
| caddy | caddy:latest | 80, 443 | reverse proxy для всего |
| rclone | rclone/rclone:latest | — | бэкап по cron |
| portainer | portainer/portainer-ce:latest | 9000 | portainer.mallexxx.duckdns.org |
| watchtower | containrrr/watchtower:latest | — | авто-обновление образов |
| inpxer | ghcr.io/hedger/inpxer:latest | 18080 | books.mallexxx.duckdns.org |
| zigbee2mqtt ⛔ | koenkk/zigbee2mqtt:latest | — | — (переехал на t610) |
| mbusd ⛔ | 3cky/mbusd:latest | 502 | Modbus (переехал на t610) |
| modbus-bridge ⛔ | modbus-bridge | — | — (переехал на t610) |
| ser2net ⛔ | ghcr.io/jippi/docker-ser2net | 502 | **ПОГАШЕН 2026-09-14** — spare-master, конфликт порта с mbusd |
| cups-splix | cups-splix | 631 | принтер |
| xray-admin | ghcr.io/mhsanaei/3x-ui:latest | 2053 (панель), 10095 (vless-ws), 443 (sub) | vpn-panel.mallexxx.duckdns.org, vpn.mallexxx.duckdns.org |
| xray-reverse-portal | teddysun/xray:latest | 12345 (SOCKS), 12346 (VLESS-TCP REALITY interconn) | — (см. `personal/tech/xray-reverse-tunnel-kraken-truenas.md`) |
### cups-splix — принтер Samsung CLX-216x (✅ поднят 2026-08-26; ✅ mDNS-фикс 2026-08-31 завершён)
**Статус:** контейнер работает, принтер `Samsung_CLX-216x_Series` **idle / enabled / accepting**. CUPS слушает `0.0.0.0:631` (host-сеть). mDNS-анонс **включён** — штатная Android print service теперь видит принтер по mDNS (подробно: [[mac-print-shared-services]]). См. ниже раздел «✅ mDNS/AirPrint анонс принтера».
Папка: `/mnt/RED_2TB/docker/cups/``Dockerfile`, `entrypoint.sh`, `docker-compose.yml`, `data/``/etc/cups`, `cache/``/var/cache/cups`, `spool/``/var/spool/cups`, `uld/`, бэкап `backup_20260831-003619.tar.gz`.
- **Image:** `cups-splix` (локальная сборка из Dockerfile; старый образ сохранён как `cups-splix-old` для отката)
- **Dockerfile** (debian:12-slim): `cups-daemon cups-client cups-common printer-driver-splix avahi-daemon avahi-utils dbus usbutils nano procps`; `cupsadmin:admin` (группа lpadmin); `COPY entrypoint.sh`; `EXPOSE 631`; `ENTRYPOINT ["/entrypoint.sh"]`
- **entrypoint.sh:** `dbus-daemon --system --fork``avahi-daemon --no-drop-root --syslog` (фон) → `exec cupsd -f`
- **compose:** `image: cups-splix`, `network_mode: host`, `privileged: true`, volume `/dev/bus/usb:/dev/bus/usb`, restart `unless-stopped` (содержит устаревший `command: [cupsd -f]`, но ENTRYPOINT переопределяет — правится только через root/UI, файл 600 root)
- **Сборка/поднятие (⚠️ полное пересоздание, НЕ `docker restart`):**
```bash
cd /mnt/RED_2TB/docker/cups/
docker build -t cups-splix-new .
docker stop cups-splix && docker rm cups-splix
docker tag cups-splix-new cups-splix && docker tag cups-splix cups-splix-old 2>/dev/null
docker compose up -d
```
> Полный разбор и симптом «телефон не видит принтер»: [[mac-print-shared-services]]
### Инвентарь compose-файлов по папкам (проверено 2026-08-24)
Каждый контейнер = своя папка `/mnt/RED_2TB/docker/<app>/`. Модель — **не один общий compose, а per-service compose** (контейнеры поднимались `docker compose up -d` из своей папки / `docker run`).
**✅ Есть `docker-compose.yml` (поднимаются `docker compose -f ... up -d`)** — 22 шт:
arr, caddy, cups, filebrowser, gitea, hermes, immich, inpx-web, inpxer, library, mbusd, mosquitto, nodered, portainer-mcp, portainer, rclone, ser2net, syncthing, transmission, vless-proxy, watchtower, **xray-admin (3x-ui, добавлен 2026-09-01)**
> 🔴 **ВАЖНО (2026-09-14):** `mbusd`, `mosquitto`, `nodered`, `ser2net` **погашены** — поднимать их обратно **НЕ НАДО** (переехали на t610). Остальные — активны.
**⚠️ НЕТ compose-файла — только конфиг (восстанавливать вручную, параметры из доки ниже):**
- ~~**ha** — Home Assistant: `/mnt/RED_2TB/docker/ha/` (automations.yaml)~~ → 🔴 **ПОГАШЕН 2026-09-14.** Папка **сохранена как ЭТАЛОН конфига** (`configuration.yaml`, modbus-блок построчно идентичен t610, 32 заслонки) — **не удалять**.
- **webdav** — `/mnt/RED_2TB/docker/webdav/` (config.yml). Образ `hacdias/webdav:latest`, домен webdav.mallexxx.duckdns.org. ✅ активен (compose на самом деле есть, см. строку выше).
- ~~**modbus-bridge** — `/mnt/RED_2TB/docker/modbus-bridge/`~~ → 🔴 **ПОГАШЕН 2026-09-14** (`Exited (0)` с 14.09 01:59 — узел `/dev/ttyZONT` исчез). Папка цела.
- ~~**zigbee2mqtt** — `/mnt/RED_2TB/docker/zigbee2mqtt/`~~ → 🔴 **ПОГАШЕН 2026-09-14** (`Exited (2)` — координатор на t610).
- ~~**homeassistant** — папка `docker/homeassistant/`~~ → **ПУСТАЯ и не использовалась**; рабочая была `ha/` (см. выше).
### Порядок восстановления docker-стека (зависимости)
1. **docker engine:** `systemctl enable --now docker` (после создания data-root, см. шапку). Проверка: `docker info | grep -iE "Server Version|Docker Root Dir"`.
2. **Инфраструктура/сеть:** ~~mosquitto (MQTT) → zigbee2mqtt (нужен mosquitto) → nodered (MQTT)~~ — 🔴 **все три ПОГАШЕНЫ 2026-09-14, на TrueNAS НЕ ВОССТАНАВЛИВАТЬ** (живут на t610). Остаётся: caddy (прокси, тянет все домены) → vless-proxy (SOCKS5 для hermes).
3. **Умный дом:****на TrueNAS БОЛЬШЕ НЕ ВОССТАНАВЛИВАТЬ** — переехало на t610 (см. «Декомиссия стека автоматизации»), **стек ПОГАШЕН 2026-09-14**. `mbusd` (Modbus TCP:502) → `modbus-bridge` (через mbusd) → `ha` (homeassistant, нужен caddy для домена) — **всё это теперь аддоны на `192.168.2.176`**.
4. **Медиа/хранилище:** transmission (нужен caddy) → arr (radarr/sonarr/prowlarr) → inpxer (books), inpx-web, library → rclone, syncthing, filebrowser, webdav, gitea. ⚠️ `inpxer`/`inpx-web` — на 2026-09-14 в циклическом краше (НЕ трогать по указанию Alex); `library` — погашен 2026-09-14 (см. декомиссию).
5. **Сервисы/свои:** hermes-taiga (нужен vless-proxy), portainer, portainer-mcp, watchtower, cups. ~~ser2net~~**погашен 2026-09-14** (конфликт порта 502 с mbusd).
6. **Проверка:** `docker ps`. HA (если когда-нибудь поднимать обратно): `docker exec homeassistant python -m homeassistant --script check_config --config /config` — но 🔴 контейнер **погашен**, живая HA = аддон на t610 `192.168.2.176`.
### ⛔ Декомиссия стека автоматизации TrueNAS (2026-09-14) — КАНОН
**Погашено 7 контейнеров** (`docker stop` + `docker update --restart=no`, **НЕ удалены**):
`homeassistant`, `mbusd`, `mosquitto`, `nodered`, `zigbee2mqtt`, `modbus-bridge`, `ser2net`
- **Почему:** всё это работает на **t610** (HA OS, `192.168.2.176`) как HA-аддоны; на TrueNAS ресурсы дублировались впустую, а `mbusd`/`modbus-bridge`/`zigbee2mqtt` вообще были мертвы (USB-адаптеры переехали физически).
- **Папки `/mnt/RED_2TB/docker/*` ЦЕЛЫ.** Откат: `docker start <name>` + `docker update --restart=unless-stopped <name>`.
- **`rm` НЕ делали** — удаление отдельным шагом, не раньше чем через 2–3 дня стабильной работы.
- **Секрет:** `HA_TOKEN` лежит **открытым текстом** в `/mnt/RED_2TB/docker/modbus-bridge/docker-compose.yml``environment` (там же `MQTT_PASS: mqtt1z3$`) — кандидат на `.env` + ротацию. Папку **не трогать/не публиковать** до ротации.
- **Полный разбор** — §5-кватер-Л в [[family/plans/t610-home-automation]].
**⚠️ Минные поля, найденные при аудите (НЕ трогались, отдельное решение Alex):**
| Контейнер | Проблема |
|---|---|
| `library` ⛔ | ~~`Restarting` циклически, **`RestartCount=29752`**~~**✅ ПОГАШЕН 2026-09-14** (по команде Alex): `docker stop library` + `docker update --restart=no``state=exited`, `restart=no`. Caddy-домен `library.mallexxx.duckdns.org`**мёртв** (и был мёртв до гашения). **Не удалён**, папка цела. **Открыто:** почему падал (`image: library-app:latest` из `build: .` — локальная сборка; тот же паттерн, что утерянные `cups-splix`/камера при пересоздании пула) |
| `inpx-web` / `inpxer` | оба `Exited (1)`, `RestartCount=13`; `books.mallexxx.duckdns.org``:18080` (мёртвый `inpxer`). **По указанию Alex НЕ трогать** |
**Диагностические питфоллы TrueNAS (проверено 2026-09-14):**
- ⚠️ **`curl http://192.168.2.176:8123``HTTP 000` — ЭТО НОРМА.** HA на t610 живёт **за Caddy**; её `:8123` закрыт, доступ = `:80` / `mallexxx.duckdns.org`. Не принимать за поломку.
- **`lsusb` на TrueNAS НЕ установлен** → USB-устройства смотреть через `/sys/bus/usb/devices/` (`product`, `manufacturer`, `idVendor`/`idProduct`).
- **`midclt call app.query``[]`** (TrueNAS Apps не используются), `/mnt/.ix-apps/app_configs` пуст. Всё — **per-service compose из своей папки**, Portainer stacks **не используются**.
- **`sudo` на TrueNAS требует пароль** (passwordless нет) — root-операции только через root-SSH/Shell.
- Кто чем управляется: `docker inspect <name> --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'`.
### Transmission — детали
- **Config:** `/mnt/RED_2TB/docker/transmission/` (монтируется как `/config`; внутри `/config/docker-compose.yml`)
- **Данные:** `/mnt/RED_2TB/storage` (монтируется как `/mnt/storage`)
- **Download dir:** `/mnt/storage/Downloads`
- **UID/GID:** ⚠️ **по факту работает как ROOT (uid 0)**, НЕ 911/911. Причина: в `/mnt/RED_2TB/docker/transmission/docker-compose.yml` **НЕ задан `PUID`/`PGID`** → linuxserver `/init` (s6-overlay) оставляет контейнер root (подтверждено `docker exec transmission id` → root). Пользователь `transdamon`/911 (док) — это владелец конфига на хосте (`drwx------ 911 911`), но НЕ процесс внутри контейнера.
- **Зачем важно:** root-трансмишен пишет файлы как root и переживает права 0000 медиа → это причина, почему он "работает" на сломанных после restore папках. Но для pipeline с jellyfin/radarr (не-root) root-создаваемые файлы барьер.
- **План фикса (Вариант A, одобрен 2026-09-02):** добавить `PUID=950 PGID=950` и пересоздать контейнер → работает под `truenas_admin`. План: `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md` §5.
- **RPC whitelist:** `172.16.6.*`
- **Web:** https://transmission.mallexxx.duckdns.org
- **Порты:** 9091 (RPC/web), 51413 (TCP/UDP peers)
### Caddy — домены
| Домен | → |
|-------|---|
| mallexxx.duckdns.org | **HA на t610** `192.168.2.176:80` ✅ (2026-09-14) |
| transmission.mallexxx.duckdns.org | Transmission :9091 |
| immich.mallexxx.duckdns.org | Immich :2283 |
| ~~nodered.mallexxx.duckdns.org~~ | **❌ УБРАН из Caddyfile (2026-09-14):** Node-RED теперь аддон на t610, наружу НЕ выпущен — доступ через ingress HA. Решение Alex «оставляем так» |
| webdav.mallexxx.duckdns.org | WebDAV |
| books.mallexxx.duckdns.org | Inpxer :18080 🔒 basicauth (user: books-admin) — ⚠️ **upstream мёртв** (`inpxer` `Exited (1)`, не трогать) |
| library.mallexxx.duckdns.org | library-app :8080 🔒 basicauth (user: books-admin) — ⚠️ **upstream мёртв** (`library` погашен 2026-09-14) |
| portainer.mallexxx.duckdns.org | Portainer :9000 |
| truenas.mallexxx.duckdns.org | TrueNAS UI :80 |
| ~~cam.mallexxx.duckdns.org~~ | **❌ УБРАН из Caddyfile (2026-09-14).** Исторический upstream: `192.168.2.197:8090` — отдельный HTTP-MJPEG-сервис (`ustreamer`), контейнер утрачен при пересоздании пула. **Камера теперь на t610:** аддон **`a889bffc_go2rtc-hardware`** → RTSP H.264 `rtsp://192.168.2.176:8554/usb_camera_h264``camera.192_168_2_176` (зона Котельная, **WebRTC работает**, поворот `#rotate=90`). Домен не нужен. Подробно [[family/plans/t610-home-automation]] §5-кватер-И-6 |
| **vpn-panel.mallexxx.duckdns.org** | **3x-ui панель :2053** (добавлен 2026-09-01) |
| **vpn.mallexxx.duckdns.org** | **Xray VLESS-WS (путь /vless) → xray-admin:10095** (добавлен 2026-09-01) |
### `xray-admin` — 3x-ui панель (Xray server, добавлена 2026-09-01)
**Цель:** 3x-ui frontend для Xray-reverse туннеля Kraken↔TrueNAS (выход клиентов сети TrueNAS через Kraken). Подробно: [[personal/tech/xray-reverse-tunnel-kraken-truenas]].
| Параметр | Значение |
|----------|----------|
| Папка | `/mnt/RED_2TB/docker/xray-admin/` |
| Контейнер | `xray-admin` (имя важно — Caddyfile резолвит по нему) |
| Образ | `ghcr.io/mhsanaei/3x-ui:latest` (3.7.0, Xray 26.7.28) |
| Volume | `/mnt/RED_2TB/docker/xray-admin:/etc/x-ui` (там `x-ui.db`) |
| Сеть | `caddy_default` (внешняя) |
| Панель | `https://vpn-panel.mallexxx.duckdns.org/` (Caddy → xray-admin:2053) |
| Inbound | `vless-ws` port `10095`, tag `in-10095-tcp`, path `/vless`, host `vpn.mallexxx.duckdns.org`; clients: `user1` (direct TrueNAS), `kraken-user` (reverse via Kraken) |
| Sub-сервер | `[::]:443` (path /sub), панель `[::]:2053` |
| Env | `TZ=Asia/Novosibirsk`, `PUID=950`, `PGID=950` |
| Ports (host) | `54321:54321` (не используется панелью — внутри панель на 2053, можно убрать) |
**Статус (2026-09-02):** контейнер **Up**, панель HTTP 200. Reverse portal развёрнут отдельным контейнером `xray-reverse-portal`; per-user egress работает end-to-end.
**✅ ПРОВЕРЕНО РАБОТАЕТ (2026-09-02): `vpn.mallexxx.duckdns.org:443` — это ФУНКЦИОНАЛЬНЫЙ Xray-СЕРВЕР, НЕ только reverse-frontend.** Проверено end-to-end юзером с Mac. Ключевые факты с живой машины:
- Контейнеры `xray-admin` (Up 21h) и `caddy` (Up 20h) оба живы. Панель `vpn-panel` → HTTP 200. TCP `vpn.mallexxx.duckdns.org:443` снаружи открыт.
- **Inbound `in-10095-tcp`** (реальный конфиг из `bin/config.json`, Xray 26.7.28): VLESS-WS, `security: none`, WS path `/vless`, host `vpn.mallexxx.duckdns.org`.
- **client id:** `ce320965-6956-4759-84bb-7cb71cfc6252` (email `user1`)
- **Outbound:** `freedom`/`direct` — сервер имеет **СОБСТВЕННЫЙ выход в интернет** через TrueNAS (не через Kraken!). routing: geoip:private + bittorrent → blocked.
- **Тест с Mac** (временный xray-клиент в docker): VLESS+WS через `vpn.mallexxx.duckdns.org:443` → HTTP 200, выходной IP `90.189.160.148` (TrueNAS). Сервер полностью рабочий.
- **⚠️ Так и твой клиент должен подключаться:** TLS терминирует Caddy на 443, inbound `security: none` → в конфиге КЛИЕНТА `network: ws`, TLS поверх на `vpn.mallexxx.duckdns.org` (**НЕ включать двойной TLS внутрь WS**).
- **⚠️ Xray 26.7.28 удалил `allowInsecure`** в клиентских tlsSettings (мигрировано на `pinnedPeerCertSha256`/`verifyPeerCertByName`). Если в клиентском конфиге был `allowInsecure: true` — клиент падает. Это частая причина «не подключается».
**Per-user egress (2026-09-02):**
- `user1`, ID `ce320965-6956-4759-84bb-7cb71cfc6252` → default outbound `direct` → TrueNAS IP `90.189.160.148`.
- `kraken-user`, ID `93a5dc4b-1b8d-4af5-9363-eb0091734293` → routing rule `user: ["kraken-user"]` → SOCKS outbound `via-kraken` at `xray-reverse-portal:12345` → Kraken IP `92.62.70.41`.
- Private destinations and BitTorrent remain blocked before the per-user rule.
- Persistent global template is stored in `settings.key=xrayTemplateConfig`; do not edit `/app/bin/config.json` manually because it is generated.
- Verified with the local `xray-test-client`: unchanged `user1` returned TrueNAS IP; changing only the client UUID to `kraken-user` returned Kraken IP over both HTTP and HTTPS.
- Pre/post backups: `/mnt/RED_2TB/docker/backups/xray-per-user-20260902-1200/`.
> ⚠️ База `x-ui.db` была **уже настроена** под эту Caddy-интеграцию (inbound vless-ws:10095, subDomain vpn-panel), поэтому панель заработала «из коробки». Бэкап базы/Caddyfile до изменений: `/mnt/RED_2TB/docker/backups/reverse-xray-3xui-20260901-113625/`.
### `xray-reverse-portal` — Xray reverse portal (TrueNAS, добавлен 2026-09-01)
**Цель:** portal-часть Xray-reverse туннеля: принимает исходящий трафик локальных клиентов сети TrueNAS (через SOCKS `:12345`) и пересылает по reverse-каналу на Kraken (bridge) → интернет через Kraken. Подробно: [[personal/tech/xray-reverse-tunnel-kraken-truenas]].
| Параметр | Значение |
|----------|----------|
| Папка | `/mnt/RED_2TB/docker/reverse-portal/` |
| Контейнер | `xray-reverse-portal` |
| Образ | `teddysun/xray:latest` (Xray 26.7.28) |
| Volume | `config.json:/etc/xray/config.json:ro` |
| Сеть | `caddy_default` |
| interconn | `:12346` VLESS (принимает reverse-канал от Kraken) — **сейчас на TCP+REALITY** (внутр. порт 12346, проброс `12346:12346`) |
| local | `:12345` SOCKS (точка входа для клиентов сети TrueNAS), проброс `12345:12345` |
| Env | `LOGLEVEL` |
**✅ Reverse работает end-to-end (2026-09-02).** Portal работает на Xray `26.4.25`, TCP+REALITY+Vision (`12346:12346`); OpenWrt DNAT `внешний:12346 → 192.168.2.197:12346`. Bridge на Kraken также закреплён на `26.4.25` и обязательно использует `network_mode: host`; Docker bridge/NAT сбрасывал reverse mux. HTTP/HTTPS egress проверен как `92.62.70.41` (Kraken). Детали и rollback: [[personal/tech/xray-reverse-tunnel-kraken-truenas]].
### Home Assistant — детали
- **Image:** `ghcr.io/home-assistant/home-assistant:stable`
- **Порт:** `8123:8123`
- **Volume:** `/mnt/RED_2TB/docker/ha``/config`
- Конфиги редактируются **напрямую на NAS**`docker cp` не нужен, изменения применяются после reload/restart HA.
### Home Assistant на TrueNAS ⛔ **ХОЛОСТОЙ ЭКЗЕМПЛЯР (аудит 2026-09-14)**
> ⛔ **СТАТУС (2026-09-14, ночь): КОНТЕЙНЕР ПОГАШЕН.** `docker stop homeassistant` + `docker update --restart=no`. Причина: `modbus.host` в `/mnt/RED_2TB/docker/ha/configuration.yaml` указывает на **`.197`** (сам TrueNAS) — шины там больше нет (адаптеры на t610), инстанс холостой. Живая HA — **аддон на t610 `192.168.2.176`**, домен `mallexxx.duckdns.org` ведёт **туда** (Caddy → `192.168.2.176:80`). **Папки и конфиги целы** — откат: `docker start homeassistant && docker update --restart=unless-stopped homeassistant`. Подробно — §5-кватер-Л в [[family/plans/t610-home-automation]].
> 📌 Эталон конфига старой HA сохранён: `/mnt/RED_2TB/docker/ha/configuration.yaml` — modbus-блок построчно идентичен тому, что уехал на t610 (32 заслонки). Использовался как эталон при сверке зон/устройств.
> ⚠️ Папки `docker/ha/` и `docker/homeassistant/` — **`homeassistant/` ПУСТАЯ**, рабочая — `ha/`.
Папка `/mnt/RED_2TB/docker/ha/``/config`. Образ `ghcr.io/home-assistant/home-assistant:stable`, порт `8123`.
**Ключевые файлы конфига:**
| Файл | Назначение |
|------|------------|
| `configuration.yaml` | Главный конфиг: интеграции, template sensors, http trusted_proxies |
| `automations.yaml` | Все автоматизации (подключён через `!include`) |
| `scripts.yaml` | Скрипты |
| `.storage/lovelace.home_plan` | Dashboard с планом этажей (JSON, управляется HA UI) |
| `www/floorplan/floor1_ha.svg` | SVG фон первого этажа |
| `www/floorplan/floor2_ha.svg` | SVG фон второго этажа |
**Перезапуск после редактирования конфига:**
```bash
ssh truenas_admin@mallexxx.duckdns.org "docker restart homeassistant"
```
**Проверка конфига перед перезапуском:**
```bash
ssh truenas_admin@mallexxx.duckdns.org "docker exec homeassistant python -m homeassistant --script check_config --config /config"
```
### mbusd — Modbus RTU → TCP gateway ⛔ **ПЕРЕЕХАЛ НА t610 (2026-09-14)**
> ⛔ **СТАТУС (аудит 2026-09-14): контейнер на TrueNAS БОЛЬШЕ НЕ РАБОЧИЙ.** USB-адаптеры (CH340 ZONT/вентиляция) физически переехали на t610 → в `/sys/bus/usb` на TrueNAS только принтер Samsung `04e8:3425`. `/dev/ttyVent` **не существует**. Контейнер формально `Up` с `2026-08-25` (RestartCount=0), но спамит `tty_reopen(): can't open tty device /dev/ttyUSB0 (No such device or address)`. Маппинг `/dev/ttyVent` докер толерирует, пока device не пересоздавали. **Кандидат на снос (п.6 плана [[family/plans/t610-home-automation]]).**
> 🔴 **⚠️ ИСТОРИЯ (устранено 2026-09-14):** `mbusd` и `ser2net` **оба** публиковали `0.0.0.0:502` И оба просили `/dev/ttyVent`. `ser2net` был в state `Created` (никогда не запущен) — при `start ser2net` был бы конфликт портов. **✅ Оба погашены 2026-09-14** (`stop` + `--restart=no`), порт 502 на TrueNAS свободен. Не поднимать оба одновременно.
Мост Modbus RTU → TCP: пробрасывает серийный порт в TCP 502. ~~Используется и для вентиляции (AT2), и для ZONT-шины.~~**исторически**; на 2026-09-14 обе линии обслуживает mbusd **на t610**.
- **Image:** `3cky/mbusd`, compose в `/mnt/RED_2TB/docker/mbusd/`
- **Порт:** `502:502` (TCP)
- **Config:** `/mnt/RED_2TB/docker/mbusd/mbusd.conf``/etc/mbusd.conf` (`device=/dev/ttyUSB0 speed=9600 mode=8n1`, `port=502`)
- **Device:** `devices: - /dev/ttyVent:/dev/ttyUSB0`
- **Entrypoint:** `["/usr/bin/mbusd","-d","-L","-","-c","/etc/mbusd.conf"]`
- **Pitfall udev-race:** см. ниже «Проблема modbus-bridge/mbusd после рестарта».
### modbus-bridge — 485-датчики + виртуальные slaves для ZONT ⛔ **ПЕРЕЕХАЛ НА t610 (2026-09-14)**
> ⛔ **СТАТУС (аудит 2026-09-14): ОСТАНОВЛЕН.** `Exited (0)` с **2026-09-14 01:59:34** (один рестарт, потом тишина) — `/dev/ttyZONT` перестал существовать в момент переезда USB на t610. `network_mode: host` + `ha.url: http://localhost:8123` → **на TrueNAS он теперь и не смог бы работать**: локальный HA смотрит на `.197`-шину, которой нет. Рабочая копия — аддон `modbus-bridge` на t610. **Кандидат на снос (п.6 плана [[family/plans/t610-home-automation]]).**
> 🔴 **Побочная находка:** `HA_TOKEN` лежит **открытым текстом** в `/mnt/RED_2TB/docker/modbus-bridge/docker-compose.yml` (env). Кандидат на ротацию вместе с токеном из remote `nolvu-landing`.
Кастомный Python-мост (`modbus_ha_bridge.py`, репо `HA-ZONT-Modbus`), контейнер `/mnt/RED_2TB/docker/modbus-bridge/`.
> ⚠️ **Уточнение (аудит 2026-09-14): `docker-compose.yml` ЗДЕСЬ ЕСТЬ** — пункт ниже («НЕ имеет compose-файла») устарел. Compose содержит `devices: /dev/ttyZONT:/dev/ttyUSB0`, env `HA_TOKEN`/`MQTT_USER=zont`/`MQTT_PASS`, `network_mode: host`, логирование `json-file` 10m×5.
- **Image:** `modbus-bridge` (локальная сборка, `--no-cache`). **НЕ имеет compose-файла** — создавался через `docker-compose`-подобный run; для восстановления использовать параметры ниже.
- **Device:** `devices: - /dev/ttyZONT:/dev/ttyUSB0` (внутри контейнера слушает `/dev/ttyUSB0`)
- **Volumes:** `config.yml``/app/config.yml` (ro), `modbus_ha_bridge.py``/app/modbus_ha_bridge.py` (ro)
- **Env (из compose):** `HA_TOKEN`, `MQTT_USER=zont`, `MQTT_PASS=...`
- **`network_mode: host`**; MQTT broker `localhost:1883` (mosquitto), HA `http://localhost:8123`.
**Роль (важно — два режима работы):**
1. **Sniff (чтение)** — сниффит реальные 485-датчики на шине ZONT: **Dining=slave 1, Kids=slave 2, Bedroom=slave 3** (CO₂/температура/влажность, регистры 2 и 100) и публикует в MQTT (`modbus/sensors/<room>/...`), а также пишет в HA.
2. **Mappings (виртуальные slaves для ZONT)** — подставляет на **slave 101/102/103** (регистр 100) значения temperature от 485-датчиков: Dining→101, Kids→102, Bedroom→103. **ZONT (Modbus master) опрашивает 101/102/103 как свои внешние датчики температуры.** Есть также wifi-термостат как slave 100 (`sensor.0xa4c13862d39377e6_temperature`) и Socket 1 = slave 101 через switch (обратим внимание: 101 занят и Dining temp — переиспользуется на одном slave с разными функциями; сверить в config.yml).
3. Также через mbusd может работать с AT2 вентиляции.
**Если modbus-bridge не слушает `ttyZONT`** (упал/не запущен) → ZONT не получает ответ на запросы slave 101/102/103 → в интерфейсе ZONT 485-датчики отображаются **«недоступные»**.
### Проблема modbus-bridge/mbusd после рестарта TrueNAS (гонка с udev)
**Симптом:** после перезагрузки TrueNAS `/dev/ttyZONT` и `/dev/ttyVent` присутствуют (`ttyZONT`→ttyUSB1, `ttyVent`→ttyUSB0, создаются init script id=1), НО контейнеры `modbus-bridge`/`mbusd` упали на старте и не перезапустились; 485-датчики в ZONT «недоступные».
**Причина:** docker стартует раньше udev → при `start` контейнера устройство ещё не существует → падение ДО запуска процесса:
```
docker inspect <c> --format '{{.State.Error}}'
error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory
# ExitCode 128 / 255, RestartCount=0
```
`restart: unless-stopped` такой отказ **не подхватывает** (RestartCount=0), и задержка внутри entrypoint не поможет (device mount происходит до старта процесса).
**Ручной фикс:** `docker start modbus-bridge mbusd` (после того как симлинки созданы).
**Защита от рецидива (план, НЕ внедрён, ждёт OK Alex):** `family/how-to/zont-modbus-bridge-udev-race-protection.md` — POSTINIT init script `/mnt/RED_2TB/system/start-modbus.sh`, который ждёт появления `ttyZONT`/`ttyVent` (≤25с) и делает `docker start modbus-bridge mbusd`.
### USB device aliases
Файл правил: `/mnt/RED_2TB/system/99-tty-alias.rules`
```
SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="?-1.6:1.0", SYMLINK+="ttyZONT"
SUBSYSTEM=="tty", KERNEL=="ttyUSB*", KERNELS=="?-1.5:1.0", SYMLINK+="ttyVent"
```
`?` — wildcard на префикс USB-шины (`2`, `3` и т.д.): правила работают даже если хаб переопределяется под другой контроллер (например, после подключения USB3-устройства к тому же хабу).
Применить после изменений:
```bash
cp /mnt/RED_2TB/system/99-tty-alias.rules /etc/udev/rules.d/ && udevadm control --reload-rules && udevadm trigger
```
> `/etc/udev/rules.d/` на TrueNAS — tmpfs, не переживает перезагрузку. Правила применяются автоматически через **TrueNAS Init/Shutdown Scripts** (POSTINIT).
**Просмотреть/изменить:** TrueNAS UI → System → Advanced → Init/Shutdown Scripts, или:
```bash
midclt call initshutdownscript.query
```
Текущая запись (id 1, POSTINIT, comment: "Map ttyUSB"):
```bash
cp /mnt/RED_2TB/system/99-tty-alias.rules /etc/udev/rules.d/ && udevadm control --reload-rules && udevadm trigger
```
## Hermes-Taiga агент
| Параметр | Значение |
|----------|----------|
| Контейнер | `hermes-taiga` |
| Telegram | через общий токен, SOCKS5 прокси `vless-proxy:1080` |
| Модель | **DeepSeek Chat** (`deepseek/deepseek-chat`) |
| Auxiliary | OpenRouter (`openrouter/auto`) |
| Vault (хост) | `/mnt/RED_2TB/storage/obsidian` |
| Vault (контейнер) | `/vault:rw` |
| obsidian-mcp | `/opt/data/.local/bin/mcpvault /vault` |
| Scope | sparse: `personal/ + family/` |
| Toolsets | hermes-cli, file, web, browser |
| web_search | Tavily (`TAVILY_API_KEY` в .env) |
| web_extract | ✅ HTTP-парсинг |
| browser | ✅ Playwright/Chromium (headless, JS-heavy сайты) |
| Прокси | SOCKS5 `vless-proxy:1080` (HTTP/HTTPS/Telegram — все через прокси) |
### SOUL.md — identity & persona (обновлено 2026-05-13)
Файл: `/opt/data/SOUL.md` (монтируется в контейнер, читается Hermes на каждый тёрн).
**Ключевые изменения 2026-05-13:**
- Добавлен блок `## Identity` — Тайга не ассистент, а лес: не извиняется, не суетится, говорит прямо
- Добавлен uncertainty posture: при отсутствии данных говорит "не знаю" / "нет данных в vault", не строит истории
- Тон исправлен: убрано "тёплая" (активировало female-helper архетип), оставлено "спокойная, уверенная, немногословная"
- Добавлена обязанность читать и писать в Obsidian (RULE 2, Vault Access с правильными MCP-командами)
- `display.personality` в config.yaml изменён с `helpful` на `neutral` — убирает Hermes-level "helpful" прайминг поверх soul
**Почему важно:** `display: personality: helpful` в config.yaml инжектировался поверх soul.md и был основным источником извинений и гиперкомпенсации.
### Починка root-проблемы (2026-05-13)
Hermes обновился — появилась проверка на root. Контейнер падал с `Refusing to run as root`.
Фикс: `HERMES_ALLOW_ROOT_GATEWAY=1` + `UV_CACHE_DIR=/tmp/uv-cache` в docker-compose.yml + пересборка с `--no-cache`.
> ⚠️ При обновлении образа — всегда `docker build --no-cache`, иначе `.venv` остаётся от root-слоя и ломает permissions.
## Obsidian Sync (Taiga)
**Скрипт:** `~/sync-vault.sh` (запускается на **хосте**, не в контейнере)
**Крон:** Hermes cron job `0 * * * *`
**Bare repo:** `file:///mnt/RED_2TB/storage/git/obsidian-vault.git`
**Лог:** `/tmp/vault-sync.log`
```bash
# Запустить sync вручную:
bash ~/sync-vault.sh
# Посмотреть лог:
tail -20 /tmp/vault-sync.log
# История коммитов:
git -C /mnt/RED_2TB/storage/git/obsidian-vault.git log --oneline -10
```
> ⚠️ Скрипт запускается от `truenas_admin` — только этот пользователь имеет ZFS ACL доступ к bare repo и vault папке.
Подробности: [[obsidian-sync]]
## Home Assistant — что настроено
### `configuration.yaml`
- `http:` раздел: `use_x_forwarded_for: true`, `trusted_proxies: 172.16.0.0/12` — обязательно для работы через reverse proxy (Caddy)
- Modbus интеграция для вентиляторов AT2 и заслонок
- Template sensors (в блоке `template: - sensor:`):
| Сенсор | Пример | Описание |
|--------|--------|----------|
| `dining_summary` | "24° 450ppm" | Темп и CO₂ в столовой |
| `dining_air_summary` | "65tvoc 3pm" | TVOC и частицы в столовой |
| `kids_summary` | "22° 600ppm" | Темп и CO₂ в детской |
| `bedroom_summary` | "21° 500ppm" | Темп и CO₂ в спальне |
| `at2_1_summary` | "Off" / "45%" | AT2-1: объединённые on/off + скорость |
| `at2_2_summary` | "Off" / "45%" | AT2-2: объединённые on/off + скорость |
### `automations.yaml`
- ГВС циркуляция: вкл (09:30) / выкл (23:00)
- Вентиляционный вентилятор вкл в 05:00
- Проходной выключатель кабинета → toggle света в кабинете (`not_from: [unavailable, unknown]` — защита от ложных срабатываний при запуске HA)
- Подсветка лестницы: вкл/выкл по датчику освещённости
- Диммер спальни: toggle и цикл яркости
- Ночной свет в душе: присутствие + освещённость
- Уведомление: датчик протечки (котельная)
- Уведомления: низкий заряд батареи (несколько устройств)
### Floor Plan Dashboard (`lovelace.home_plan`)
Два вида — Ground Floor (`floor1`) и Second Floor (`floor2`) — `picture-elements` поверх SVG фона.
**Первый этаж (`floor1`):**
- Приточные заслонки: столовая (левая/правая), кабинет
- Вытяжные заслонки: кухня, туалет 1F
- Вентилятор 3 (кухонная вытяжка)
- Метки AT2-1 / AT2-2 (`sensor.at2_1_summary` / `sensor.at2_2_summary`)
- Сауна, обогревательный кабель
- Свет кабинет (левый/правый)
- Метка столовой (`sensor.dining_summary`) и качество воздуха (`sensor.dining_air_summary`)
**Второй этаж (`floor2`):**
- Приточные заслонки: детская, спальня, север
- Вытяжные заслонки: ванная, душ 2F
- Свет спальни (диммер)
- Метки: `sensor.kids_summary`, `sensor.bedroom_summary`
**SVG dark mode** — встроенный CSS в SVG-файлах:
```svg
<style>
@media (prefers-color-scheme: dark) {
path, line, polyline, polygon, rect, circle, ellipse { stroke: white; }
}
</style>
```
> ЖJSON Lovelace зафиксирован в git по пути `floorplan/lovelace.home_plan.json` (справочный снимок, HA **не** подгружает его автоматически).
---
## 🔻 Декоммиссия стека автоматизации TrueNAS → t610 (аудит 2026-09-14)
**Контекст:** миграция умного дома TrueNAS → HP t610 (HA OS) завершена (п.5-мк плана [[family/plans/t610-home-automation]] закрыт). Остался **п.6** — погасить дублирующий стек на TrueNAS. Вместо слепого «гасим всё» проведён **аудит фактом** (что реально живо, что мёртво, что нельзя трогать).
### Что искали и как (методика аудита)
| Шаг | Команда | Зачем |
|---|---|---|
| Список контейнеров | `docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}'` | кто жив/умер, какие порты торчат |
| Кто чем управляется | `for c in $(docker ps -a --format '{{.Names}}'); do docker inspect $c --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'; done` | 🔑 **все** оказались per-service compose из `/mnt/RED_2TB/docker/<app>/` (не Portainer-стек). В `portainer/data/compose/`**пусто**. |
| Почему умер | `docker inspect <c> --format '{{.State.Error}} {{.State.ExitCode}} {{.State.FinishedAt}}'` + `docker logs --tail 20 <c>` | точное время и причина |
| Есть ли железо | `ls /sys/bus/usb/devices/` + `cat .../product`,`idVendor:idProduct` | на TrueNAS только принтер Samsung `04e8:3425` (Intel `8087:0024` = USB-контроллеры). **CH340/координатора НЕТ.** |
| `lsusb`/`dmesg` | — | ❌ **недоступны** `truenas_admin` (`command not found`); `dmesg` пуст без root. Использовать `/sys/bus/usb`. |
| Кто ссылается | `grep -nE '...' /mnt/RED_2TB/docker/caddy/Caddyfile` | не сломать рабочие домены |
> 🔑 **Питфолл:** `docker inspect <c>` **работает** под `truenas_admin` без sudo, а `midclt call ...` и `dmesg` — **нет** (нужен root). Для аудита хватает `docker` + `/sys`.
### Вердикт по каждому контейнеру
| Контейнер | Состояние | Причина | Решение |
|---|---|---|---|
| `homeassistant` | Up 5 дн | холостой — `modbus.host=192.168.2.197`, шины там нет | ✅ **ПОГАШЕН 2026-09-14** |
| `mbusd` | Up (ложно), 14:42 `can't open /dev/ttyUSB0` | `/dev/ttyVent` не существует (USB уехал) | ✅ **ПОГАШЕН 2026-09-14** |
| `mosquitto` | Up 3 нед | ZONT переключён на `.176` (DNAT) | ✅ **ПОГАШЕН 2026-09-14** |
| `nodered` | Up (healthy) | flows перенесены на t610 (68 узлов) | ✅ **ПОГАШЕН 2026-09-14** (решение Alex: «Гасим nodered») |
| `zigbee2mqtt` | Exited (2) **14.09 01:59** | `Adapter disconnected` — координатор на t610 | ✅ `restart=no` 2026-09-14 |
| `modbus-bridge` | Exited (0) **14.09 01:59** | `/dev/ttyZONT` исчез | ✅ `restart=no` 2026-09-14 |
| **`caddy`** | Up | **17 доменов TrueNAS + `mallexxx.*` → t610** | 🔴 **НЕ ТРОГАТЬ** (не тронут) |
| `ser2net` | `Created` (никогда не стартовал) | конфликт 502 с mbusd | ✅ **ПОГАШЕН 2026-09-14** (по команде Alex) |
| `library` | ~~Restarting, restart=29752~~ | 🔴 циклический краш, Caddy ссылается (`library:8080`) | ✅ **ПОГАШЕН 2026-09-14** (по команде Alex); причина краша открыта |
| `inpx-web`, `inpxer` | Exited (1), 13 рестартов, 3 нед | циклический краш | 🔴 **НЕ ТРОГАТЬ** (указание Alex) |
**Ключевой факт-маркер переезда:** `zigbee2mqtt` и `modbus-bridge` **оба** легли в **2026-09-14T01:59** — синхронно, в момент физического переноса USB-адаптеров. Это доказательство, что дубль перестал работать сам, а не «сломался от чего-то».
### Порядок безопасного гашения (одобренный шаблон)
```bash
# 1) ГАСИМ, НЕ УДАЛЯЕМ (откат возможен)
docker stop homeassistant mbusd mosquitto nodered zigbee2mqtt modbus-bridge
# 2) Снять автозапуск, чтобы не поднялись после ребута
docker update --restart=no homeassistant mbusd mosquitto nodered zigbee2mqtt modbus-bridge
# 3) Проверки
curl -s -o /dev/null -w '%{http_code}\n' https://mallexxx.duckdns.org # ожидаем 200 (t610)
# ZONT MQTT: живой поток в mosquitto на .176, а НЕ на .197
# 4) Папки /mnt/RED_2TB/docker/* НЕ удалять — 2-3 дня, потом rm отдельным шагом
```
**Правила этого шага:**
-**НЕ** `docker rm`, ❌ не удалять `/mnt/RED_2TB/docker/<app>/` — сначала «погасить», откат = `docker start` + вернуть `restart: unless-stopped`.
-**Caddy не гасить и не переносить** — 17 из 20 доменов это сервисы TrueNAS.
-`inpx-*`**не трогать** (указание Alex). `library`**погашен отдельной командой Alex** (2026-09-14), причина краша не выяснена.
- ⚠️ Порт 502: `mbusd` и `ser2net` **не поднимать одновременно** (оба погашены).
- **✅ Факт выполнения 2026-09-14:** погашено 9 контейнеров (7 автоматизации + `ser2net` + `library`). Проверено: 502/1883/8123/1880 на TrueNAS свободны, `mallexxx.duckdns.org` = 200, MQTT на `.176` живой, RTSP `:8554` OPEN.
---
## Печать / cups-splix (2026-08-26, починено)
**Принтер Samsung CLX-216x подключён по USB к TrueNAS** (не в сети!). Единственный путь печати — контейнер `cups-splix`, который раздаёт CUPS на `192.168.2.197:631`.
**Почему телефон не видел принтер (2026-08-26):** после пересоздания пула контейнер `cups-splix` **не был поднят** — образ локальный (не registry), стёрлся вместе с `.ix-apps`; при восстановлении его не пересобирали (пометка «проверить при надобности»). Конфиг `/mnt/RED_2TB/docker/cups/data` (это `/etc/cups`) цел → принтер прописан и подцепился после рестарта сам.
**Рецепт подъёма (при «не вижу принтер»):**
```bash
cd /mnt/RED_2TB/docker/cups
docker build -t cups-splix . # образ локальный, собрать заново (~3.5 мин)
docker compose up -d # поднять (privileged + /dev/bus/usb)
docker exec cups-splix lpstat -p -d # проверить принтер
nc -z 192.168.2.197 631 # проверить порт наружу
```
- Принтер: `usb://Samsung/CLX-216x%20Series?serial=9566BAGQ213134Z.&interface=1` (USB ID `04e8:3425` Samsung CLX-216x).
- Порт 631: открыт наружу после подъёма.
### ✅ mDNS/AirPrint анонс принтера — включён 2026-08-31 (Android print service видит принтер)
Проблема: Android **штатная служба печати** (в отличие от Samsung Mobile Print, который ходит прямо по IP) ищет принтер **только через mDNS/Bonjour** (`_ipp._tcp.local`). CUPS не анонсировал: в контейнере не было `avahi-daemon`, а `printer-dns-sd-name` в IPP был `no-value` → Android помечал принтер «недоступен», даже добавленный вручную по IP.
**Решение (выполнено):** пересобрали cups-splix — теперь запускает `dbus-daemon` + `avahi-daemon` рядом с cupsd через `entrypoint.sh`, и в `cupsd.conf` включено `Browsing On` + `BrowseLocalProtocols dnssd`. После этого CUPS регистрирует принтер в avahi → mDNS-анонс с **`mopria-certified=1.3`** на IPv4 `192.168.2.197` физического интерфейса `enp3s0`. Android (Mopria) теперь находит принтер сам в локальной сети.
**Что изменилось в конфиге** (папка `/mnt/RED_2TB/docker/cups/`):
- `Dockerfile`: добавлен `avahi-daemon` в apt, написан `entrypoint.sh`, `ENTRYPOINT` вместо `CMD` (`.old` образ сохранён как `cups-splix-old`).
- `entrypoint.sh`: стартует `dbus-daemon --system`, затем `avahi-daemon --no-drop-root`, затем `exec cupsd -f`.
- `data/cupsd.conf`: `Browsing Off``Browsing On` + добавлена строка `BrowseLocalProtocols dnssd` (бэкап `cupsd.conf.pre-avahi`).
**⚠️ Важный питфолл:** после правки конфига НЕ использовать `docker restart cups-splix` — он убивает avahi-daemon (defunct), перед новым подъёмом обязателен **`docker stop cups-splix && docker rm cups-splix && docker compose up -d`** (полный пересоздание, чтобы entrypoint перевыполнился с нуля).
**Проверка анонса:**
```bash
docker exec cups-splix sh -c "timeout 6 avahi-browse -rt -p _ipp._tcp | grep ';enp3s0;IPv4;'"
# должно показать: ... Samsung\032CLX-216x... truenas.local;192.168.2.197;631; "mopria-certified=1.3" ...
```
**Бэкап конфига (2026-08-31):** `/mnt/RED_2TB/docker/cups/backup_20260831-003619.tar.gz` (md5 `0e303a6a57ae767d1e14cd72c8039fe4`) — tar из /etc/cups, /var/spool/cups, /var/cache/cups.
> Диагностика и полное объяснение: [[mac-print-shared-services]]
> ⚠️ **2026-08-31: топология изменена.** TrueNAS больше НЕ в локальной сети (только публичный DNS `mallexxx.duckdns.org`) — из других подсетей/внешки `192.168.2.197` недостижим, и **снаружи `mallexxx.duckdns.org:631` закрыт**. НО **из самой подсети `192.168.2.x` TrueNAS достижима** (телефон `192.168.2.141` успешно печатал по `192.168.2.197:631` — CUPS access_log это подтверждает). → Samsung Mobile Print (app) печатает (висит на локальном IPP внутри подсети), а штатная Android print service с `ipp://192.168.2.197:631/...` показывала «недоступен» из-за **отсутствия mDNS/AirPrint-анонса** (avahi-daemon не запущен; `printer-dns-sd-name = no-value`). ✅ **Исправлено** (см. раздел «✅ mDNS/AirPrint анонс принтера»): cups-splix пересобран с avahi-daemon, cupsd.conf получил `Browsing On` + `BrowseLocalProtocols dnssd` → принтер анонсируется по mDNS (`mopria-certified=1.3`, IPv4 `192.168.2.197`); Android-служба теперь находит принтер сама. Детали и откат: [[mac-print-shared-services]].
> ✅ **2026-09-02: печать ИЗВНЕ сети TrueNAS работает через SSH → cups-splix.** Хотя `mallexxx.duckdns.org:631` (IPP) снаружи закрыт, документ (PDF, 1 стр A4) успешно напечатан с клиента вне подсети: `scp` → TrueNAS `/tmp` → `docker cp` внутрь `cups-splix:/tmp` → `docker exec cups-splix lp -d Samsung_CLX-216x_Series -o media=A4 file.pdf` → job в `completed`, `Rendering completed`. CUPS сам конвертит PDF→PS (gs/pdftops есть, PPD `*cupsFilter: 0 pstoqpdl`). Полный рецепт — [[mac-print-shared-services]] (раздел «Печать PDF извне сети TrueNAS»).
## Связанные заметки
- [[truenas-access]] — SSH-доступ
- [[truenas-rclone-backup]] — система бэкапов
- [[obsidian-sync]] — Obsidian sync Eagle ↔ Taiga ↔ Kraken
- [[openmediavault-rpi5]] — Kraken NAS (Hermes агент, sync)