857 lines
103 KiB
Markdown
857 lines
103 KiB
Markdown
# TrueNAS — инфраструктура
|
||
|
||
> ✅ **ДОМАШНЯЯ АВТОМАТИЗАЦИЯ ПЕРЕНЕСЕНА НА HP t610 (2026-09-14).** HA, zigbee2mqtt, mosquitto, mbusd, modbus-bridge **и flows Node-RED** переехали на **t610** (HA OS, `192.168.2.176`). Единый документ по t610 — [[family/how-to/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/how-to/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/how-to/home-automation]] §5-кватер-И-3/И-6.
|
||
> - **Не перенесено с TrueNAS:** ~~погашение TrueNAS-стека (Этап 4 п.6 — заблокировано: Caddy на TrueNAS держит точку входа)~~ → **✅ ЗАКРЫТО 2026-09-14 (ночь): стек автоматизации ПОГАШЕН, Caddy остался на TrueNAS (так и задумано).** См. §5-кватер-Л в [[family/how-to/home-automation]].
|
||
|
||
> ## 🏁 2026-09-15 (ФИНАЛ) — ШТАТНАЯ ПОДПИСКА РАБОТАЕТ, СТАТИКА `space-` ВЫЧИЩЕНА. `vless-proxy` ПОДКЛЮЧЁН.
|
||
>
|
||
> **Итог:** egress через **штатный механизм `outbound_subscriptions`** (28 серверов `sub1-*`, авто-обновление 600 с). Статические `space-01…10` **удалены** как костыль. Живой тест: `vless-proxy:1080` → `104.28.219.140` / `188.239.191.18` ≠ `90.189.160.148`.
|
||
>
|
||
> | Что | Значение |
|
||
> |---|---|
|
||
> | `outbound_subscriptions` | `remark=vless-space`, `tag_prefix=sub1-`, `update_interval=600` |
|
||
> | outbounds | 31 = `direct`+`blocked`+`via-kraken` + **28 × `sub1-*`** |
|
||
> | балансировщик | `space-balancer`, `selector: ["sub1-"]`, `leastLoad` |
|
||
> | observatory | **`burstObservatory`**, `subjectSelector: ["sub1-"]`, `pingConfig{sampling:2, interval:1m}` |
|
||
> | `routing.rules` | `{"user":["vless-space"],"balancerTag":"space-balancer"}` |
|
||
> | клиенты | `user1`, `kraken-user`, `vless-space` — целы |
|
||
>
|
||
> ✅ **Доки актуализированы 2026-09-15** — сняты устаревшие статусы «`vless-space` НЕ СОЗДАН / БД откачена» и «авто-обновление не начато».
|
||
>
|
||
> ### 🔑 ТРИ ПИТФОЛЛА БАЛАНСИРОВЩИКА — все три обязательны
|
||
>
|
||
> Ошибка `app/dispatcher: non existing outTag: space-balancer` вызывалась **тремя независимыми причинами** (каждая воспроизведена и снята отдельно):
|
||
>
|
||
> | # | Причина | Фикс |
|
||
> |---|---|---|
|
||
> | 1 | правило ссылалось через `outboundTag` | → **`balancerTag`** |
|
||
> | 2 | `strategy: leastPing` (в Xray 26.x балансировщик не создаётся) | → **`leastLoad`** |
|
||
> | 3 | в observatory отсутствовал `sampling` | → **`"sampling": 3`** |
|
||
>
|
||
> ### 🔴 ЧЕТВЁРТЫЙ ПИТФОЛЛ (стоил этой сессии) — два поля селектора + два имени секции
|
||
>
|
||
> **а) `selector` и `subjectSelector` — РАЗНЫЕ поля, менять ПАРОЙ.** Сменил префикс подписки → проверь оба:
|
||
> ```bash
|
||
> docker exec xray-admin cat /app/bin/config.json | jq -c '{bal:.routing.balancers[0].selector, obs:(.burstObservatory // .observatory).subjectSelector}'
|
||
> # оба должны быть ["sub1-"]
|
||
> ```
|
||
> **б) Секция в UI называется `burstObservatory`, не `observatory`.** Xray 26.x принимает обе; панель при сохранении может удалить `observatory` и создать `burstObservatory`. **Проверять `keys[]`, оба имени:**
|
||
> ```bash
|
||
> docker exec xray-admin cat /app/bin/config.json | jq -r 'keys[]'
|
||
> docker exec xray-admin cat /app/bin/config.json | jq -c '.burstObservatory // .observatory'
|
||
> ```
|
||
> **в) Симптом рассинхрона — молчаливый `direct`:** `subjectSelector` не матчит ни один outbound → `leastLoad` без живых кандидатов → трафик в **первый outbound списка**. **Ошибок в логе НЕТ.**
|
||
>
|
||
> ⚠️ **`xray -test` печатает `Configuration OK` при всех этих ошибках** — семантику маршрутизации ловит только рантайм-лог (`non existing outTag`) + живой запрос через клиент.
|
||
>
|
||
> **Артефакты:** `~/tmp-xray-space/` — `xui_v9.db` (статика, рабочая история), `xui_v10.db`, `xui_v10_src.db`, `strip_space_outbounds.sh`, `write_v10.sh`, `vless-proxy-config-new.json`. Бэкапы `/mnt/RED_2TB/docker/backups/xray-admin-before-cleanup-20260915-035749/` + `xray-admin-before-vless-space-20260915-012057` (точка отката).
|
||
>
|
||
> ---
|
||
>
|
||
> ## 🔗 `vless-proxy` → `xray-admin` (2026-09-15)
|
||
>
|
||
> **Что было:** `vless-proxy` (SOCKS `:1080` + HTTP `:1081`) смотрел на **мёртвый** `v.qentra.top` → `hermes-taiga` (Telegram/Discord) без сети.
|
||
>
|
||
> **Что стало** — `/mnt/RED_2TB/docker/vless-proxy/config.json`:
|
||
>
|
||
> | Поле | Было | Стало |
|
||
> |---|---|---|
|
||
> | `vnext[0].address` | `v.qentra.top` | `vpn.mallexxx.duckdns.org` |
|
||
> | `vnext[0].users[0].id` | `2D9F24C4-…` | `a792c483-07e2-4723-9c50-78054c0abc07` (`vless-space`) |
|
||
> | `tlsSettings.serverName` | `v.qentra.top` | `vpn.mallexxx.duckdns.org` |
|
||
> | `wsSettings.path` | `/qentra` | `/vless` |
|
||
> | `wsSettings.headers.Host` | `v.qentra.top` | `vpn.mallexxx.duckdns.org` |
|
||
>
|
||
> Порт 443, `security: tls`, `network: ws` — без изменений.
|
||
>
|
||
> **Цепочка:** `hermes-taiga → vless-proxy:1080 → vpn.mallexxx.duckdns.org:443 → xray-admin → 28 × sub1-* → интернет`
|
||
> Env `hermes-taiga` (`TELEGRAM_PROXY`, `DISCORD_PROXY` = `socks5://vless-proxy:1080`) **менять не нужно** — рестарт не требуется, SOCKS-соединения устанавливаются на каждый запрос.
|
||
>
|
||
> 🔴 **Правильная проверка egress (питфолл):** `wget` **не умеет SOCKS5** — `docker exec vless-proxy wget -qO- https://api.ipify.org` вернёт **локальный** IP контейнера `90.189.160.148` и создаст ложное впечатление «direct». Проверять только через SOCKS-прокси:
|
||
> ```bash
|
||
> docker run --rm --network hermes_taiga_net alpine sh -c \
|
||
> "apk add -q curl; curl -s --max-time 20 --socks5-hostname vless-proxy:1080 https://api.ipify.org"
|
||
> # ожидается НЕ 90.189.160.148
|
||
> ```
|
||
>
|
||
> 🔴 **ДОСТУП (проверено 2026-09-15):** `/mnt/RED_2TB/docker/vless-proxy/` — `root:root 755`, `config.json` примонтирован `:ro`, внутри контейнера `/etc/xray/config.json` тоже `Read-only file system`. **`truenas_admin` править НЕ может** (`touch` → Permission denied; `sudo` требует пароль; `root@192.168.2.197` → publickey denied). Файл правит **только Alex от root**; агент готовит конфиг локально (`~/tmp-xray-space/vless-proxy-config-new.json`) и отдаёт целиком.
|
||
>
|
||
> ⚠️ **`docker compose up -d hermes-taiga` → `no such service`.** Сервис в `/mnt/RED_2TB/docker/hermes/docker-compose.yml` называется **`taiga`** (`hermes-taiga` — это `container_name`). Правильно: `docker compose up -d taiga`.
|
||
>
|
||
> 🔴 **Прежний хард-вывод «3x-ui нельзя править снаружи» — ОКОНЧАТЕЛЬНО ОПРОВЕРГНУТ.** SQLite-путь работает при двух условиях: (1) в `xrayTemplateConfig` нет инбаунда (только `api`), (2) БД правится локально на Mac и кладётся файлом с `rm -f *.db-wal *.db-shm` + `chown 950:root`.
|
||
>
|
||
> **⚠️ ОТДЕЛЬНАЯ НЕЗАКРЫТАЯ ПРОБЛЕМА — `kraken-user`:** не работает, потому что **сервер Kraken недоступен** (не связано с БД). Проверено 2026-09-15: `ssh-kraken.qentra.top` → `Connection timed out during banner exchange`; `kraken@10.99.1.2:22` → `Operation timed out`; DNS `kraken` → NXDOMAIN. Портал на TrueNAS жив (`xray-reverse-portal` Up, `12345`/`12346` LISTEN), но соединений от бриджа **ноль** → ждём восстановления Kraken (решение Alex «подождём, может оживет»).
|
||
>
|
||
> **✅ РЕШЕНО 2026-09-15 (штатная подписка).** Было: `space-01…10` статически вбиты в шаблон — при смене списка у `profilegrid` всё ломалось молча. Стало: штатная таблица **`outbound_subscriptions`** 3x-ui (`remark=vless-space`, `tag_prefix=sub1-`, `update_interval=600`) → **28 серверов `sub1-*`, авто-обновление**. Статика `space-01…10` **удалена**. Балансировщик `space-balancer`: `selector: ["sub1-"]`, `leastLoad`; наблюдение — **`burstObservatory`** с `subjectSelector: ["sub1-"]`. Ручная пересборка шаблона больше НЕ нужна.
|
||
>
|
||
> **Правила взаимодействия (Alex, 2026-09-15):** команды — плоские однострочники, **без `ssh … '…'`-обёртки**, **без `sleep N`**, **без кириллицы в bash**, без `execute_code`/python. Правку SQLite делать **локально на Mac**, потом заливать готовый файл.
|
||
>
|
||
> **✅ Compose-файл `xray-admin` ВОССТАНОВЛЕН** из `docker inspect` (пережил все откаты). Полный разбор, процедура повторения и таблица диагностики — [[personal/tech/vless-space-subscription-egress]] / [[personal/tech/xray-outbound-subscription-3xui]].
|
||
>
|
||
> Обновлено (ранее): 2026-09-15 — попытки 1–7 (провалившиеся) приводятся в [[personal/tech/vless-space-subscription-egress]]; их итог — «`vless-space` НЕ СОЗДАН, БД ОТКАЧЕНА», что **с тех пор устарело**: задача закрыта в попытке 9 и переведена на штатную подписку (см. выше ✅ РЕШЕНО). Единственный живой вывод оттуда: **3x-ui НЕЛЬЗЯ править снаружи работающего контейнера** — клиенты инбаунда только через панель/API-токен; работает через SQLite лишь `settings.xrayTemplateConfig` (outbound'ы/правила/балансировщик). Остальные детали (7 подходов, `auth`/`reverse`=`NULL`, инбаунд-в-шаблоне) — исторические грабли, разобраны по ссылке.
|
||
|
||
> ## ⚠️ ПРИОРИТЕТ 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 ~28–51 Мбит впритык к пикам файла). НЕ транскодинг (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-admin`: compose-файл УТРАЧЕН (обнаружено 2026-09-15).** В `/mnt/RED_2TB/docker/xray-admin/` лежат только `x-ui.db`, `-shm`, `-wal`, `system_metrics.gob`. Docker label указывает на `docker-compose.yml`, но файла нет. **Причина (найдено через Zulip DB, `personal/zulip router issues`, id=86681):** 2026-09-01 05:40:08 UTC агент выполнил `docker exec xray-admin rm -f /etc/x-ui/docker-compose.yml` — volume смонтирован как `/etc/x-ui` (bind-mount), поэтому `rm` внутри контейнера снёс файл на хосте, через 1,5 минуты после создания. **Пересоздать контейнер из папки сейчас НЕЛЬЗЯ** — только из `docker inspect`. Подробно и параметры для восстановления: [[family/plans/reverse-xray-3xui-kraken]]. Проверить перед любым `docker compose` по этому сервису.
|
||
| 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/how-to/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/how-to/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)
|
||
|
||
> ### ✅ SUBSCRIPTION-КАНАЛ (auto-обновление клиентов) — работает, проверено 2026-09-15
|
||
>
|
||
> **Прямой ответ на вопрос Alex «можно поменять на xray subscription channel (auto)?»: да — он УЖЕ есть, включать ничего не надо. Ошибка была в том, что в клиент вбивали одиночный `vless://…`, а нужна ССЫЛКА ПОДПИСКИ.**
|
||
>
|
||
> | Что | Значение (проверено живьём 2026-09-15) |
|
||
> |---|---|
|
||
> | Базовый sub-URL | `https://vpn-panel.mallexxx.duckdns.org/sub/` → **HTTP 200** |
|
||
> | `user1` (direct, TrueNAS `90.189.160.148`) | `https://vpn-panel.mallexxx.duckdns.org/sub/68c5cy5n5ui138yh` |
|
||
> | `kraken-user` (egress через Kraken `92.62.70.41`) | `https://vpn-panel.mallexxx.duckdns.org/sub/f43074a029dc656e` |
|
||
> | `vless-space` (egress через external-подписку) | `https://vpn-panel.mallexxx.duckdns.org/sub/24df9391356b48ff` |
|
||
> | Формат ответа | **base64-список `vless://`** (стандарт «subscription channel») |
|
||
> | Settings в `x-ui.db` | `subDomain=vpn-panel.mallexxx.duckdns.org`, `subPort=443`, `subScheme=https`; у каждого клиента своё поле **`subId`** (16 символов) |
|
||
>
|
||
> **Разложенный payload `user1`** (для проверки совпадения с ручным конфигом):
|
||
> ```
|
||
> vless://ce320965-6956-4759-84bb-7cb71cfc6252@vpn.mallexxx.duckdns.org:443?encryption=none&host=vpn.mallexxx.duckdns.org&path=%2Fvless&security=tls&type=ws#vless-ws-user1
|
||
> ```
|
||
> ```
|
||
> vless://93a5dc4b-1b8d-4af5-9363-eb0091734293@vpn.mallexxx.duckdns.org:443?encryption=none&host=vpn.mallexxx.duckdns.org&path=%2Fvless&security=tls&type=ws#vless-ws-kraken-user
|
||
> ```
|
||
>
|
||
> **Как включить авто-обновление в клиенте (3 шага):** ① удалить вручную вбитый профиль/сервер; ② «Add subscription» → вставить ПОЛНЫЙ путь `…/sub/<subId>` (без `/sub` не работает); ③ включить **auto update interval** (6–12 ч). Новые клиенты, добавленные в панели, после этого появляются в клиенте сами — руками `vless://` больше вбивать не нужно.
|
||
>
|
||
> **Где искать «auto» по приложениям** (ответ на вопрос Alex 2026-09-15 «какой клиент» — уточнение не понадобилось, докрыто здесь):
|
||
> | Клиент | Как добавить | Где авто-обновление |
|
||
> |---|---|---|
|
||
> | **Happ** (iOS/Android) | «+» → **Add subscription** → вставить URL | в настройках подписки, «Auto update» + интервал |
|
||
> | **v2rayN** (Windows) | Subscriptions → **Add subscription** | «Sub update interval» (мин) в настройках подписки |
|
||
> | **NekoBox / sing-box** (Android) | Группа → **Add subscription** | в свойствах группы, «Auto update» + интервал |
|
||
> | **Streisand** (iOS) | «+» → **Subscription** | внутри подписки, «Auto update» |
|
||
> | **Xray/`xray-core` в docker** | — | ❌ **не умеет.** Только статический `config.json`; «auto» = внешний cron-скрипт (`curl` sub → `base64 -d` → собрать config → `docker restart`) |
|
||
> ⚠️ Обязательное условие во всех: вставлять **полный URL с `/sub/<subId>`**, а не одиночный `vless://…` — иначе получится статический сервер без обновления.
|
||
>
|
||
> **Команды проверки подписки (с TrueNAS, без правки чего-либо):**
|
||
> ```bash
|
||
> ssh truenas_admin@mallexxx.duckdns.org
|
||
> curl -sk -o /tmp/s.txt -w 'HTTP %{http_code} size %{size_download}\n' https://vpn-panel.mallexxx.duckdns.org/sub/<subId>
|
||
> curl -sk https://vpn-panel.mallexxx.duckdns.org/sub/<subId> | base64 -d # → vless://… построчно
|
||
> ```
|
||
> **Где брать `subId`** (в контейнере нет `sqlite3`):
|
||
> ```bash
|
||
> docker exec xray-admin sh -c "strings /etc/x-ui/x-ui.db | grep -o '\"subId\":\"[a-z0-9]*\"'"
|
||
> ```
|
||
> ⚠️ `jq`/`python3` в контейнере `xray-admin` не проверялись — использован `strings` (проверенный на TrueNAS приём, см. диагностические питфоллы ниже).
|
||
>
|
||
> **Что панель ТЕКУЩЕЙ версии (3.7.0) умеет и не умеет по подпискам:**
|
||
> - ✅ **Есть:** `subId` на клиента, sub-сервер (`/sub/<subId>` → base64 vless-список), настройки `subEnable/subPath/subURI/subJsonEnable/subJsonPath/subJsonURI/subClashEnable/subClashPath/subClashURI/subTitle/subListen/subUpdates/subDomain/subPort/subScheme/subCertFile/subKeyFile`, шаблоны `custom-subscription-templates`, таблица `sub_balancers`, `last_sub_fetch` в `client_traffics` (панель видит, кто и когда тянул подписку).
|
||
> - ❌ **НЕТ «subscription channel» как отдельной сущности с ветками/каналами** (типа mihomo-«channel»/Nekoray-«channel»): в бинарнике `/app/x-ui` **нет ни одной строки `channel` в этом смысле** и нет API-роутов каналов. Есть категории **`subJsonURI` / `subJsonPath`** — это JSON/Mihomo-формат той же подписки, `XUI`/`subClashEnableRouting` — mihomo-специфика. То есть «channel» = **ссылка подписки + клиентский auto-update**, отдельного механизма в панели нет.
|
||
> - Роуты панели по темам подписок (из `strings /app/x-ui`): `/panel/api/clients/sub`, `/panel/api/sub-balancers*`, `/panel/api/xray/outbound-subs*`. (`outbound-subs` = панель сама тянет ВНЕШНИЕ подписки в свои outbound — противоположное направление, не клиентская подписка.)
|
||
>
|
||
> ✅ **ОТКРЫТЫЙ ВОПРОС БЕЗОПАСНОСТИ (задан Alex 2026-09-15, решения НЕТ):** путь `/sub/<subId>` отдаётся **без авторизации** — `/sub/abc` тоже даёт 200. Кто знает `subId` — получает рабочий ключ. Возможный фикс: подписка по токену/`subUpdates`-проверке в настройках панели либо короткий `subId` + ротация. **Ничего не менялось, ждём решения.**
|
||
>
|
||
> ### 🔴 ПИТФОЛЛ: подмена `x-ui.db` при ЖИВОМ контейнере ТЕРЯЕТ панельные данные (2026-09-15)
|
||
>
|
||
> **Как было потеряно:** снят `x-ui.db` при работающем контейнере → `docker stop` (панель сбросила WAL в файл) → поверх положен снятый ранее файл → **запись `outbound_subscriptions` уничтожена**.
|
||
>
|
||
> Панель пишет в `-wal`; `sqlite3 x-ui.db "SELECT …"` снаружи показывает **устаревшие** данные (0 записей при живой подписке).
|
||
>
|
||
> **Правильный порядок:** `docker stop` **ДО** скачивания БД. Если остановить нельзя — читать WAL через `strings /mnt/RED_2TB/docker/xray-admin/x-ui.db-wal` (не через `sqlite3` на файле). Признак: `SELECT COUNT(*) FROM outbound_subscriptions` → `0`, а панель запись показывает.
|
||
>
|
||
> **Восстановление:** заново добавить подписку в UI (`Xray → Outbound Subscriptions`). Бэкапы БД старше правки пусты — URL подписки в доке не хранится.
|
||
|
||
> ### 🧹 ЧИСТКА ЭТОЙ ДОКИ (2026-09-15, Alex: «Убирай»)
|
||
>
|
||
> Из документа вырезан блок-летопись **«⚠️ ИСТОРИЯ (2026-09-15, ранние попытки) — АРТЕФАКТЫ ГОТОВЫ, ПРИМЕНЕНИЕ НЕ ВЫПОЛНЕНО»** (163 строки) вместе с вложенной в него подзадачей `hermes-taiga`. Причина: описывал состояние «задача не выполнена», противоречащее факту, и содержал ложное утверждение «Xray не умеет подписки → авто только в GUI».
|
||
>
|
||
> - Файл: **990 → 836 строк**. Бэкап вырезанного: `family/how-to/truenas-infrastructure.md.bak-before-cut-history` (в той же папке, `.gitignore`-независимый; при необходимости восстановить — файл .md перезаписать из .bak).
|
||
> - Инструмент вырезания: `~/tmp-xray-space/cut_history_block.py` (на Mac; режет по маркерам начала/конца, **сначала пишет `.bak`**, никакого `sed`).
|
||
> - Восстановлен украденный подзаголовок `### xray-admin — 3x-ui панель` (был внутри вырезанного блока — без него секция пропадала из оглавления).
|
||
> - Проверено: осиротевших ссылок на вырезанный раздел в vault — 0 (`grep -rn` по всем `.md`).
|
||
> - **Оставлены намеренно** (помечены как летопись, не врут о текущем статусе): §«ПОПЫТКА 1…8» и §«ПРЕДЫДУЩИЙ ФИНАЛ» в [[personal/tech/vless-space-subscription-egress]] — полезны как грабли.
|
||
|
||
---
|
||
|
||
### `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), `vless-space` (подписка profilegrid — см. ниже) |
|
||
| Sub-сервер | `[::]:443` (path /sub), панель `[::]:2053` |
|
||
| Env | `TZ=Asia/Novosibirsk`, `PUID=950`, `PGID=950`, `XUI_IN_DOCKER=true`, `XUI_MAIN_FOLDER=/app`, `XUI_ENABLE_FAIL2BAN=true`, `XUI_DB_TYPE=`, `XUI_DB_DSN=` |
|
||
| Ports (host) | `54321:54321` (не используется панелью — внутри панель на 2053, можно убрать) |
|
||
| **Compose** | `/mnt/RED_2TB/docker/xray-admin/docker-compose.yml` — **✅ ВОССТАНОВЛЕН 2026-09-15** из `docker inspect` (был утрачен 2026-09-01, см. [[family/plans/reverse-xray-3xui-kraken]]). `docker compose config` валиден, `docker compose ps` распознаёт контейнер. |
|
||
|
||
> 🔴 **ПИТФОЛЛ `xray-admin` (bind-mount `/etc-x-ui`):** правка/удаление файлов внутри контейнера в пути `/etc/x-ui/` **бьёт прямо по хосту** — это тот же самый каталог. Именно так 2026-09-01 был уничтожен `docker-compose.yml` (`docker exec xray-admin rm -f /etc/x-ui/docker-compose.yml`). Никогда не делать `rm`/`mv` в `/etc/x-ui` изнутри контейнера. Файлы складывать на хост через `docker run --rm -v /tmp:/src -v /mnt/RED_2TB/docker/xray-admin:/dst alpine cp …`.
|
||
|
||
> 🔴 **ПИТФОЛЛ правки SQLite `x-ui.db` (WAL):** база работает в WAL-режиме. Нельзя копировать только `.db` и класть рядом со старыми `-wal`/`-shm` → `database disk image is malformed`. Правильно: `docker stop xray-admin` → `rm -f x-ui.db-wal x-ui.db-shm` → SQL напрямую в `/data/x-ui.db` → `chown 950:root` → `docker start`. Лучше всего — вообще править через панель.
|
||
|
||
> 🔴 **ПИТФОЛЛ ручного `INSERT` в таблицу `clients`:** SQLite ставит `NULL` в колонки, не указанные в `INSERT`. Заполнять все текстовые колонки (`auth`, `reverse`, `flow`, `password`, `group_name`, `security`) пустой строкой `''` / значением по образцу живого клиента. **НО:** проверено 2026-09-15 — даже при полностью корректной БД (все типы совпадают, `integrity ok`, шаблон валиден, Xray принимает конфиг `Configuration OK`) **клиент, добавленный в `clients` снаружи, в `config.json` НЕ появляется.** Причина — 3x-ui рендерит список клиентов из своего внутреннего состояния, а не из файла БД. **Правка клиентов инбаунда возможна ТОЛЬКО через панель (`/panel/api/inbounds/update/:id`) или её API-токен.** См. [[personal/tech/vless-space-subscription-egress]].
|
||
|
||
> 🔴 **3x-ui держит БД открытой:** при живом контейнере `x-ui.db` на диске показывает **старую дату** — правки уходят в `-wal`. Удаление `-wal` перед правкой уничтожает актуальные данные 3x-ui. Признак, что правка не применилась: `ls -la /app/bin/config.json /etc/x-ui/x-ui.db` → если БД датирована раньше правки, 3x-ui её не перечитал.
|
||
|
||
> ✅ **ПРАВИЛЬНЫЙ способ правки SQLite (установка Alex, 2026-09-15):** базу `scp` на Mac → править и проверять **локально** (`sqlite3`, `jq`, `PRAGMA integrity_check`) → валидировать шаблон **живым Xray-бинарником** (`docker cp … && ./xray-linux-amd64 run -test -c …` → `Configuration OK.`) → заливать **готовый файл** одной командой `cp` + `chown 950:root`. **Не гонять SQL по SSH** — вложенные кавычки в `ssh '… sh -c \"…\"'` ломаются (`unrecognized token: ""PRAGMA"`, `no such column: ""`).
|
||
|
||
> ⚠️ **Панель на `/login` отдаёт 403** — это не поломка и не отсутствие доступа, просто другой путь у API. Логин панели — `vpn-admin`, пароль в БД лежит **bcrypt-хэшем** (`$2a$10$JJscByJjUHJyqmp1a8LZ7egLY0g.XbIoY…`), агент его не читает. `secret` из `settings` (`RuERf2DTzPTw3CoMcVjk7tGXKCQOk0Z4`) для логина **не подходит** (403), API-путь даёт 404 без `webBasePath`.
|
||
|
||
> 📌 **Как генерируется `config.json`:** 3x-ui собирает `/app/bin/config.json` из БД. **Outbound'ы и routing берутся из `xrayTemplateConfig`** (таблица `settings` — правится целиком и **реально применяется**), **а список клиентов — из внутреннего состояния 3x-ui** (не из `inbounds.settings` и не из таблицы `clients` при внешней правке).
|
||
>
|
||
> **Точка правки Xray-конфига:** таблица `settings` → ключ **`xrayTemplateConfig`** в `/etc/x-ui/x-ui.db`. **⚠️ `/app/bin/config.json` — генерируемый, не править (перезапишется).** `sqlite3` внутри контейнера отсутствует — работать хостовым бинарём или `alpine`-контейнером.
|
||
|
||
**Статус (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/`.
|
||
|
||
**Sub-канал (проверено 2026-09-15):**
|
||
|
||
| Клиент | `subId` | sub-ссылка | Egress |
|
||
|---|---|---|---|
|
||
| `user1` | `68c5cy5n5ui138yh` | `https://vpn-panel.mallexxx.duckdns.org/sub/68c5cy5n5ui138yh` | TrueNAS `90.189.160.148` |
|
||
| `kraken-user` | `f43074a029dc656e` | `https://vpn-panel.mallexxx.duckdns.org/sub/f43074a029dc656e` | Kraken `92.62.70.41` |
|
||
| `vless-space` | `24df9391356b48ff` | `https://vpn-panel.mallexxx.duckdns.org/sub/24df9391356b48ff` | ✅ **СОЗДАН 2026-09-15**, egress через подписку `profilegrid.net` (**28 серверов `sub1-*`**, `space-balancer` **leastLoad** + `burstObservatory`) |
|
||
|
||
- Sub-сервер отдаёт **base64-список** `vless://…` (проверено: HTTP 200, `text/plain`). Пример тела: `vless://ce320965-…@vpn.mallexxx.duckdns.org:443?encryption=none&host=vpn.mallexxx.duckdns.org&path=%2Fvless&security=tls&type=ws#vless-ws-user1`.
|
||
- **`/sub/<subId>` отдаётся БЕЗ авторизации** — любой, кто знает `subId`, получает рабочий ключ. Открытый вопрос безопасности.
|
||
- **Авто-обновление подписки на КЛИЕНТЕ — функция GUI-клиента** (Happ / v2rayN / NekoBox / sing-box: «Add subscription» + auto-update interval). Xray в docker (и `vless-proxy`, и HA-аддон) подписки **не умеет** — там только статический `config.json`; «auto» реализуется внешним cron-скриптом, который тянет `/sub/<subId>` → генерит `config.json` → рестартит контейнер.
|
||
- **⚠️ Поправка (2026-09-15): это НЕ значит, что у сервера нет авто-обновления.** Разные механизмы, не путать:
|
||
| Где | Что тянет | Авто-обновление |
|
||
|---|---|---|
|
||
| GUI-клиент (телефон/ноут) | `/sub/<subId>` **с `xray-admin`** | да, интервал в клиенте |
|
||
| `xray-admin` (СЕРВЕР) | внешнюю подписку `profilegrid.net` | ✅ **ДА — штатная `outbound_subscriptions`**, `tag_prefix=sub1-`, `update_interval=600` |
|
||
| `vless-proxy` (клиент-контейнер) | — | ❌ нет, только cron-скрипт |
|
||
**Как работает серверное авто (штатный путь 3x-ui):** запись в `Xray → Outbound Subscriptions` → панель сама раз в 600 с парсит подписку и создаёт outbound'ы `sub1-01…sub1-28` → `space-balancer` (`selector: ["sub1-"]`, `leastLoad`) подхватывает их **по префиксу**, т.к. балансировщик пересобирается из селектора, а не из списка. Новые серверы в подписке появляются сами, руками ничего не вбивать. Для `leastLoad` обязателен `burstObservatory.subjectSelector: ["sub1-"]` (тот же префикс!).
|
||
- Панель: логин **`vpn-admin`**, пароль — bcrypt-хэш в таблице `users` (`$2a$10$JJscByJjUHJyqmp1a8LZ7egLY0g.XbIoY…`), **агенту недоступен**. `/login` с `admin/admin` → 403.
|
||
|
||
### 🔴 ПИТФОЛЛ (критичный): 3x-ui НЕЛЬЗЯ править через SQLite снаружи
|
||
|
||
Проверено четырьмя подходами 2026-09-15, все провалились (подробно — [[personal/tech/xray-outbound-subscription-3xui]]):
|
||
|
||
| Можно через SQL | Нельзя через SQL |
|
||
|---|---|
|
||
| `settings.xrayTemplateConfig` — outbound'ы, `routing.rules`, `routing.balancers`, `observatory` ✅ (13 outbound'ов применились) | **Клиенты инбаунда** — `inbounds.settings`, таблица `clients` ❌ |
|
||
|
||
**Почему:** 3x-ui держит БД открытой и пишет в `-wal`; при рестарте список клиентов берёт **из своей внутренней памяти**, а не из файла. Правки в `clients`/`inbounds.settings` молча игнорируются, `config.json` перегенерируется в урезанном виде (2978 б вместо 11 990).
|
||
|
||
> **Признак невключившейся правки:** `ls -la /app/bin/config.json /etc/x-ui/x-ui.db` — если БД показывает дату **раньше** правки, 3x-ui её не перечитал.
|
||
> **Правильный путь:** клиенты — только через панель (`/panel/api/inbounds/update/:id`) или API-токен (Settings → API Tokens). `kraken-user` в 2026-09-02 добавлялся именно так.
|
||
|
||
> ⚠️ **ПИТФОЛЛ bind-mount:** folder `/mnt/RED_2TB/docker/xray-admin` смонтирована в контейнер как `/etc/x-ui`. Любой `rm`/`mv` внутри контейнера по этому пути **удаляет файл на хосте**. Так был утрачен `docker-compose.yml` 2026-09-01 (`docker exec xray-admin rm -f /etc/x-ui/docker-compose.yml`). Не чистить этот каталог изнутри контейнера.
|
||
|
||
> ⚠️ База `x-ui.db` была **уже настроена** под эту Caddy-интеграцию (inbound vless-ws:10095, subDomain vpn-panel), поэтому панель заработала «из коробки». Бэкап базы/Caddyfile до изменений: `/mnt/RED_2TB/docker/backups/reverse-xray-3xui-20260901-113625/`. Бэкап перед попыткой `vless-space`: `/mnt/RED_2TB/docker/backups/xray-admin-before-vless-space-20260915-012057/`.
|
||
|
||
### `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/how-to/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/how-to/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/how-to/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/how-to/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)
|