[2026-09-02 12:14:08] taiga-vault: merge conflict — committed markers

This commit is contained in:
Taiga
2026-09-02 12:14:08 +00:00
38 changed files with 4172 additions and 51 deletions
+85 -1
View File
@@ -1,7 +1,7 @@
---
title: Arr Stack — Taiga
created: '2026-05-23'
updated: '2026-05-23'
updated: '2026-09-02'
type: tech
namespace: family
tags: [arr, taiga, infra, media, pitfalls]
@@ -13,6 +13,22 @@ related:
Secondary arr stack on Taiga (TrueNAS), added 2026-05-20.
> **STATE 2026-09-02 (end-of-session):** Стек **ПОДНЯТ И РАБОТАЕТ** ✅. `docker compose up -d` в `/mnt/RED_2TB/docker/arr` создал и запустил `prowlarr`, `radarr`, `sonarr`, `jellyfin` (все в проекте `arr`, процессы под **uid 950** — PUID/PGID=950 применён). Сеть `media_net` воссоздана (`docker network create media_net`), transmission подключён к `media_net`. **Персистентность сетей:** в `docker/transmission/docker-compose.yml` добавлена networks секция `media_net` + `transmission_default` (external) — transmission сам находится в обеих сетях при любом пересоздании.
>
> **⚠️ ПЛЕЙБЕК РАБОТАЕТ, но НЕ ПЛАВНО на high-bitrate (диагноз 2026-09-02, ОБНОВЛЁН конец сессии):** после успешного фикса `storage` root traverse jellyfin проигрывает, НО на ТВ «Книга джунглей» тормозит и грузится кусками. **ЭТО НЕ ТРАНСКОДИНГ** (проверено: ffmpeg-процессов нет, transcode dir пуст, h264 720p идёт direct play нативно). **НЕ ап-линия TrueNAS** — замер с самого NAS опроверг раннюю гипотезу (см. ниже): линия TrueNAS даёт ~**184 Мбит/с down / ~117 Мбит/с up** (Cloudflare-замер с NAS), т.е. НЕ зажата на ~30 Мбит. **Настоящая причина — per-TCP-flow / BDP-ограничение при высоком RTT** между двумя домами: single SCP = ~28 Мбит/с, но **4 параллельных потока = ~51 Мбит/с** (агрегат РАСТЁТ с параллельностью → это ограничение конгeст-окна одного TCP, а НЕ жёсткий лимит линии/транзита). RTT ~104 мс, ~50 мс теряются на **одном физическом межоператорском прыжке** (мой провайдер TTK 3–6 мс → хоп `194.186.168.65` до 54 мс). Пер-хоп loss-анализ: грань моего ISP чиста (0%, 3 мс), дальние хопы дают спорадические LOSS-кластеры (ICMP-деприоритизация, НЕ устойчивые потери), re-route 104 мс **полностью не уберёт** (это география/пиринг, не дефектная петля). Мак-download НЕ виноват (CDN ~78 Мбит/с ✅). Файл 720p BR 7.1 GB (средний ~12 Мбит/с, пики >20) в пределах одного TCP-потока ~28–51 Мбит с малым запасом + 104 мс рвёт HLS-буфер → динамичные сцены подтормаживают. **Jellyfin НЕ умеет мультистримить один плейбек** (последовательный HLS на одном TCP; штатной настройки «в N потоков» нет). **Реальные пути:** (в 1) if TrueNAS в одном здании/роутере — дать локальный маршрут к `192.168.2.197` (убьёт 104 мс, LAN-скорость); (2) поднять ап-линию TrueNAS ТОЛЬКО если она реально мала — но замер 117 Мбит up говорит, что скорее нужен не тариф, а (3) снижение эффективной латентности/битрейт-запаса: ограничить jellyfin-транскод < ~20 Мбит ИЛИ прокси, тянущий файл с NAS в 4+ TCP-потоков (подтянет агрегат к 51+), ИЛИ WireGuard-туннель через VPS (меньше jitter/пер-потоковой деградации; минус не убирает 104 мс). Жирный отказ от варианта (б) «поднять ап-линию» как первичного — он основывался на ОШИБОЧНОМ замере 28 Мбит от Мака как потолка TrueNAS. Полный пересмотренный разбор: секция «Плейбек по сети → …» ниже.
>
> **✅ Два пост-запуска блокатора — ОБА РЕШЕНЫ (2026-09-02 конец):**
> 1. **Jellyfin не проигрывал (FFmpeg 243)** — переход решён двумя фиксами: (а) `chown -R 950:950 /mnt/RED_2TB/docker/arr/jellyfin` (конфиг вглубь был 911:911) открыл UI; (б) главный скрытый корень — корень `/mnt/RED_2TB/storage` остался `921:921`, ACL `everyone@ EXECUTE=False` → uid 950 не мог traverse в `/storage/Movies/...`. Фикс (root): `chown 950:950 /mnt/RED_2TB/storage && chmod 750 /mnt/RED_2TB/storage`. После этого jellyfin проигрывает. Транскодинг откл.: Dashboard→Playback→убрать «Allow …transcoding».
> 2. **Transmission 255 торрентов "no data found"** — downloadDir УЖЕ корректно указывал на `/storage/Movies`, файлы были и читались под 950; ошибка была закеширована от старта при блокированном traverse. Фикс (НЕ root): `docker restart transmission` → **254/255 чисты** сразу. Остался торрент #1 — Verify в UI.
>
> **Почему стек изначально не запускался — медиа-права были сломаны** (тот же restore-инцидент uid 921/0000): `/mnt/RED_2TB/storage/{Movies,Cartoons,Downloads,Music,series,shared}` были `d---------`/`drwx------`, owner `transmission` (uid 921). radarr/sonarr монтируют `/storage` (rw), jellyfin `:ro` — со сломанными правами не прочитали бы библиотеку. ✅ **Права медиа ИСПРАВЛЕНЫ** (2026-09-02) до `950:950 drwxrwx---`; контейнеры arr/jellyfin затем подняты и запущены. Полный контекст и команды: `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`.
> **Docker-image facts (2026-09-02):** All 5 media images **loaded locally** on TrueNAS (`docker images`): `lscr.io/linuxserver/{radarr,sonarr,jellyfin,transmission,prowlarr}:latest`. All containers now exist and run under **uid 950**. Was: transmission container existed (now running as uid 950); jellyfin/radarr/sonarr/prowlarr containers were NOT yet created — now they are (PUID/PGID=950).
> **Transmission originally ran as ROOT** (not 911/950): its compose had no `PUID`/`PGID`, so linuxserver `/init` (s6-overlay) left it root. ✅ **Fixed 2026-09-02:** `PUID=950 PGID=950` added and container force-recreated → now daemon under uid 950. It mounts `storage` → `/mnt/storage`, download-dir = `/mnt/storage/Downloads`.
> **Fix direction (approved Variant A):** set `PUID=950 PGID=950` on transmission + all arr/jellyfin compose services so every service shares uid `950` and mutually reads files; then recursively fix perms in depth. Plan + commands: `2026-09-02-restore-privilege-scope.md` §5.
>
> **PROGRESS 2026-09-02 (updated end-of-session):** Both compose files edited for PUID/PGID=950 (transmission at `/mnt/RED_2TB/docker/transmission/docker-compose.yml`, arr at `/mnt/RED_2TB/docker/arr/docker-compose.yml` incl. all 4 services). **transmission container force-recreated** from its proper folder (`cd /mnt/RED_2TB/docker/transmission && docker compose up -d --force-recreate`) and now runs its daemon as **uid 950** (was root) — env `PUID=950 PGID=950` confirmed, process under `abc`/950. Media perms in depth recursively fixed to `950:950 drwxrwx---` on all top storage folders (incl. git/nas 2nd root pass). **Git-sync on Mac now RESOLVED** — the broken NFS4 `DENY READ_DATA` ACL on ~1946 loose git objects in `obsidian-vault.git` was stripped via full **dacl replacement** (not stripacl), so `git push` from Mac works again (push `a2c7279..2b6c181`, ahead=0 behind=0). **Arr stack is UP (2026-09-02 end):** `cd /mnt/RED_2TB/docker/arr && docker compose up -d` created/started prowlarr/radarr/sonarr/jellyfin. All daemons under **uid 950**. jellyfin reads `/storage/Movies`; radarr↔transmission via `media_net` (`transmission:9091`) OK; caddy resolves transmission via `transmission_default` (Web UI). UI ports: prowlarr 9696, radarr 7878, sonarr 8989, jellyfin 8096, transmission 9091. NOTE: radarr/sonarr/jellyfin mount `/mnt/RED_2TB/storage` as `/storage` (NOT `/media` like Kraken) — radarr root-folder on Taiga differs.
## Notes from Setup (2026-05-20)
- Config and pitfalls recorded during initial Taiga arr stack deployment
@@ -29,3 +45,71 @@ Secondary arr stack on Taiga (TrueNAS), added 2026-05-20.
(Details were referenced but not captured. Update this page after next
Taiga arr maintenance session.)
## Плейбек по сети → per-TCP-flow/BDP-ограничение при хай-РТТ (диагноз 2026-09-02, ПЕРЕСМОТРЕН конец сессии)
**Симптом:** jellyfin на TrueNAS работает, файлы проигрываются, но на ТВ high-bitrate (720p BluRay и выше) *тормозят / грузятся кусками*, потом подтормаживают на динамике.
**Вердикт — НЕ транскодинг и НЕ ап-линия TrueNAS.** Live-проверка во время плейбека через `docker exec jellyfin sh -c 'ps ... | grep ffmpeg'` и `ls /config/cache/transcodes/`:
- нет ни одного дочернего ffmpeg, transcode dir пуст;
- jellyfin-процесс `ps` — это сам сервер, не транс-ребёнок.
- Файл `The.Jungle.Book.1967.720p.BluRay.5xRus.Eng.HDCLUB.mkv` — h264 **High@L4.1, 1256×720** → приложение ТВ (Jellyfin app) тянет нативно (direct play), транскодинг не нужен.
- Lог показывает, что jellyfin даже при direct-play может ремуксовать в **HLS-сегменты по 6 сек** (`-codec:v:0 copy ... -f hls` — копия, не перекодирование). «Грузка кусками» = HLS-сегменты добираются по сети одним TCP-потоком.
**Сетевая топология (два дома, доступ только через внешку):**
| | Сеть | Шлюз | Внешний IP | Провайдер |
|---|---|---|---|---|
| Мак / ТВ | `192.168.1.57` | `192.168.1.1` | динамика | ТТК (92.62.x / 185.20.x) |
| TrueNAS | `192.168.2.197` | `192.168.2.2` | `90.189.160.148` | Ростелеком (217.107.x) |
TrueNAS **физически/логически НЕ в локальной сети Мак/ТВ**. ТВ→Jellyfin идёт целиком по интернету между двумя домами через межоператорский транзит.
**Замеры (воспроизводимы) — САМОЕ ВАЖНОЕ: замер с самого NAS, а не от Мака.**
> Ранняя гипотеза «~28 Мбит = ап-линия TrueNAS ~30 Мбит» была ОШИБОЧНОЙ: 28 Мбит — это потолок ОДНОГО TCP-потока от Мака по пути с 104мс RTT, а НЕ лимит линии TrueNAS. Проверено замером С TrueNAS до Cloudflare:
```bash
# На самом TrueNAS — интернет-линия НЕ зажата:
ssh truenas_admin@mallexxx.duckdns.org \
'curl -o /dev/null -s -w "DOWN %{speed_download} B/s\n" "https://speed.cloudflare.com/__down?bytes=50000000"'
# DOWN ~23 MB/s ≈ 184 Мбит/с
ssh truenas_admin@mallexxx.duckdns.org \
'truncate -s 30M /tmp/up.bin && curl -o /dev/null -s -w "UP %{speed_upload} B/s\n" -X POST "https://speed.cloudflare.com/__up" --data-binary @/tmp/up.bin; rm -f /tmp/up.bin'
# UP ~14.7 MB/s ≈ 117 Мбит/с
# ovh/tele2 speedtest ХОСТЫ ЗАБЛОКИРОВАНЫ из RU (curl 000/timeout) — юзать Cloudflare __down/__up.
```
**Где реальная пропускная просадка — per-TCP-flow/BDP при высоком RTT** (не жёсткий лимит). Ключевой тест — агрегат растёт с параллельностью:
```bash
# 1 поток: ~28 Мбит/с
scp -q truenas_admin@mallexxx.duckdns.org:/tmp/dis.bin /tmp/dis.bin
# 4 параллельных потока: ~51 Мбит/с ← агрегат РАСТЁТ → BDP-штраф одного TCP при 104мс, не лимит линии/транзита
for f in a b c d; do scp -q truenas_admin@mallexxx.duckdns.org:/tmp/$f.bin /tmp/par_$f.bin & done; wait
```
(8-потоковый тест не дозамерен — апрув на запуск истёк; экстраполированное число НЕ фигурирует.)
**Латентность и loss по хопам (per-hop):**
```bash
ping -c 5 mallexxx.duckdns.org # ~104 мс avg
traceroute -m 10 -n 90.189.160.148
# х1-7 мой провайдер: 3–6 мс
# х8 194.186.168.65 → прыжок ~54 мс (переход ТТК→Ростелеком-регион)
# per-hop loss probe (через отдельные ping каждые ~0.25с к 92.62.74.1 / 194.186.x / 217.107.x / 8.8.8.8):
# моя ISP-грань 92.62.74.1: ~3 мс, 0% loss (61/61) ← сегмент чистый
# дальние хопы (194.186.x,8.8.8.8): спорадич. LOSS-кластерами синхронно → ICMP-деприоритизация, НЕ устойчивые потери данных
# mtr на macOS по умолчанию нет — ставить tofu (brew install mtr). 8.8.8.8 тоже ~53мс → ВСЕ дальние сети идут через тот же 50мс переход.
```
**Вывод (пересмотренный):** ограничитель = **per-TCP-flow / BDP-штраф за 104мс RTT**, а не ап-линия TrueNAS (117 Мбит up — отдаёт, но один поток из-за латентности получает лишь ~28–51). Файл 7.1GB/78 мин → средний ~12 Мбит/с, пики >20 — впритык к achievable single-flow ~2851 с малым запасом; 104мс рвёт HLS-буфер → стоп-кары. Re-route 104мс полностью НЕ уберёт (пиринг/география, но у Мак/ТВ-все дальние сети идут через тот же 50мс переход — намек, что частичный выигрыш смены исхода возможен, но не гарантирован).
**Что реально чинит (по убыванию надёжности):**
1. **Если TrueNAS в одном здании/роутере** → дать ТВ/Маку локальный маршрут к `192.168.2.197`, не через внешку `90.189.160.148` — убьёт 104мс, станет LAN. Топология в `truenas-infrastructure.md` (Доступ) говорит про разные подсети — обязательно сверить, один ли это физический роутер/здание (вопрос открыт).
2. **Jellyfin НЕ умеет мультистримить один плейбек** (последовательный HLS на одном TCP; штатной настройки «в N потоков» нет). Параллельность можно применить только на уровне доставки файла, НЕ внутри jellyfin-потока:
- прокси-«качель»: локально отдаёт клиенту один поток, а файл тянет с NAS в 4+ TCP (aria2/hget) → подтянет агрегат к ~51+;
- **WireGuard-туннель дом↔NAS через VPS** (`91.207.28.205`, см. `truenas-remote-access-reverse-proxy.md`) — меньше jitter/пер-потоковой деградации, но 104мс физику не уберёт. **⚠ XRAY-ТУННЕЛЬ УЖЕ ИЗМЕРЕН и НЕ ПОМОГАЕТ** (2026-09-02): оба egress-режима локального `xray-test-client` (`kraken-user` reverse → Kraken ~45 Мбит; `user1` direct/REALITY → TrueNAS ~37 Мбит) дают ~35–45 Мбит с нестабильностью — тот же уровень, НЕ кратно выше single-flow прямого пути (28–51 Мбит). Детали и способ переключения клиента: `personal/tech/xray-reverse-tunnel-kraken-truenas.md` § «СОСТОЯНИЕ КЛИЕНТА/Замеры».
3. **Прагматичный фикс под ТВ-стрим сейчас:** ограничить jellyfin-транскод битрейтом < ~20 Мбит (заведомо ниже single-flow achievable ~28), чтобы один HLS-поток укладывался без дожевания. Включается сразу, без новой инфраструктуры.
4. Поднять ап-линию TrueNAS — **только если** замер из п.º (117 Мбит up) реально маловат для нужного контента; как первичный вариант отвергнут.
> **Перекрёстно:** это исправление ранней ошибочной записи «потолок ~28 = ап-линия TrueNAS» (см. history этого файла до 2026-09-02). Если будущая сессия увидит противоречие — истина здесь: NAS-линк 184/117 Мбит, проблема per-flow/BDP при высоком RTT.
+53
View File
@@ -85,6 +85,59 @@ docker compose up -d
| `hermes/config/` | `/opt/data` | `HERMES_HOME` — config, sessions, skills, memory |
| `/home/kraken/obsidian` | `/vault` | Obsidian vault read/write access |
## SSH из контейнера → хост (диагностика и фиксы)
> Перенесено из удалённого скилла `kraken-omv-maintenance` / `kraken-docker-ssh`. Актуальные пути и фиксы для случая, когда `ssh kraken-host` изнутри контейнера `hermes-kraken` не работает.
**Архитектура**
```
Container (hermes-kraken)
uid=10000 (dropped from root by entrypoint)
HOME=/opt/data
~/.ssh/config = /opt/data/.ssh/config (bind mount from host)
/etc/ssh/ssh_config — bind mount (полный /etc/ssh/)
Host (Kraken RPi5)
User kraken (uid=1000) owns /home/kraken/.ssh/
/home/kraken/.ssh/id_ed25519 — закрытый ключ (обязательно 600)
/home/kraken/.ssh/authorized_keys — должен содержать публичный ключ
```
**Fixed points (НЕ менять)**
1. В compose **не задавать** `user:`, `entrypoint:`, `HERMES_UID/GID` — entrypoint сам сбрасывает uid (image defaults).
2. Публичный ключ на хост один раз: `ssh-copy-id kraken@<host>`.
3. Закрытый ключ на хосте **обязан быть 600**: `ssh kraken@<host> "chmod 600 /home/kraken/.ssh/id_ed25519"` — OpenSSH 10.x (Bookworm) отвергает 644.
4. В `/etc/passwd` контейнера должен быть `kraken:x:1000` — не выставлять `user:` в compose.
5. SSH config обязан лежать в `$HOME/.ssh/config` (`$HOME=/opt/data``/opt/data/.ssh/config`).
**Диагностика по порядку**
```bash
ssh kraken@<host> "echo OK && hostname" # доступен ли хост
ssh kraken@<host> "sudo docker ps --filter name=hermes-kraken --format '{{.Names}} {{.Status}}'"
# изнутри контейнера на хост (loopback алиас kraken-host)
ssh kraken@<host> "sudo docker exec hermes-kraken ssh -o ConnectTimeout=5 kraken-host 'echo HELLO'"
# verbose — какие конфиги читает SSH
ssh kraken@<host> "sudo docker exec hermes-kraken ssh -v kraken-host 'echo HELLO' 2>&1 | grep -E 'config|debug1.*/ssh|Host|connect|Permission|authenticate|bad|owner' | head -15"
ssh kraken@<host> "sudo docker exec hermes-kraken getent passwd 1000" # uid 1000 в passwd?
ssh kraken@<host> "sudo docker exec hermes-kraken ls -la /opt/data/.ssh/id_ed25519"
ssh kraken@<host> "sudo docker exec hermes-kraken cat /opt/data/.ssh/config"
ssh kraken@<host> "sudo docker exec hermes-kraken sh -c 'echo HOME=\$HOME; ls -la \"\$HOME/.ssh/config\"'"
```
**Pitfalls**
- Не менять `user:` в compose — entrypoint должен стартовать как root, чтобы сделать chown.
- Не chown'ить `/opt/data` на `1000:1000` — entrypoint делает `chown -R hermes:hermes` (uid 10000).
- Не ставить 644 на закрытый ключ.
- НЕ использовать `Include ~/.ssh/config` в системном `/etc/ssh/ssh_config` — OpenSSH не резолвит `~` в системных Include.
- Если `$HOME=/opt/data`, а конфиг живёт в `/opt/data/home/.ssh/` — SSH его не прочитает (путь не совпадает).
- Может быть несколько пар ключей: bind mount приносит хост-ключ, а агент может иметь свой в `/opt/data/home/.ssh/`.
- passwd сбрасывается при пересоздании контейнера.
- Полный mount `/etc/ssh/` перезаписывает и host keys тоже.
## Notes
- `network_mode: host` — port 8642 is directly on the Kraken host, no port mapping needed
+4
View File
@@ -194,6 +194,10 @@ ZONT relays
[8: Конвектор котельная - н.п.]
```
> **ℹ️ Про «виртуальные sensor 101/102/103» и «недоступные датчики в ZONT»:**
> 101/102/103 — это **виртуальные Modbus-slaves**, которые контейнер `modbus-bridge` на TrueNAS подставляет на шине `ttyZONT`: реальные 485-датчики **Гостиная=1, Детская=2, Спальня=3** сниффятся и их температуры выдаются ZONT'у как датчики 101/102/103 (регистр 100). ZONT (Modbus master) опрашивает их как внешние датчики.
> Если `modbus-bridge` не запущен/не слушает `ttyZONT` → ZONT показывает эти датчики **«недоступные»**. Известная первопричина — гонка docker/udev после рестарта TrueNAS. Подробности и план защиты: `[[family/how-to/truenas-infrastructure.md#Проблема-modbus-bridge/mbusd-после-рестарта-TrueNAS-гонка-с-udev]]` и `[[family/plans/zont-modbus-bridge-udev-race-protection]]`. (Заметка обновлена 2026-08-25: добавлено пояснение про 101/102/103, ZONT relays не менялись.)
## Карта регистров контроллера вентиляторов
```
+18 -17
View File
@@ -1,15 +1,19 @@
# Kraken — Внешний доступ
> Обновлено: 2026-06-24
> Обновлено: 2026-09-01
> Updated: 2026-09-01 23:00 — диск/докер кракена восстановились после перезагрузки.
## Как зайти
Везде `ssh kraken`. Резолвится через `~/.ssh/config` на Eagle:
- **Дома** — напрямую по LAN (`192.168.1.15`)
- **Снаружи** — через WireGuard (`10.99.1.2`, VPN поднимается автоматически `wg-auto.sh`)
- **Снаружи** — ⚠️ через WireGuard (`10.99.1.2`) **БОЛЬШЕ НЕ РАБОТАЕТ**: VPS-узло (10.99.0.1/10.99.1.1) qentra.top **удалили 2026-09-01**. Альтернатива внешнего доступа обсуждается через Xray reverse (см. [[tech/xray-reverse-tunnel-kraken-truenas]]).
WireGuard split-tunnel: Eagle (10.99.0.2) ↔ VPS ↔ Kraken (10.99.1.2). Подробнее: [[wireguard-vpn]].
> ⚠️ **Kraken-диск был нестабилен 2026-09-01**: USB-диск TOSHIBA в цикле enumeration (`device descriptor read/64 error -110`, `device not accepting address error -62`, `[sda] Read Capacity(10) failed` → `0 B`), Kraken перезагружался (`System is booting up / pam_nologin`). **После повторной перезагрузки диск зарегистрировался**: `sda` 1.8T, `sda1` смонтирован в `/srv/dev-disk-by-uuid-6194539b-...`. Docker стал `active`.
> ⚠️ **Kraken Docker на 2026-09-01:** Server 29.4.3, Docker Root Dir `/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker-data`. **30 образов сохранены, но 0 контейнеров** (all прежние контейнеры — jellyfin/transmission/radarr/hermes-kraken и т.д. — потеряны и НЕ пересозданы после сбоя; data-root на HDD был в цикле enumeration). При необходимости — пересоздать из образов.
## Portainer (локально)
@@ -26,26 +30,23 @@ EP=3 # endpoint ID на Кракене = 3, не 1!
`http://kraken:8642/v1/chat/completions` — OpenAI-compatible endpoint.
## Docker контейнеры (2026-06-24)
## Reverse Xray bridge (развёрнут 2026-09-01)
- Контейнер **`xray-reverse-bridge`** в `/home/kraken/xray-reverse/` (compose + `config.json`, образ `teddysun/xray:latest`, Xray 26.7.28 ARM64).
- Outbound VLESS+REALITY TCP → `mallexxx.duckdns.org:12346` (TrueNAS через OpenWrt DNAT), reverse tag `reverse-in`, egress freedom.
-**End-to-end payload НЕ работает** (bridge принимает reverse-канал, но данные от portal до bridge не доходят). Детали: [[tech/xray-reverse-tunnel-kraken-truenas]].
## Docker контейнеры (исторически было 2026-06-24; на 2026-09-01 НЕ восстановлены)
| Имя | Заметки |
|-----|---------|
| flaresolverr | |
| hermes-kraken | |
| homeassistant | |
| jellyfin | |
| portainer | |
| prowlarr | |
| radarr | |
| rclone | |
| sonarr | |
| transmission | |
| cloudflared | |
| watchtower | |
| xray-reverse-bridge | развёрнут 2026-09-01 (единственный активный) |
| flaresolverr / hermes-kraken / homeassistant / jellyfin / portainer / prowlarr / radarr / rclone / sonarr / transmission / cloudflared / watchtower | образы есть, контейнеры потеряны — пересоздать при необходимости |
## Связанные заметки
- [[kraken-network]] — SSH, WG топология
- [[wireguard-vpn]] — полное описание WG
- [[wireguard-vpn]] — полное описание WG (⚠️ VPS-звено мёртво на 2026-09-01)
- [[kraken-portainer-access]]
- [[openmediavault-rpi5]]
+15 -2
View File
@@ -1,7 +1,7 @@
---
title: Kraken Network & Infra
created: '2026-05-23'
updated: '2026-05-23'
updated: '2026-09-02'
type: tech
namespace: personal
tags: [infra, kraken, ssh, wireguard, network]
@@ -17,7 +17,20 @@ related:
ssh kraken
```
IP: `192.168.1.15` (wlan0, primary). SSH alias `kraken` resolves via `~/.ssh/config`.
SSH alias `kraken` resolves via `~/.ssh/config`.
## Актуальная сеть (проверено 2026-09-02)
> Оба интерфейса живы. **eth0 — активный uplink** (default route metric 100), wlan0 — fallback (metric 600).
| Интерфейс | IP | MAC | Uplink role |
|---|---|---|---|
| **eth0** (Ethernet, Gigabit RPi5 rp1-gem/macb) | `192.168.1.14/24` (DHCP) | `2c:cf:67:64:03:f3` | **primary** — default via `192.168.1.1`, metric 100 |
| **wlan0** (WiFi) | `192.168.1.15/24` (DHCP) | `2c:cf:67:64:03:f4` | fallback — metric 600 |
- Ethernet link: **1000 Mbit/s full duplex** (как и ожидалось для Gigabit-порта RPi5), carrier up, стабильно.
- Router/gateway: `192.168.1.1` (`f0:79:59:77:9b:70`). eth0 MAC соответствует static lease в доке [[family/how-to/openmediavault-rpi5|openmediavault-rpi5]].
- ⚠️ Ранее эта заметка утверждала «wlan0 = .15 primary» — устарело (см. таблицу выше).
## WireGuard Topology
+1 -1
View File
@@ -34,7 +34,7 @@ mallexxx.duckdns.org:/mnt/RED_2TB/storage/git/obsidian-vault.git
| Узел | Vault путь | Scope | Скрипт | Крон |
|------|-----------|-------|--------|------|
| Eagle | `~/obsidian` | full vault | `~/scripts/sync-vault.sh` | `0 * * * *` (Hermes cron job) |
| Eagle | `~/obsidian` | full vault | `~/scripts/sync-vault.sh` | **launchd `com.sync-vault`** (5 мин; ⚠️ НЕ Hermes cron — см. `vault-git-sync.md` §Scripts) |
| Kraken | `~/obsidian` | sparse: `personal/ family/` | `~/scripts/sync-vault.sh` | `0 * * * *` (crontab) |
| Taiga | `/mnt/RED_2TB/docker/hermes/vault` | sparse: `personal/ family/` | `~/sync-vault.sh` (на хосте!) | `0 * * * *` (Hermes cron job) |
+72
View File
@@ -0,0 +1,72 @@
# RED_2TB — карта датасетов и назначений (для решения о пересоздании пула)
> Собрано: 2026-08-20 (Ель — Кит). Источник: live-данные `zfs list` + `ls` с TrueNAS (readonly-импорт).
> НАЗНАЧЕНИЕ: решить, воссоздавать ли карту датасетов как есть, или что-то поменять/добавить/убрать перед пересозданием пула RED_2TB.
> Ничего не изменялось — только сбор информации.
## Статус спасения на 2026-08-21
- **Выгрузка ЗАВЕРШЕНА УСПЕШНО** (подтверждено Alex). Данные RED_2TB (4.56T) на IronWolf — `DEST`, `/mnt/IRONWOLF`.
- **RED_2TB пул — OFFLINE** в БД TrueNAS (id=1), НЕ импортирован. `zpool export``no such pool`.
- Проверочный rsync прогон завершён (rsync не запущен).
- **РЕШЕНИЕ:** пересоздаём пул с новой топологией — ВКЛЮЧАЕМ WD2TB#2 (sdf) зеркалом к WD2TB#1 (sdc). Итог: `mirror {sdc,sdf}` + `mirror {sde,sdd}`.
- Следующий шаг: `zpool labelclear` по разделам `*2` + `zpool create` (подробно в [[truenas-sata-ports-and-zfs-pools]] → «Пересоздание пула 2026-08-21»).
## Общая сводка
- Пул: RED_2TB, 5.44T (4.61T занято), компрессия lz4, рекордсайз 128K, acltype nfsv4, atime=on, exec=on.
- Квот/резерваций НЕТ ни на одном датасете (все `none`).
- Монтинг: датасеты в `/RED_2TB/*`, служебные `.system`/`ix-apps` в `legacy`/`/.ix-apps`.
## ✅ Датасеты (воссоздавать как ZFS datasets)
| Датасет | USED | REFER | Назначение | Примечание |
|---------|------|-------|-----------|------------|
| **storage** | 3.24T | 3.24T | Общее хранилище мультимедиа и файлов | Подкаталоги: Cartoons, Downloads, Edu, Movies, Music, ada3s1, art, books, cartoons-series, documentaries(-series), git, nas(пусто), obsidian, obsidian-syncthing, photo_dedup_test, radarr, seafile, series, shared, singularity, sonarr, work. `git/` = hermes-taiga.git, obsidian-vault.git |
| **backup** | 287G | 287G | Резервные копии (личные доки, коды, VM, пароли, браузеры) | Много семейных документов (договоры, справки), Google Keep/Play, VPN, Virtual Machines, accessKeys.csv, lastpass_export.zip, коды восстановления. |
| **TimeMachine/guest** | 277G | 267G | Бэкапы macOS (Time Machine) | Родитель TimeMachine 277G/96K; дочерний `guest` несёт данные. Много снимков `aapltm-*`. |
| **Edu** | 214G | 214G | Учебные материалы | |
| **Photos** | 146G | 146G | Фотографии | |
| **old-bu** | 65.5G | 65.5G | Старый семейный архив фото/видео | Фото 2009–2010+, свадьбы, семейные события (папки вида `09-01-01 Новый 2009 год!`). |
| **ix-apps** | 24.0G | - | Системный — TrueNAS Apps (docker 23.6G, truenas_catalog 385M) | Воссоздаётся самой TrueNAS, не вручную. |
| **iocage** | 15.4G | 9.19M | Jail-ы TrueNAS | Jails: backuppc, emby, homeassistant, plex, transmission, worker + releases 11.2/12.2/12.3, images, download, templates. |
| **openbsd** | 10.2G | 4.43M | ?? неясно — refer всего 4.43M при used 10.2G | Вероятно remnants после снимка/пробного пула. Решить: нужен ли вообще. |
| **docker** | 2.98G | 2.98G | Живой docker-конфиг (текущие контейнеры) | |
| **apps** | 192K | 96K | Точка для app-конфигов | Дочерний `apps/homeassistant-config` (96K). |
| **.system/** | 568M | - | Служебное TrueNAS (configs, netdata, rrd, samba4, syslog...) | Воссоздаётся самой системой, не создавать руками. |
## ⚠️ Данные ВНЕ датасетов — лежат прямо в корне `RED_2TB` (REFER 362G)
Эти пути НЕ являются ZFS-datasets (их нет в `zfs list`) — при пересоздании пула их надо решать отдельно, иначе потеряются (или перепутаются с содержимым корневого датасета):
| Путь | Содержимое | Важность |
|------|-----------|----------|
| `/RED_2TB/system/` | SSH-туннель: `tunnel.sh`, `tunnel_key` (приватный!), `tunnel_key.pub`, `99-tty-alias.rules`. Владелец root, режим 600/644. | ⚠️ **КРИТИЧНО** — рабочий туннель TrueNAS. root-only. |
| `/RED_2TB/docker.bak/` | Бэкап конфигов docker: caddy, cups, filebrowser, ha, hermes, homeassistant, immich, inpx-web, inpxer, mbusd, modbus-bridge, mosquitto, nodered, portainer, python, rclone, ser2net | Архив/бэкап контейнеров. `hermes/` = бэкап Hermes-агента. |
| `/RED_2TB/immich-photos-upload/` | Конфиг Immich: backups, encoded-video, library, profile, thumbs, upload | Рабочий Immich (он же в docker). |
| Корневые файлы | `.DS_Store`, `._.DS_Store` (мусор mac), `dedupe_rm.sh`, `files.txt.xz` (содержимое old-bu/somo?) | dedupe_rm.sh — скрипт дедупликации, файловый список. |
## 🤔 Метки для решения
Вопросы, которые надо решить ПЕРЕД пересозданием:
1. **openbsd (10.2G/4.43M)** — судя по refer почти пуст. Что это? Удалить из map?
2. **Внутри storage/ есть `Edu`** — это ДУБЛЬ датасета `Edu`? Проверить: возможно медиа-папка Edu в storage vs отдельный датасет Edu для учебных.
3. **`nas` внутри storage пуст**.
4. **`TimeMachine`** (277G) — вернуть ли отдельным датасетом как было, с дочерним `guest`?
5. **`docker` vs `docker.bak`** — оба сохранить? `docker` = живой, `docker.bak` = архив.
6. **`immich-photos-upload`** — оставить в корне пула (вне датасета) или завести отдельный датасет?
7. **Внедатасетные каталоги** (`system`, `docker.bak`, `immich-photos-upload`) — после пересоздания они окажутся в корневом dataset RED_2TB (REFER 362G). Решить, оставить их там или разнести по датасетам.
## Ключевые решения по подходу к пересозданию (из truenas-sata-ports-and-zfs-pools.md)
- In-place починки НЕТ (битая space map, паника на rw).
- Рабочий путь: readonly-импорт → выгрузка rsync → `zpool destroy`+`create` → возврат данных rsync.
- НЕ использовать `zfs send|recv` (падает на повреждённом пуле). Только rsync.
- **РЕШЕНО (2026-08-21):** включить WD2TB#2 (sdf) зеркалом к WD2TB#1 (sdc) при пересоздании. Топология `mirror {sdc,sdf}` + `mirror {sde,sdd}` — оба зеркалированы.
- `zpool import`/`mount`/destroy/create — ТОЛЬКО под root (truenas_admin не root).
- **НИКОГДА не импортировать RED_2TB в rw** (kernel panic). Только `labelclear` + `create`.
## Ссылки
- Связанные: [[truenas-sata-ports-and-zfs-pools]] (план спасения/пересоздания), [[truenas-access]] (общие данные доступа).
+25 -5
View File
@@ -2,15 +2,35 @@
title: "🖨 Samsung — настройки"
aliases: ["Samsung CLX-2160", "Samsung TV", "samsung"]
tags: ["family", "how-to", "devices"]
updated: "2026-05-17"
updated: "2026-08-26"
---
# 🖨 Samsung — настройки
## Принтер Samsung CLX-2160 (сетевой адрес)
## Принтеры в системе (на Маке admin, macOS)
```
ipps://192.168.2.197:631/printers/Samsung_CLX-216x_Series
```
Два принтера:
- **Samsung CLX-216x** — сетевой: `ipps://192.168.2.197:631/printers/Samsung_CLX-216x_Series`. Драйвер Generic PostScript.
- **Samsung M2020 Series** (SEC84251974A6B3) — AirPrint (dnssd), дефолтный. Подключается по Wi-Fi/AirPrint.
## Состояние печати / шеринга (диагностика 2026-08-26)
Симптом: с телефона не виден принтер.
### ✅ Корень проблемы (подтверждено SSH на TrueNAS)
**Samsung CLX-216x физически подключён к TrueNAS (USB) и обслуживается docker-контейнером `cups-splix` (драйвер splix). Контейнер НЕ запущен** — образ не собран, контейнер отсутствует после пересоздания пула. Поэтому принтер не виден по сети → телефон не печатает.
- На TrueNAS нет другой службы печати: `lpstat`/`cupsd` не установлены, порт 631 закрыт.
- `192.168.2.197` — это адрес TrueNAS (не принтер); запись `ipps://192.168.2.197:631/...` = расшаренная печать TrueNAS.
- **Фикс:** пересобрать `cups-splix` и поднять — см. `[[truenas-infrastructure]]` (раздел «cups-splix — принтер») и `[[mac-print-shared-services]]`.
### Факты из CUPS на этом Маке (вторичны для этой проблемы)
- `Listen localhost:631` — служба печати CUPS слушает **только локально**, наружу не отдаёт.
- `SharePrinters` в `/etc/cups/cupsd.conf` не активен — **шеринг печати выключен** (оба принтера `Shared: No`). Шеринг на Маc актуален только для принтера, висящего на Маcе (Samsung M2020).
Подсеть: Мак в этом сеансе был на `192.168.6.x`, инфраструктура живёт на `192.168.2.x` — расхождение из-за того, что Мак был вне основной сети, а не из-за принтера.
Примечание: `sudo -n cupsctl` не работает без пароля — шеринг удалённо через SSH проверить нельзя.
## Отключение Detecting Device
+9 -3
View File
@@ -9,12 +9,16 @@ Android (Syncthing app)
│ P2P sync (QUIC/TCP :22000)
TrueNAS (syncthing контейнер)
/var/syncthing/obsidian-vault → /mnt/RED_2TB/storage/obsidian
/var/syncthing/obsidian-vault → /mnt/RED_2TB/storage/obsidian-syncthing
├── Obsidian vault (полная копия на TrueNAS)
└── Eagle (Mac) — продолжает через git, Syncthing не участвует
```
> ⚠️ **2026-09-02 уточнение:** фактический mount в compose — `/mnt/RED_2TB/storage/obsidian-syncthing` (НЕ `/storage/obsidian`). Есть две отдельные папки:
> - `/storage/obsidian` — архивная/рабочая копия vault (старый mount в доке; `.stfolder` отсутствует) — НЕ является sync target.
> - `/storage/obsidian-syncthing` — **активная sync-копия** (`.stfolder` присутствует, uid 950) — это то, что реально монтируется контейнером. По ней и идёт телефонная синхронизация. В блоке `volumes:` ниже именно она.
## Доступ
- **Web UI:** https://syncthing.mallexxx.duckdns.org
@@ -42,7 +46,7 @@ services:
- TZ=Asia/Novosibirsk
volumes:
- /mnt/RED_2TB/docker/syncthing/config:/var/syncthing/config
- /mnt/RED_2TB/storage/obsidian:/var/syncthing/obsidian-vault
- /mnt/RED_2TB/storage/obsidian-syncthing:/var/syncthing/obsidian-vault
ports:
- "22000:22000/tcp"
- "22000:22000/udp"
@@ -55,7 +59,9 @@ networks:
external: true
```
**UID 950** = `truenas_admin` — имеет `FULL_CONTROL` ACL на `/mnt/RED_2TB/storage/obsidian`.
**UID 950** = `truenas_admin` — имеет `FULL_CONTROL` ACL на `/mnt/RED_2TB/storage/obsidian-syncthing` (и на `/storage/obsidian`).
> **Питфол (после restore 2026-08-31):** после восстановления из бэкапа и syncthing-папка (`obsidian-syncthing`), и многие `/storage/*` стали `uid 921` (`transmission`) с правами 0000 → syncthing-папка уходит в `error: stat .stfolder: permission denied` → телефонная синхронизация стоит. Фикс: вернуть `950:950` + `u+rwX,g+rwX` (см. `family/documents/vault-sync/2026-08-31-syncthing-truenas-incident.md`). Эта же поломка затрагивает `git/` и медиа-папки (см. `2026-09-02-restore-privilege-scope.md`).
## Caddy
+9
View File
@@ -42,6 +42,15 @@ docker run --rm alpine sh -c 'apk add -q openssh sshpass && sshpass -p 1316261 s
**Пароль root:** `1316261`
> 💡 **Бэкап firewall OpenWrt перед любой правкой redirect-правил** (вошло в практику 2026-09-01):
> ```bash
> # с TrueNAS: сохранить весь firewall-конфиг OpenWrt в backup-папку TrueNAS
> docker run --rm alpine sh -c 'apk add -q openssh sshpass && sshpass -p 1316261 ssh -o StrictHostKeyChecking=no root@192.168.2.2 "uci show firewall"'
> # → сохранить вывод в /mnt/RED_2TB/docker/backups/openwrt-firewall-YYYYMMDD-HHMMSS.txt
> # Пример сделанного: /mnt/RED_2TB/docker/backups/openwrt-firewall-20260901-130558.txt
> ```
> Существующие redirect-правила OpenWrt → TrueNAS(192.168.2.197): MQTT 1883, SSH 22, caddy_http 80→8088, caddy_https 443→8443, HomeAssistant 8123 (disabled).
## Пул и датасеты
Пул: RED_2TB (ZFS)
+229 -16
View File
@@ -1,6 +1,36 @@
# TrueNAS — инфраструктура
> Обновлено: 2026-07-06
> Обновлено: 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` на момент старта контейнеров ещё не существуют.
> - Контейнеры с `devices: /dev/ttyZONT:...` падают на `start` с `error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory` (ExitCode 128/255, RestartCount=0).
> - `restart: unless-stopped` НЕ перезапускает такой контейнер (отказ до старта процесса).
> - Следствие: modbus-bridge не отвечает на шине → 485-датчики в ZONT отображаются **«недоступные»**.
> - Ручной фикс: `docker start modbus-bridge mbusd` (после готовности tty-симлинков).
> - Защита от рецидива (план, НЕ внедрён — ждёт OK Alex): `family/plans/zont-modbus-bridge-udev-race-protection.md` — POSTINIT init script с ожиданием симлинков + `docker start`.
> **⚠️ ДРУГОЕ (открытое):** пул `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`.
## Доступ
@@ -12,6 +42,14 @@
- ⚠️ 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 | Назначение |
@@ -91,12 +129,60 @@ TrueNAS использует **NFSv4 ACL**, а не стандартный POSIX
| mbusd | 3cky/mbusd:latest | — | Modbus |
| modbus-bridge | modbus-bridge | — | — |
| cups-splix | cups-splix | — | принтер |
| 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)**
**⚠️ НЕТ compose-файла — только конфиг (восстанавливать вручную, параметры из доки ниже):**
- **ha** — Home Assistant: `/mnt/RED_2TB/docker/ha/` (automations.yaml). Образ `ghcr.io/home-assistant/home-assistant:stable`, порт `8123`, volume `/mnt/RED_2TB/docker/ha``/config`.
- **webdav** — `/mnt/RED_2TB/docker/webdav/` (config.yml). Образ `hacdias/webdav:latest`, домен webdav.mallexxx.duckdns.org.
- **modbus-bridge** — `/mnt/RED_2TB/docker/modbus-bridge/` (config.yml + modbus_ha_bridge.py). Образ `modbus-bridge` (локальная сборка из репо `HA-ZONT-Modbus`). Volumes: config.yml → `/app/config.yml` (ro), modbus_ha_bridge.py → `/app/modbus_ha_bridge.py` (ro).
- **zigbee2mqtt** — `/mnt/RED_2TB/docker/zigbee2mqtt/` (configuration.yaml). Образ `koenkk/zigbee2mqtt:latest`, работает через mosquitto.
- **homeassistant** — в доке упомянут как отдельный контейнер (порт 8123, volume → /config); папка `docker/homeassistant/` есть, но название контейнера в таблице `homeassistant`, а папка конфига HA фактически `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) → caddy (прокси, тянет все домены) → vless-proxy (SOCKS5 для hermes).
3. **Умный дом:** mbusd (Modbus TCP:502) → modbus-bridge (через mbusd) → ha (homeassistant, нужен caddy для домена).
4. **Медиа/хранилище:** transmission (нужен caddy) → arr (radarr/sonarr/prowlarr) → inpxer (books), inpx-web, library → rclone, syncthing, filebrowser, webdav, gitea.
5. **Сервисы/свои:** hermes-taiga (нужен vless-proxy), portainer, portainer-mcp, watchtower, cups, ser2net.
6. **Проверка:** `docker ps`. HA: `docker exec homeassistant python -m homeassistant --script check_config --config /config`.
### Transmission — детали
- **Config:** `/mnt/RED_2TB/docker/transmission/` (монтируется как `/config`)
- **Config:** `/mnt/RED_2TB/docker/transmission/` (монтируется как `/config`; внутри `/config/docker-compose.yml`)
- **Данные:** `/mnt/RED_2TB/storage` (монтируется как `/mnt/storage`)
- **Download dir:** `/mnt/storage/Downloads`
- **UID/GID:** 911/911 (пользователь `transdamon`)
- **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)
@@ -115,6 +201,64 @@ TrueNAS использует **NFSv4 ACL**, а не стандартный POSIX
| truenas.mallexxx.duckdns.org | TrueNAS UI :80 |
| cam.mallexxx.duckdns.org | Камера :8090 |
| docs.mallexxx.duckdns.org | Docs :8000 |
| **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 — детали
@@ -144,24 +288,49 @@ ssh truenas_admin@mallexxx.duckdns.org "docker restart homeassistant"
ssh truenas_admin@mallexxx.duckdns.org "docker exec homeassistant python -m homeassistant --script check_config --config /config"
```
### mbusd — Modbus TCP gateway
### mbusd — Modbus RTU → TCP gateway
Мост Modbus RTU → TCP: пробрасывает серийный порт инвертора AT2 вентиляции в TCP 502.
Мост Modbus RTU → TCP: пробрасывает серийный порт в TCP 502. Используется и для вентиляции (AT2), и для ZONT-шины.
- **Image:** `3cky/mbusd`
- **Порт:** `502:502`
- **Config:** `/mnt/RED_2TB/docker/mbusd/mbusd.conf``/etc/mbusd.conf`
- **Device:** `/dev/ttyVent``/dev/ttyUSB0` (внутри контейнера)
- **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 — AT2 Modbus → MQTT
### modbus-bridge — 485-датчики + виртуальные slaves для ZONT
Кастомный Python-мост: читает регистры инвертора AT2 через mbusd и публикует в MQTT → Home Assistant.
Кастомный Python-мост (`modbus_ha_bridge.py`, репо `HA-ZONT-Modbus`), контейнер `/mnt/RED_2TB/docker/modbus-bridge/`.
- **Image:** `modbus-bridge` (локальная сборка)
- **Volumes:**
- `/mnt/RED_2TB/docker/modbus-bridge/config.yml``/app/config.yml` (ro)
- `/mnt/RED_2TB/docker/modbus-bridge/modbus_ha_bridge.py``/app/modbus_ha_bridge.py` (ro)
- **Source:** `modbus_ha_bridge.py` в репозитории `HA-ZONT-Modbus`
- **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/plans/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
@@ -310,6 +479,50 @@ git -C /mnt/RED_2TB/storage/git/obsidian-vault.git log --oneline -10
---
## Печать / 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]] — система бэкапов
@@ -0,0 +1,511 @@
# TrueNAS — инфраструктура
> Обновлено: 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` на момент старта контейнеров ещё не существуют.
> - Контейнеры с `devices: /dev/ttyZONT:...` падают на `start` с `error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory` (ExitCode 128/255, RestartCount=0).
> - `restart: unless-stopped` НЕ перезапускает такой контейнер (отказ до старта процесса).
> - Следствие: modbus-bridge не отвечает на шине → 485-датчики в ZONT отображаются **«недоступные»**.
> - Ручной фикс: `docker start modbus-bridge mbusd` (после готовности tty-симлинков).
> - Защита от рецидива (план, НЕ внедрён — ждёт OK Alex): `family/plans/zont-modbus-bridge-udev-race-protection.md` — POSTINIT init script с ожиданием симлинков + `docker start`.
> **⚠️ ДРУГОЕ (открытое):** пул `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 **не работает**
## Пользователи и группы (ключевые)
| 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 | mallexxx.duckdns.org |
| 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 | nodered.mallexxx.duckdns.org |
| mosquitto | eclipse-mosquitto:latest | — | — |
| 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 |
| nodered | node-red:latest | 1880 | nodered.mallexxx.duckdns.org |
| zigbee2mqtt | koenkk/zigbee2mqtt:latest | — | — |
| mbusd | 3cky/mbusd:latest | — | Modbus |
| modbus-bridge | modbus-bridge | — | — |
| cups-splix | cups-splix | — | принтер |
| 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)**
**⚠️ НЕТ compose-файла — только конфиг (восстанавливать вручную, параметры из доки ниже):**
- **ha** — Home Assistant: `/mnt/RED_2TB/docker/ha/` (automations.yaml). Образ `ghcr.io/home-assistant/home-assistant:stable`, порт `8123`, volume `/mnt/RED_2TB/docker/ha` → `/config`.
- **webdav** — `/mnt/RED_2TB/docker/webdav/` (config.yml). Образ `hacdias/webdav:latest`, домен webdav.mallexxx.duckdns.org.
- **modbus-bridge** — `/mnt/RED_2TB/docker/modbus-bridge/` (config.yml + modbus_ha_bridge.py). Образ `modbus-bridge` (локальная сборка из репо `HA-ZONT-Modbus`). Volumes: config.yml → `/app/config.yml` (ro), modbus_ha_bridge.py → `/app/modbus_ha_bridge.py` (ro).
- **zigbee2mqtt** — `/mnt/RED_2TB/docker/zigbee2mqtt/` (configuration.yaml). Образ `koenkk/zigbee2mqtt:latest`, работает через mosquitto.
- **homeassistant** — в доке упомянут как отдельный контейнер (порт 8123, volume → /config); папка `docker/homeassistant/` есть, но название контейнера в таблице `homeassistant`, а папка конфига HA фактически `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) → caddy (прокси, тянет все домены) → vless-proxy (SOCKS5 для hermes).
3. **Умный дом:** mbusd (Modbus TCP:502) → modbus-bridge (через mbusd) → ha (homeassistant, нужен caddy для домена).
4. **Медиа/хранилище:** transmission (нужен caddy) → arr (radarr/sonarr/prowlarr) → inpxer (books), inpx-web, library → rclone, syncthing, filebrowser, webdav, gitea.
5. **Сервисы/свои:** hermes-taiga (нужен vless-proxy), portainer, portainer-mcp, watchtower, cups, ser2net.
6. **Проверка:** `docker ps`. HA: `docker exec homeassistant python -m homeassistant --script check_config --config /config`.
### 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 | Home Assistant :8123 |
| transmission.mallexxx.duckdns.org | Transmission :9091 |
| immich.mallexxx.duckdns.org | Immich :2283 |
| nodered.mallexxx.duckdns.org | Node-RED :1880 |
| webdav.mallexxx.duckdns.org | WebDAV |
| books.mallexxx.duckdns.org | Inpxer :18080 🔒 basicauth (user: books-admin) |
| library.mallexxx.duckdns.org | library-app :8080 🔒 basicauth (user: books-admin) |
| portainer.mallexxx.duckdns.org | Portainer :9000 |
| truenas.mallexxx.duckdns.org | TrueNAS UI :80 |
| cam.mallexxx.duckdns.org | Камера :8090 |
| docs.mallexxx.duckdns.org | Docs :8000 |
| **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`, client id `ce320965-6956-4759-84bb-7cb71cfc6252` (user1) |
| Sub-сервер | `[::]:443` (path /sub), панель `[::]:2053` |
| Env | `TZ=Asia/Novosibirsk`, `PUID=950`, `PGID=950` |
| Ports (host) | `54321:54321` (не используется панелью — внутри панель на 2053, можно убрать) |
**Статус (2026-09-01):** контейнер **Up**, панель HTTP 200. Reverse **портал** развёрнут отдельным контейнером `xray-reverse-portal` (см. ниже). 3x-ui поддерживает reverse (`clientReverseTags`).
**✅ ПРОВЕРЕНО РАБОТАЕТ (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` — клиент падает. Это частая причина «не подключается».
> ⚠️ База `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 внедрён на TCP+REALITY (2026-09-01 выполнен) + ИСТИННЫЙ КОРЕНЬ НАЙДЕН 2026-09-02.** Portal пересоздан на TCP+REALITY (`12346:12346`), OpenWrt DNAT `внешний:12346 → 192.168.2.197:12346` добавлен, bridge на Kraken пересоздан. REALITY-ключи: server PrivateKey `0JTjeirfviDqCr63wSnisvU7DV6SpR9_9V2l_EUHmkk`, PublicKey `GhsphQLT_0fwOvK45MHeAgG3sBQsFtw7lQfUIbrLMQU`, shortId `1451ef281caf5905`, SNI `www.cloudflare.com`. **НЕ ВНЕДРЕНО (ждёт команды):** payload по-прежнему не проходит даже с фиксом #6612 → истинный корень [issue #6242](https://github.com/XTLS/Xray-core/issues/6242) (регрессия bridge в v26.5+, у нас 26.7.28). Решение: сдаунгрейд bridge до `teddysun/xray:26.4.25`. Детали: [[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.
**Ключевые файлы конфига:**
| Файл | Назначение |
|------|------------|
| `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
Мост Modbus RTU → TCP: пробрасывает серийный порт в TCP 502. Используется и для вентиляции (AT2), и для ZONT-шины.
- **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
Кастомный Python-мост (`modbus_ha_bridge.py`, репо `HA-ZONT-Modbus`), контейнер `/mnt/RED_2TB/docker/modbus-bridge/`.
- **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/plans/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 **не** подгружает его автоматически).
---
## Печать / 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]].
## Связанные заметки
- [[truenas-access]] — SSH-доступ
- [[truenas-rclone-backup]] — система бэкапов
- [[obsidian-sync]] — Obsidian sync Eagle ↔ Taiga ↔ Kraken
- [[openmediavault-rpi5]] — Kraken NAS (Hermes агент, sync)
@@ -1,8 +1,60 @@
# TrueNAS — SATA порты и пулы
<<<<<<< HEAD
> Обновлено: 2026-08-17
## ✅ РЕШЕНО: HGST 12TB завёлся — проблема была в 3.3V PWDIS, НЕ в карте
=======
> Обновлено: 2026-08-21 (данные спасены, пул RED_2TB OFFLINE, готовность к пересозданию). СТАТУС: выгрузка данных на IronWolf **завершена успешно** (4.56T на `/mnt/IRONWOLF`, подтверждено Alex). Пул RED_2TB **OFFLINE** (не импортирован), диски физически на месте. Идёт подготовка к пересозданию пула с новой топологией (добавляем WD2TB#2 зеркалом к WD2TB#1). HGST сломан (см. ниже).
## ✅ РЕШЕНО (2026-08-21): пул RED_2TB — данные спасены, пул OFFLINE, готовность к пересозданию
**ВЫГРУЗКА ДАННЫХ ЗАВЕРШЕНА УСПЕШНО.** Alex подтвердил: «операция завершилась успешно, ничего не было перезаписано». Данные RED_2TB (4.56T) лежат на IronWolf 12TB — пул `DEST`, `/mnt/IRONWOLF`. Ключевые конфиги подтверждены на `/mnt/IRONWOLF`: `system/tunnel.sh`+`tunnel_key`+`.pub` (критичный SSH-туннель), `docker.bak/` (309M), `docker/` (1.1G), `immich-photos-upload`, `dedupe_rm.sh`, `files.txt.xz`. `storage/obsidian` и `storage/git` существуют (Permission denied для `truenas_admin` из-за NFSv4 ACL, transmission-owner — это нормально, НЕ потеря).
**Текущее состояние (2026-08-21, live-проверка):**
- **RED_2TB пул — статус OFFLINE** в БД TrueNAS (`midclt call pool.query``id=1, guid 3817880812699166755`), пул **НЕ импортирован**. `zpool export RED_2TB``no such pool` (уже выгружен/не в активном контексте).
- `zpool import -d /dev` всё ещё **видит** RED_2TB как **ONLINE** импортируемый, члены: `sdc2` (simplex WD2TB#1) + `mirror-1 {sde2 WD4TB, sdd2 Seagate4TB}`.
- rsync не запущен — проверочный прогон завершён.
- Диски физически на месте (by-id, см. таблицу портов ниже).
**Актуальная раскладка дисков (2026-08-21, по `/dev/disk/by-id`, стабильные имена):**
| Диск | by-id/model | Роль |
|------|------------|------|
| sda | `ata-KINGSTON_SA400S37120G_50026B77844E881C` | Boot SSD (не трогать) |
| sdb | `ata-ST12000NT001-3LX101_WV700FQ5` | ⭐ IronWolf 12TB = DEST, `/mnt/IRONWOLF` (целевой, данные выгружены) |
| sdc | `ata-WDC_WD20EFAX-68B2RN1_WD-WXH2A31D5HDJ` | **WD2TB#1** (исходный simplex-член RED_2TB) |
| sdd | `ata-ST4000DM004-2CV104_WFN66CM2` | **Seagate4TB** (mirror-1 второй член) |
| sde | `ata-WDC_WD40EZAZ-00SF3B0_WD-WX22D51JJFZ7` | **WD4TB** (mirror-1 первый член) |
| sdf | `ata-WDC_WD20EFAX-68B2RN1_WD-WXJ2A31CUNNT` | **WD2TB#2** (доп., НЕ в исходном пуле) |
## ⚠️⚠️ АКТИВНАЯ ПРОБЛЕМА №1 (ЗАКРЫТО, история): пул RED_2TB импортирован READONLY, данные выгружались rsync
Пан-loop преодолён (рецепт ниже). RED_2TB импортирован readonly удачно — **паники больше нет**. **ПРОГРЕСС 2026-08-18:** дочерние datasets (`storage`, `backup`, `Photos`, `Edu`, `docker`, `old-bu`, `TimeMachine/guest`, `iocage/*`) **успешно смонтированы под root** (`zfs mount -a` + при необходимости `mount -o remount,rw /`). Данные видны. Выгрузка на IronWolf идёт **rsync** (см. блок ниже).
**ТЕКУЩИЙ БЛОКЕР (конец сессии):**
- `zpool import`/`mount` требуют **root** (`some devices require root privileges`). `truenas_admin` НЕ root (sudo просит пароль). Все операции с пулом — только под root.
- **Нужно добыть root:** SSH → включить root login (`PermitRootLogin`), или выполнять команды через WebUI-админ/консоль.
- **IronWolf 12TB подключён к материнке** (sdc) как целевой диск для спасения данных. На нём **создан пул-приёмник `DEST`** (rw, ONLINE, ~10.6T свободно), монтируется на `/mnt/IRONWOLF`. Первая попытка rsync скопировала только 355G (см. блок 2026-08-18 ниже).
- **WD 2TB#1 (sda2, simplex-член RED_2TB) СЕЙЧАС ОТКЛЮЧЁН** — чтобы загрузиться без паники его отсоединяли; на конец сессии он не в системе. RED_2TB без него может импортироваться, но его данные частично будут недоступны.
## ⚠️⚠️ ПРОБЛЕМА №2: HGST 12TB УРОНЕН НА ПОЛ — вероятный слом после падения
**2026-08-17 вечер.** HGST (HUH721212ALE600, сер. 8CKD08RE) **уронили на пол, будучи подключённым**. Развитие сценария (как происходило):
1. **После удара — сектор 0 стал нечитаем** (по USB-мосту): ядро давало `critical medium error, dev sdf, sector 0``Add. Sense: Unrecovered read error``unable to read partition table` / `unable to read RDB block 0`. Разметка (`sdf1`/`sdf2`) пропала. Это НЕ ошибка моста/кабеля — `hostbyte=DID_OK driverbyte=DRIVER_OK`, ошибку вернул сам диск.
2. **smartctl мог прочитать INFO-секцию** (`Model: HGST HUH721212ALE600`, `8CKD08RE`, FW `LEBDT3P2`, 512e, SATA 6.0 Gb/s, SMART enabled) — контроллер жив, линк поднят.
3. **На MacBook через USB-мост диск «щёлкает» и не шуршит головкой при старте** — признак механических проблем после удара (головки/мотор). КЛИК-ОФ-ДЕФ возможен, но также нельзя исключать нехватку питания через USB-мост на 12TB-диске.
**Состояние (на 2026-08-17):** **подтверждён аппаратный отказ — диск не ремонтопригоден.** Симптом: ритмичный «click-click, click-click» при работающем моторе = головки не могут выйти на дорожку/парковку (классический click of death после удара). Это механическое повреждение, НЕ лечится программно (SMART/прошивка), чинить может только профи-recovery и это дороже нового диска. **Данных на нём НЕТ** (не был добавлен в пул, только новая разметка sdf1/sdf2) — поэтому списан без recovery. Закрыто.
> ⚠️ Урок для будущего: enterprise-диск, уроненный на пол работающим — почти всегда аппаратная смерть (мотор/головки). Если на диске критичные данные — только профи-recovery, и шанс не 100%.
> 🔁 ИСТОРИЯ ВОПРОСА: до падения диск был ПОЛНОСТЬЮ рабочим. Причина исходного «молчания» по SATA — PWDIS (см. ниже). После снятия 3.3V завёлся и линковался. Затем урон на пол — аппаратный отказ (click of death).
---
## ✅ РЕШЕНО (исторически): HGST 12TB заводился — проблема была в 3.3V PWDIS, НЕ в карте
>>>>>>> origin/main
**2026-08-17.** HGST **линуется и полностью работает** теперь. Ключевое изменение — **отключена/обезврежена 3.3V линия (PWDIS-контакт №3 на SATA-разъёме питания)**. Диск:
- определяется как `/dev/sde`, `HGST HUH721212ALE600`, серийник `8CKD08RE`, **10.9T**, секторов `23437770752` (штатная ёмкость 12TB по SFF-8447)
@@ -16,11 +68,16 @@
**ASUS P8H77-V LE**, чипсет Intel H77.
6 SATA портов на Intel контроллере (порт от ASMedia отсутствует).
<<<<<<< HEAD
### Распределение портов (текущее состояние — после перетыкания 2026-08-17)
=======
### Распределение портов (актуально на конец 2026-08-17, после финального перетыкания)
>>>>>>> origin/main
| Порт (ata) | Тип | Скорость | Цвет | Диск | by-id |
|------------|-----|----------|------|------|-------|
| ata1 (SATA6G_1) | SATA 3 | 6 Gb/s | серый | **sda** — WD 2TB (WD20EFAX) | WD-WXH2A31D5HDJ |
<<<<<<< HEAD
| ata2 (SATA6G_2) | SATA 3 | 6 Gb/s | серый | **sdb** — WD 2TB (WD20EFAX, второй, был на карте ata9) | WD-WXJ2A31CUNNT |
| ata3 (SATA3G_1) | SATA 2 | 3 Gb/s | синий | **sdc** — WD 4TB (WD40EZAZ) | WD-WX22D51JJFZ7 |
| ata4 (SATA3G_2) | SATA 2 | 3 Gb/s | синий | **sdd** — Kingston 120GB SSD (boot) | 50026B77844E881C |
@@ -34,6 +91,24 @@
- Несмотря на перетыкание пулы **здоровы** (см. раздел про пулы ниже) — подтверждено, что ZFS не зависит от порта.
> ⚠️ В отличие от изначального плана, диски сейчас не по плану — проверять актуальное распределение по `by-id`/модели, а не по буквам. Типичные буквы при стабильном подключении: sda=WD2TB#1, sdb=WD2TB#2, sdc=WD4TB, sdd=Kingston, sde=Seagate4TB.
=======
| ata2 (SATA6G_2) | SATA 3 | 6 Gb/s | серый | **sdb** — WD 4TB (WD40EZAZ) | WD-WX22D51JJFZ7 |
| ata3 (SATA3G_1) | SATA 2 | 3 Gb/s | синий | **sdc** — ⭐ **IronWolf 12TB (ST12000NT001)** | WV700FQ5 |
| ata4 (SATA3G_2) | SATA 2 | 3 Gb/s | синий | **sdd** — Kingston 120GB SSD (boot) | 50026B77844E881C |
| ata5 (SATA3G_3) | SATA 2 | 3 Gb/s | синий | *(свободен/не иден-тиф.)* | — |
| ata6 (SATA3G_4) | SATA 2 | 3 Gb/s | синий | **sde** — Seagate 4TB (ST4000DM004) | WFN66CM2 |
| *(карта ASM1166)* | — | — | — | **НЕ В СЛОТЕ** (вытащена) | — |
**⚠️ Фактическое положение на конец сессии (2026-08-17, после подключения IronWolf для спасения):**
- **Буквы разъехались ещё раз.** Финальный `lsscsi`: **sda=WD4TB**, **sdb=Kingston boot**, **sdc=⭐ IronWolf 12TB (целевой для спасения)**, **sdd=Seagate4TB**. **WD 2TB#1 (`WD-WXH2A31D5HDJ`) СЕЙЧАС ОТКЛЮЧЁН / НЕ в системе** (отсоединяли, чтобы загрузиться без паники).
- **⭐ IronWolf 12TB подключён к материнке и ЛИНКУЕТСЯ** — `sdc` = `ST12000NT001-3LX101`, 10.9T, by-id `WV700FQ5`. Он свободен (не в пуле) и определён как **целевой диск для спасения данных с RED_2TB**. На нём ещё НЕ создан пул-приёмник.
- **Карта ASMedia ASM1166 вытащена** — `lspci` показывает только Intel H77 (`00:1f.2`). WD 2TB#2 перенесён с карты, затем был намеренно отключён пользователем.
- **HGST 12TB (`HUH721212ALE600`)** — УРОНЕН НА ПОЛ, аппаратный отказ (см. блок КРИТИЧНО), считается вышедшим из строя.
> ⚠️ Буквы (`sda`/`sdb`) **shift-аются при перетыкании** и сейчас разъехались: `sdb` = WD4TB (не WD2TB#2!), `sdc` = IronWolf. **Всегда сверять по by-id/модели, не полагаться на буквы.**
> ⚠️ ⚡ **СРОЧНО:** пул `RED_2TB` после этого перетыкания НЕ заимпортирован (см. блок «КРИТИЧНО» в разделе пулов). Все члены на месте — нужен Import Pool.
>>>>>>> origin/main
## Плата расширения SATA в PCIe (установлена ~2026-07-30)
@@ -63,7 +138,11 @@
## ✅ Решение HGST 12TB (2026-08-17) — корень найден, диск работает
<<<<<<< HEAD
> ⚠️ **Актуальный статус на 2026-08-17 вечер:** хоть HGST и завёлся (см. ниже КАК), в финальном перетыкании **карта ASM1166 вытащена из слота, HGST и IronWolf сейчас НЕ подключены** (подробнее в таблице портов выше). Этот блок фиксирует **как была решена причина не-линка** — пригодится, когда диск вернётся в систему.
=======
> ⚠️ **Актуальный статус на 2026-08-17 ночь:** HGST **УРОНЕН НА ПОЛ и сломан** (см. блок КРИТИЧНО в самом верху). Карта ASM1166 вытащена из слота, IronWolf подключён на материнку. Этот блок фиксирует **как изначально решалась причина не-линка** (PWDIS) — полезно для понимания, но теперь диск вышел из строя механически.
>>>>>>> origin/main
Проблема не-линка HGST по SATA **решена: это 3.3V PWDIS на SATA-питании.** Разметка не трогалась — sde1=200M, sde2=10.9TB остались как были. Когда диск снова будет подключён — добавить в пул TrueNAS по by-id/GUID (ZFS к порту не привязана). После добавления — удалить этот блок.
@@ -102,20 +181,192 @@ lspci -k | grep -i sata
## Важно про ZFS и перетыкание
- ZFS не привязана к букве диска или SATA порту. TrueNAS распознаёт пул по GUID на дисках.
<<<<<<< HEAD
- Можно перетыкать диски в любые порты — TrueNAS поднимет пул автоматически (подтверждено 2026-08-17).
- Если пул не поднялся автоматически: WebUI → Storage → Import Pool.
=======
- **Перетыкание НЕ всегда поднимает пул автоматически** (2026-08-17: RED_2TB не заимпортировался сам после перетыкания, см. «КРИТИЧНО» ниже). Если пул не виден в `zpool list` — нужен ручной Import (WebUI Storage → Import Pool или `zpool import <pool>` под root). Данные при этом целы, пока все члены `ONLINE`.
>>>>>>> origin/main
- Проверка пула после перетыкания: `/sbin/zpool status <pool>` — убедиться что все члены `ONLINE`, ошибки `0 0 0`.
## Пулы TrueNAS (проверено 2026-08-17)
Имена пулов, топология и члены — проверять статус через `/sbin/zpool` (см. ниже про PATH).
<<<<<<< HEAD
| Пул | Размер | Члены (по /dev со стабильным подключением) | Топология | Монтирование |
|-----|--------|-----------|-----------|--------------|
| **RED_2TB** | 5.44T (4.60T занято) | mirror: `sdc2` (WD4TB) + `sde2` (Seagate4TB); отдельно `sda2` (WD2TB) | 1 диск (sda2) + mirror-1 (2 диска) | `/mnt` |
| **boot-pool** | 111G (7.65G занято) | `sdd3` (Kingston 120GB boot SSD) | 1 диск | — |
- RED_2TB: HEALTH **ONLINE**, нераспределённый свободный диск (данные не реплицируются на sda2 — он отдельный, а не парный). Если redun-dancy важна — учесть, что sda2 без зеркала.
=======
| Пул | Размер | Члены (по `/sbin/zpool status` от 2026-08-17) | Топология | Монтирование |
|-----|--------|-----------|-----------|--------------|
| **RED_2TB** | 5.44T (4.60T занято) | **state ONLINE, 0 0 0 ошибок, "No known data errors"**: `sdd2` (WD2TB#1) + mirror-1 `{sdc2 WD4TB, sdb2 Seagate4TB}` — буквы по последнему status, сверять by-id (буквы shift-аются) | 1 диsk (`WD2TB#1`) + mirror-1 (WD4TB+Seagate) | `/mnt`**readonly-импорт, datasets не смонтированы, данные НЕ выгружены** |
| **boot-pool** | 111G (7.65G занято) | `sdb3` (Kingston 120GB boot SSD) | 1 диск | — |
- RED_2TB: HEALTH **ONLINE** по `zpool status` (readonly-импорт не паникует), scrub «завис» на ~72% (при readonly не доходит — но это НЕ фикс, см. ниже). Все ошибки 0 0 0 — **данные целы**. Один vdev (`WD2TB#1`) simplex — без зеркала; WD2TB#1 сейчас физически отключён.
### ✅ ПРОГРЕСС (2026-08-17 глубокая ночь): READONLY-импорт УСПЕШЕН, паника преодолена
**Рабочий рецепт получения доступа к данным подтверждён на практике.** Члены пула физически на месте: `sda2`=WD2TB#1 (ata1), `sdb2`=WD4TB (ata2, буква сменилась), `sde2`=Seagate4TB (ata6).
**Что сработало (пошагово):**
1. Тюнабели `zfs.zfs_recover=1 zfs.zil_replay_disable=1` в GRUB → **НЕ помогли** (всё равно паника). `rd.break=pre-mount` и `rd.break` → тоже НЕ помогли.
2. **ЕДИНСТВЕННЫЙ рабочий способ загрузиться без паники:** физически ОТКЛЮЧИТЬ все диски проблемного пула (чтобы дойти до рабочего shell/WebUI), затем вставить обратно.
- Включить с отключёнными дисками RED_2TB (WD2TB#, WD4TB, Seagate4TB) → boot-pool поднимается, паники нет.
- Вставить диски обратно (горячо) в те же порты.
3. **READONLY-импорт не паникует** (по mav из iXsystems: «read-only import doesn't even read space maps»):
```bash
zpool import -o readonly=on RED_2TB
```
→ **`Import was successful`** — паники нет, метаданные прочитаны! (попытка `zpool import -nRED_2TB` без `-F` невозможна; `-n` требует `-F` синтаксиса.)
4. **⚠️ Текущий блок:** после readonly-импорта выдаются ошибки монтирования:
```
cannot mount '/RED_2TB': failed to create mountpoint: Read-only file system
Import was successful, but unable to mount some datasets
```
Причина: корневая ФС readonly (после обхода паники). **Точки монтирования не создаются.**
**СЛЕДУЮЩИЙ ШАГ (не завершён):** смонтировать datasets вручную в существующую/записываемую точку (корневая / readonly). Порядок:
```bash
zfs list -r RED_2TB # какие datasets есть (zfs list работает без mount)
# смонтировать в существующую пустую папку, не создавая новую (или через tmpfs/rw-точку)
# например:
# mkdir -p /mnt/rec 2>/dev/null; (если /mnt rw — иначе выбрать rw-точку)
# zfs set mountpoint=/mnt/rec RED_2TB (или mount -o)
# затем выгружать данные на запасные диски rsync
```
**Критичные ограничения (выяснены по ходу):**
- `zpool import` требует **root** (`some devices require root privileges`) — truenas_admin НЕ root (sudo просит пароль). Все операции import/mount — под root. **На конец сессии это главный блокер** — без root не смонтировать/выгрузить.
- Раньше при readonly-импорте в тредах было: datasets показываются но пути «not found», и полностью нечитаемы (permission denied) если данные повреждены. Здесь readonly-импорт прошёл чисто (no panic) — но монтирование ещё не доведено до конца.
- **Данные на пуле важно выгрузить на другие диски** (пул восстановится только пересозданием — аппаратная метаданная ошибка). Это главный незавершённый шаг.
**🧪 ИТОГ ПО «ПОЧИНИТЬ ПУЛ» (2026-08-17, важно для будущих сессий):**
- **In-place «починки» НЕТ.** По mav (лидер OS-команды iXsystems) в тредах: *"I don't know a way to recover from this situation without data offload and pool recreation"*. Паника на space map не лечится флагами.
- **Опции это НЕ решают:** `zfs.zfs_recover=1`, `zfs.zil_replay_disable=1` (в GRUB), `rd.break=pre-mount`, `rd.break` — все НЕ помогли (паника осталась). Readonly-импорт («doesn't even read space maps») — единственное, что не паникует и даёт доступ к данным.
- **`-F` (восстановление) уже показал панику** в этой сессии (`adding existent segment to range tree`). Повторный `-F` на повреждённом пуле рискован — может углубить повреждение. Не жать вслепую.
- **`zpool attach RED_2TB <wd2tb2>` (идея зеркала на 2 WD2TB) НЕ выполнима в текущем состоянии**: attach — это write, он пишет в space maps (обновляет метаданные) → паника. Readonly-импорт не даст attach; переимпорт в rw вернёт панику. Также 2TB не влезет под 4.6T данных целиком. Идея зеркала валидна только ПОСЛЕ пересоздания пула из спасённых данных.
- **Правильная дорога (единственная надёжная):** readonly-импорт → смонтировать datasets вручную → выгрузить данные на целевой пул (IronWolf 12TB) → пересоздать RED_2TB → вернуть данные. Попытки «починить rw» возможны, но только ПОСЛЕ спасения данных и на свой риск.
- **Для «100% восстановления с правами»:** `rsync -aHAX` (права, владельцы, ACL, xattr, хардлинки) или `zfs send | zfs recv` (идеально байт-в-байт со снимками, но требует пула-приёмника и снимка).
> ⚠️ После успешного монтирования и выгрузки — обновить таблицу членов пула и закрыть этот блок.
### 🆕 ПРОГРЕСС (2026-08-18): datasets смонтированы под root, выгрузка идёт rsync — НЕ send|recv
**Смонтирование дочерних datasets — РАБОТАЕТ под root.** Это снимает блокер «datasets не смонтированы» из прошлой сессии:
```bash
mount -o remount,rw / # если корневая ФС readonly мешает создавать mountpoint-ы
zfs mount -a # смонтировать все datasets
# проверить:
df -h /RED_2TB # должно показать ~4.6T, а НЕ 1.1T/362G родительского
ls /RED_2TB/storage | head # должно быть не пусто (Cartoons, Downloads, Movies...)
```
После `zfs mount -a` в `mount` видны все дочерние datasets на `/RED_2TB/*` (все `ro` — readonly, для чтения rsync это норм).
**⚠️ СМОНТИРОВАТЬ datasets под `truenas_admin` НЕЛЬЗЯ** — `zfs mount -a` даёт `Insufficient privileges`. Монтирование и выгрузка — только **под root**.
**🐛 Причина «только 355G» на первой выгрузке rsync (разгадана):** первая попытка `rsync /RED_2TB/ /mnt/IRONWOLF/` запускалась, когда **дочерние datasets НЕ были смонтированы**, поэтому `/RED_2TB/storage` (3.24T), `/RED_2TB/backup` (287G) и т.д. были **пустыми mountpoint-дирами**. rsync скопировал только ~355G, лежащих прямо в родительском dataset `RED_2TB` (REFER 362G: `.DS_Store`, `dedupe_rm.sh`, `files.txt.xz`, `docker.bak`, `system`, `immich-photos-upload`). **rsync не сломался — ему просто нечего было копировать из не смонтированных дочерних datasets.** После монтирования данных стало ~4.6T — rsync перезапущен.
**❌ `zfs send | zfs recv` НЕ работает на повреждённом пуле — использовать rsync:** при `zfs send RED_2TB/storage | zfs recv DEST/storage` (под root) recv падает с `signal received` / `Bad file descriptor` / `IOT instruction (core dumped)`, exit 1. ZFS не может прочитать данные/метаданные из пула с повреждённой space map на лету при stream-чтении. **rsync — правильный и единственный надёжный способ** (переживает ошибки чтения отдельных файлов, exit 23, копирует остальное).
**⚠️ ЛОВУШКА «zfs send -n» (dry-run) НЕ подтверждает права send:** под `truenas_admin` `zfs send -n RED_2TB/docker` возвращал **exit 0 без ошибок** — это ОБМАНЧИВО. Реальный `zfs send` (без `-n`) даёт `warning: cannot send 'RED_2TB/docker': permission denied`. Дочерние datasets доступны только root (ACL root-only). Не доверять dry-run для проверки прав send.
**Команды выгрузки (под root):**
```bash
rsync -aHAX --info=progress2 /RED_2TB/ /mnt/IRONWOLF/ > /tmp/rsync2.log 2>&1 &
# прогресс:
while true; do clear; date +%H:%M:%S; du -sh /mnt/IRONWOLF/; tail -3 /tmp/rsync2.log; pgrep -a rsync >/dev/null && echo RUNNING || echo DONE; sleep 15; done
```
**Итог выгрузки:** после монтирования datasets и перезапуска rsync должны лечь все ~4.6T (storage, backup, Edu, Photos, TimeMachine/guest, old-bu, docker...). После завершения — сверка `du -sh /mnt/IRONWOLF/` vs `zfs list RED_2TB` и обновить таблицу членов пула.
**Опция добавить WD2TB#2 как зеркало к WD2TB#1** (`zpool attach RED_2TB <wd2tb2>`): валидна, но ТОЛЬКО после успешного импорта пула и его стабилизации. Не пытаться до восстановления.
### ✅ ПЕРЕСОЗДАНИЕ ПУЛА (2026-08-21) — ВЫПОЛНЕНО
**Решение (подтверждено Alex):** пересоздаём RED_2TB с **новой топологией — ВКЛЮЧАЕМ WD2TB#2 (sdf) зеркалом к WD2TB#1 (sdc)**. В итоге: `mirror {sdc, sdf}` + `mirror {sde, sdd}` — оба исходных simplex-члена получают зеркала (ранее WD2TB#1 был simplex без защиты).
**✅ СТАТУС (2026-08-21, live): пул СОЗДАН успешно.** `zpool create RED_2TB mirror /dev/sdc /dev/sdf mirror /dev/sde /dev/sdd` → `state: ONLINE, 0 0 0 ошибок, No known data errors`, `SIZE 5.44T, ALLOC 384K, HEALTH ONLINE`. Пул пустой (данные ещё возвращаются).
**Записи TrueNAS, которые важно знать (2026-08-21):**
- `midclt call pool.query` → `id=1, name=RED_2TB, status=OFFLINE`, `topology:null`. Устаревшая запись в БД.
- **`midclt call pool.delete 1` НЕ существует** в этом билде (`'PoolService' object has no attribute 'do_delete'`) — запись через API не удалить. Пользоваться командной строкой `zpool` (root) или UI.
- `zpool labelclear -f` **принимает только ОДИН vdev за раз** — «too many arguments» при передаче нескольких дисков.
**Команды пересоздания (под root, на консоли TrueNAS):**
```bash
# 1. Стереть старые метки ZFS с ПАРТИЦИЙ (пул был построен на разделах *2, НЕ на целых дисках!)
zpool labelclear -f /dev/sdc2
zpool labelclear -f /dev/sdf2
zpool labelclear -f /dev/sde2
zpool labelclear -f /dev/sdd2
# 2. Проверить, что RED_2TB исчез из импортируемых
zpool import -d /dev
# 3. Создать пул заново на ЦЕЛЫХ дисках (TrueNAS создаст свои разделы *2)
zpool create RED_2TB mirror /dev/sdc /dev/sdf mirror /dev/sde /dev/sdd
# 4. Проверить
zpool status RED_2TB
zpool list RED_2TB
```
**⚠️ КРИТИЧЕСКИЕ ЛОВУШКИ labelclear (из openzfs issues #18027, #3156, #14869):**
- **Целиться надо в ПАРТИЦИИ (`*2`), а не в целый диск.** TrueNAS строит пулы на разделах `...2`. `zpool labelclear -f /dev/sdc` (целый диск) даёт `failed to clear label for /dev/sdc` — метки лежат внутри раздела `sdc2`, на целом диске их «не видит» целиком.
- **`failed to clear label` также выводится, когда метки УЖЕ стёрты** (issue #18027) — не обязательно ошибка. Если после `labelclear` `zpool import -d /dev` не показывает RED_2TB — значит метки стёрты, всё ок.
- `labelclear` сам по себе может не стереть оба набора меток (`#14869`), если чистить не ту цель — поэтому чистить по разделам, которые реально добавлялись.
**🧭 НОВАЯ ТОПОЛОГИЯ ПОСЛЕ ПЕРЕСОЗДАНИЯ:**
| vdev | Члены | Назначение |
|------|-------|-----------|
| mirror-0 | sdc (WD2TB#1) + sdf (WD2TB#2) | Пара WD 2TB (зеркалирование) |
| mirror-1 | sde (WD4TB) + sdd (Seagate4TB) | Пара 4TB (зеркалирование) |
**После создания пула — НЕ забыть:**
- пересоздать datasets по [[red2tb-dataset-map]] (storage, backup, Photos, Edu, TimeMachine/guest, docker, old-bu, iocage; `.system`/`ix-apps` TrueNAS создаст сама);
- решить судьбу данных ВНЕ датасетов (`system/`, `docker.bak/`, `immich-photos-upload/`, корневые файлы) — после пересоздания окажутся в корневом dataset;
- вернуть данные: `rsync -aHAX /mnt/IRONWOLF/ /RED_2TB/`;
- восстановить инфраструктуру (docker: caddy, transmission, HA, immich...), доступы, cron-бэкапы, Obsidian sync.
### ✅ LIVE-СТАТУС ПОСЛЕ ПЕРЕСОЗДАНИЯ (2026-08-24, проверка Китом)
**Пул УЖЕ зарегистрирован в TrueNAS и работает — перезагрузка/импорт НЕ нужны:**
- `zpool status RED_2TB` → **ONLINE** (mirror-0 {sdc,sdf} + mirror-1 {sde,sdd}), ошибки `0 0 0`.
- `midclt call pool.query` → `id=1, name=RED_2TB, status=ONLINE`, topology заполнена новой (оба mirror, GUIDs). БД TrueNAS привязала пул по GUID, запись обновлена под новую топологию.
- Пул смонтирован (`/mnt/RED_2TB/`, `mounted=yes`), CAP 79% (5.44T, ALLOC 4.35T, FREE 1.09T).
- **rsync возврата данных ЗАВЕРШЁН.** Вернулись все datasets: storage 3.29T, immich-photos-upload 353G, backup 287G, Edu 214G, Photos 146G, old-bu 65.2G, docker 2.92G, docker.bak 789M, system 112K. Корни IronWolf↔RED_2TB идентичны по ls.
**⚠️ НЕ ЗАКРЫТО: TimeMachine (~277G) НЕ вернулся.** Причина: на IronWolf `/mnt/IRONWOLF/TimeMachine/` существует (277G), но root-only NFSv4 ACL → `truenas_admin` НЕ может прочитать (`Permission denied`) → rsync его не докопировал. На RED_2TB датасет `TimeMachine` НЕ воссоздан (нет в `zfs list`, каталога нет). **TODO под root:** создать dataset `RED_2TB/TimeMachine` (+ дочерний `guest` как было) и `rsync -aHAX /mnt/IRONWOLF/TimeMachine/ /mnt/RED_2TB/TimeMachine/`. iocage-каталог восстановлен, но старые jails не нужны (всё в docker) — решено ранее.
### ⚠️⚠️ АКТИВНАЯ ПРОБЛЕМА №3 (2026-08-24): Docker/слой приложений НЕ поднят — контейнеры лежат
Пул с файлами работает, но **слой приложений (docker/TrueNAS Apps) НЕ восстановлен**. Проверка live (Кит):
- `docker ps` → `Cannot connect to the Docker daemon`. `systemctl status docker` → `inactive (dead)`, **disabled**.
- **`docker daemon.json` (`/etc/docker/daemon.json`):** `{"data-root": "/mnt/.ix-apps/docker", "exec-opts": ["native.cgroupdriver=cgroupfs"], "iptables": true, "storage-driver": "overlay2", "default-address-pools": [{"base": "172.17.0.0/12", "size": 24}]}` → это классическая схема TrueNAS Apps.
- **Датасета `.ix-apps`/`ix-applications` НЕТ** в `zfs list` на пересозданном пуле → docker storage/образы/volumes (в старом пуле это был датасет `ix-apps`, docker 23.6G) **НЕ мигрировали** / потеряны.
- **Конфиги ВСЕХ приложений на месте** в `/mnt/RED_2TB/docker/` (29 каталогов): arr, backups, caddy, cups, filebrowser, gitea, ha, hermes, homeassistant, immich, inpx-web, inpxer, library, mbusd, modbus-bridge, mosquitto, nodered, portainer, portainer-mcp, python, rclone, ser2net, syncthing, transmission, vless-proxy, watchtower, webdav, xray-admin, zigbee2mqtt.
- `override.conf` (`/etc/systemd/system/docker.service.d/override.conf`): только `ExecStartPost=iptables -P FORWARD ACCEPT && ip6tables -P FORWARD ACCEPT` — применяется при старте docker.
**Вывод:** `/mnt/RED_2TB/docker/` — это конфиги; docker-образы (layers) не сохранились → контейнеры надо пересоздавать с перекачкой образов.
**ПЛАН ВОЗВРАТА КОНФИГА В СТРОЙ (4 шага, пока НЕ выполнен):**
1. **WebUI TrueNAS → Apps → Settings → Choose Pool → RED_2TB.** TrueNAS сама создаст датасет приложений (ним `ix-applications`), примонтирует docker storage в `/mnt/ix-applications` (data-root `.ix-apps/docker`), поднимет `docker.service`. *(`docker` сейчас disabled — старт произойдёт именно через настройку Apps, не вручную.)*
2. Конфиги приложений уже лежат в `/mnt/RED_2TB/docker/<app>` — трогать не надо.
3. **Пересоздать каждый контейнер** (WebUI Apps нативный/Custom App) с **bind-mount** `/mnt/RED_2TB/docker/<app>` → внутрь контейнера. Образы перекачаются при старте, контейнер подхватит свой существующий конфиг.
4. Разовое: `override.conf` (iptables FORWARD) применится сам при старте docker; порты/сеть прежние; данные приложений (immich library, transmission downloads и т.д.) уже в `/mnt/RED_2TB/`.
**⚠️ Перезагрузка НЕ поможет** поднять контейнеры: docker `disabled` + пул приложений не настроен. Перезагрузка полезна только ПОСЛЕ шага 1.
**⚠️ Вопрос к Alex:** docker storage `.ix-apps` (образы, ~23.6G) точно НЕ переносили на IronWolf? Если перенесли — указать куда, вернуть и настройка упростится (образы сохранятся). Если нет — только перекачка.
## ⚠️ НЕ ВХОДИТЬ В RW-ИМПОРТ ПОВРЕЖДЁННоГО ПУЛА
**Импорт RED_2TB в не-readonly режиме (`zpool import` без `-o readonly=on`) — ВСЕГДА даёт kernel panic** (`zfs: adding existent segment to range tree`). Это правило подтверждено много раз. При пересоздании пул НЕ импортировать — только стереть метки (`labelclear`) и создать заново. `zpool import -d /dev` (dry-list) безопасен, но не запускает пул.
>>>>>>> origin/main
- Идёт регулярный scrub (запускается ночью воскресенья).
- **`zpool` не в PATH для zsh truenas_admin** — вызывать через абсолютный путь `/sbin/zpool` или `/usr/sbin/zpool` (иначе `command not found`).
+15 -2
View File
@@ -1,6 +1,6 @@
---
title: Vault Git Sync — Architecture & Scripts
updated: '2026-06-20'
updated: '2026-09-02'
type: tech
tags:
- vault
@@ -12,6 +12,12 @@ tags:
# Vault Git Sync
> **STATE 2026-09-02 (позднее обновление):** Eagle/bare repo снова **синхронны** (ahead=0/behind=0, `2fab879`). Ранее (см. ниже) git-sync стоял из-за битых прав `storage/git` — **починено** полной dacl-заменой (`family/documents/vault-sync/2026-09-02-restore-privilege-scope.md` §RESOLVED).
>
> **⛔ НОВАЯ проблема 2026-09-02 (не решена):** оба **Taiga-клиента** (`/storage/obsidian` и `/storage/obsidian-syncthing`) **отстали на месяц** — HEAD `ceea848` (2026-08-01) vs bare repo `2fab879` (2026-09-02). Причина: контейнер `hermes-taiga` в **crash-loop** (16339 рестартов) — `uv run hermes gateway run` не может докачать депы (pytz/markdown-it-py) с PyPI, т.к. весь HTTP идёт через **мёртвый `socks5://vless-proxy:1080`**, а `UV_CACHE_DIR=/tmp/uv-cache` пустеет на каждом рестарте. Taiga 3-phase sync (крон внутри агента) не выполняется => телефон видит устаревший vault. Подробно: `family/documents/vault-sync/2026-09-02-hermes-taiga-crashloop.md`. Фикс НЕ применён (ждёт Alex).
> **Триггер cron на маке (Eagle) — это launchd, НЕ Hermes cron:** `~/Library/LaunchAgents/com.sync-vault.plist` → `/Users/admin/scripts/sync-vault.sh`, `StartInterval=300` (5 мин). Скрипт `sync-vault-lib.sh` намеренно глушит dead remote (`git fetch` fail → `exit 0`), поэтому launchd показывает `last exit code = 0` даже при фактически стоящем sync. Системный crontab на маке пуст.
Obsidian vault is a bare git repo on TrueNAS:
`/mnt/RED_2TB/storage/git/obsidian-vault.git`
Also mirrored in Gitea: `https://git.mallexxx.duckdns.org/git_admin/obsidian-vault`
@@ -50,10 +56,16 @@ No stash. No GIT_DIR/GIT_WORK_TREE workarounds.
| Host | Script | Type | Trigger |
|--------|-------------------------------|---------------|----------------------|
| Eagle | `~/scripts/sync-vault.sh` | full clone | Hermes cron */5 |
| Eagle | `~/scripts/sync-vault.sh` | full clone | **launchd** `com.sync-vault` (⚠️ НЕ Hermes cron) `StartInterval=300` |
| Kraken | `~/scripts/sync-vault.sh` | sparse clone | host crontab */5 |
| Taiga | `/opt/data/sync-vault.sh` | 3-phase orch. | Hermes cron */5 |
> **⭐ УТОЧНЕНО 2026-09-02 (Eagle/мак sync-механизм):** автосинка на маке запускается **НЕ Hermes cron, а launchd-агентом** `~/Library/LaunchAgents/com.sync-vault.plist`:
> - Программа: `/Users/admin/scripts/sync-vault.sh`, `StartInterval = 300` сек (5 мин)
> - `launchctl list` → активен, `runs = 3762`, `last exit code = 0`
> - ⚠️ **`sync-vault-lib.sh` умышленно глушит недоступность remote**: если `git fetch` падает → логирует `Fetch failed (...)` и `exit 0`. Поэтому launchd показывает `exit code 0`, даже когда sync фактически сломан (см. случай ahead 55 при сломанном bare repo после restore). Это **не** отсутствие cron и не сбой — диагностировать нужно по `git status` (ahead count), а не по exit-code агента.
> - Системный crontab и `/etc/crontab` на маке отсутствуют.
All clients share a common library: `sync-vault-lib.sh` (same dir as sync-vault.sh).
Source of truth for scripts: `~/Developer/vault-sync-test/scripts/` on Eagle.
@@ -121,6 +133,7 @@ cd ~/Developer/vault-sync-test && bash test-sync.sh
- `git add -A` in sparse worktree still stages deletions of out-of-cone files tracked in index — need to unstage them (fixed in old script; irrelevant with proper clone)
- `core.quotePath=true` (default) escapes Cyrillic paths in `git ls-files` output — use `-c core.quotePath=false`
- ZFS on TrueNAS blocks `chmod``git init` fails from host; must run from inside Docker container or create `.git` structure manually
- **NFS4 `owner@ DENY READ_DATA` ACL breaks push (fake "corrupt" objects)** — see History 2026-09-02. Key: after a TrueNAS **pool restore**, a subset of loose git objects in the bare repo can carry an inverted NFS4 ACL `owner@ type=DENY READ_DATA=True`. In NFSv4 a DENY overlays ALLOW, so the owning uid (e.g. 950) can't mmap-read those objects → on receive, `git-receive-pack`/`index-pack` reports `loose object ... is corrupt` and rejects push, even though data is intact (`git fsck --full` under root is clean). Fix = `filesystem.setacl <repo> ... {stripacl:true}` (chmod/chown do NOT remove DENY ACEs). Tell-tale: POSIX file mode `40` (`r--------`) on loose objects vs normal `750`.
## History
+13 -3
View File
@@ -1,20 +1,30 @@
---
title: VPS qentra.top
created: '2026-05-24'
updated: '2026-05-27'
updated: '2026-09-01'
type: tech
namespace: personal
tags: [infra, vps]
confidence: medium
status: retired
related:
- "[[tech/xray-reverse-tunnel-kraken-truenas]]"
- "[[tech/kraken-network]]"
- "[[tech/wireguard-vpn]]"
---
# VPS qentra.top
**IP:** 91.207.28.205
**Stack:** nginx + Python 3.11, Cloudflare proxy
> ## ⛔ УДАЛЁН на 2026-09-01
> **VPS `91.207.28.205` (qentra.top) больше НЕ существует.** Вся инфраструктура на нём (nginx, Xray/VLESS+REALITY, x-ui panel, OpenVPN, WebSocket v.qentra.top, backup-скрипты, nolvu/panel vhosts) — утрачена вместе с сервером.
> **Следствия:**
> - На TrueNAS контейнер `vless-proxy` (teddysun/xray) outbound указывает на `v.qentra.top:443` → **сейчас мёртв**. Hermes-Taiga (SOCKS5 через `vless-proxy:1080`) **без рабочего прокси**.
> - WireGuard Eagle↔VPS↔Kraken: VPS-звено мёртво.
> - Rasputin-роутер VLESS-туннель (`188.239.191.235` / node3.sysnx.net) — это ДРУГОЙ сервер (не qentra), не трогать.
> - Замена для выхода клиентов сети TrueNAS → Kraken: см. **[[tech/xray-reverse-tunnel-kraken-truenas]]** (Xray reverse, ЧАСТИЧНО внедрён: 3x-ui на TrueNAS развёрнут 2026-09-01, reverse-клиент на Kraken ещё нет).
**IP:** 91.207.28.205 *(недоступен с 2026-09-01)*
**Stack:** nginx + Python 3.11, Cloudflare proxy *(исторические данные ниже)*
**Panels:** https://panel.qentra.top (x-ui, проксируется nginx на 8443 → 5430), v.qentra.top:8964
## Subdomain Setup
+6 -1
View File
@@ -1,7 +1,10 @@
# WireGuard VPN — Eagle ↔ Kraken
> Создано: 2026-05-14
> Статус: ✅ работает
> Статус: ⚠️ **СЛОМАНО на 2026-09-01** — VPS-узло (10.99.0.1/10.99.1.1) **удалён** вместе с qentra.top.
> Вся hub-and-spoke топология (wg-quick@wg0/wg1, SNAT, dnsmasq-резолвинг `kraken`, nftables forward) жила на VPS и **утрачена**. `ssh kraken` с Eagle извне через WG больше не работает.
> Альтернатива для внешнего доступа к Kraken на 2026-09-01: reverse-SSH туннель через VPS-заменитель не существует; локально дома — напрямую по LAN 192.168.1.15 (см. [[kraken-access]]). План замены сети: [[tech/xray-reverse-tunnel-kraken-truenas]].
> ⚠️ **Дома Eagle подключается к Kraken напрямую по LAN** (wg-auto.sh детектит домашний роутер и делает `wg-quick down`) — это направление работает. Проблема только во внешнем (не-дома) подключении.
## Топология
@@ -10,6 +13,8 @@ Eagle (10.99.0.2) ←→ wg0 VPS (10.99.0.1) ←→ wg1 VPS (10.99.1.1) ←→ K
:51820 :51821
```
> ⚠️ Топология выше — ИСТОРИЧЕСКАЯ, VPS-звено мертво.
Два интерфейса на VPS чтобы избежать hairpin forwarding. FORWARD идёт wg0→wg1, SNAT меняет src Eagle на `10.99.1.1`.
---
@@ -0,0 +1,72 @@
---
status: implemented
tags:
- family
- homeautomation
- zont
- modbus
title: Защита modbus-bridge от гонки с udev (ZONT датчики)
updated: '2026-08-25'
---
# Защита modbus-bridge/mbusd от гонки с udev (ZONT датчики)
> Статус: **внедрено** (2026-08-25, шаги 13). Датчики в ZONT снова отвечают, скрипт и init script на месте.
## Проблема
ZONT (192.168.0.10) — Modbus master на RS-485 шине `ttyZONT`. 485-датчики: Dining=1, Kids=2, Bedroom=3.
Контейнер `modbus-bridge` сниффит их и подставляет виртуальные slaves 101/102/103 → ZONT опрашивает как внешние датчики. Если modbus-bridge не слушает шину → **ZONT показывает датчики «недоступными»**.
**Первопричина (2026-08-25):** гонка загрузки TrueNAS — docker стартовал раньше udev, `/dev/ttyZONT` и `/dev/ttyVent` ещё не существовали → контейнеры `modbus-bridge` (Exit 128) и `mbusd` (Exit 255) упали на старте:
`error gathering device information while adding custom device "/dev/ttyZONT": no such file or directory` (RestartCount=0).
Фикс был: ручной `docker start modbus-bridge mbusd`.
## Почему контейнеры сами НЕ поднялись (RestartCount=0)
`restart: unless-stopped`/`always` ретраит в ДВУХ случаях:
1. Процесс контейнера **стартовал и завершился** с ненулевым кодом → демон ретраит с backoff.
2. **Перезапуск docker daemon** → демон пробует поднять `unless-stopped`/`always` контейнеры.
Наш случай — ТРЕТИЙ, особый: контейнер **вообще не стартовал** — ошибка на этапе монтирования устройства.
- Нет процесса, который «завершился бы» → **restart policy не на что применять**`RestartCount=0`, демон не ретраит.
- После падения (13:24) демон не перезапускался → второго триггера не было.
**Вывод:** отказ на этапе mount устройства НЕ перезапускается restart policy. Авто-подъём гарантирован только скриптом, ждущим устройства.
## Ключевое ограничение (задержка в entrypoint НЕ помогает)
У обоих контейнеров устройство проброшено через `devices: /dev/ttyZONT:/dev/ttyUSB0` / `devices: /dev/ttyVent:/dev/ttyUSB0`.
**Docker при `start` монтирует устройство ДО запуска процесса** — если `<src>` отсутствует на момент старта, контейнер вообще не стартует, и `sleep` внутри entrypoint/CMD **не выполняется**. Поэтому решение — на уровне init скрипта.
## Внедрённое решение
### 1. Скрипт `/mnt/RED_2TB/system/start-modbus.sh` (root, `-rw-r--r--`)
Ожидает появления tty-алиасов от udev (до ~50с), затем запускает контейнеры:
```bash
#!/bin/bash
# Ждём tty-алиасы от udev (макс ~25с), затем стартуем modbus контейнеры.
for i in $(seq 1 50); do
[ -e /dev/ttyZONT ] && [ -e /dev/ttyVent ] && break
sleep 1
done
sleep 2
docker start modbus-bridge mbusd 2>/dev/null
```
### 2. Init script (TrueNAS, id=3)
- **when:** POSTINIT, **type:** COMMAND, **timeout:** 30, **enabled:** true
- **command:** `bash /mnt/RED_2TB/system/start-modbus.sh`
- **comment:** `Start modbus-bridge/mbusd after udev tty aliases`
### Порядок POSTINIT скриптов
| id | command | comment | enabled |
|----|---------|---------|---------|
| 1 | `cp .../99-tty-alias.rules /etc/udev/rules.d/ && udevadm control --reload-rules && udevadm trigger` | Map ttyUSB | ✅ |
| 2 | `bash /mnt/RED_2TB/system/tunnel.sh &` | — | ✅ |
| 3 | `bash /mnt/RED_2TB/system/start-modbus.sh` | Start modbus-bridge/mbusd after udev tty aliases | ✅ |
## Проверка
- `/dev/ttyZONT``ttyUSB1` (CH340), `/dev/ttyVent``ttyUSB0` — симлинки появляются после POSTINIT id=1.
- После reboot: `docker ps` — modbus-bridge и mbusd Up; датчики в ZONT отвечают.
- Просмотр init scripts: `midclt call initshutdownscript.query`
- Откат: `midclt call initshutdownscript.delete <ID>` + удалить скрипт с диска.
## Связанные заметки
- [[family/how-to/home-automation.md]] — карта slave ID, ZONT, датчики
- [[family/how-to/truenas-infrastructure.md]] — docker, modbus-bridge, mbusd, udev rules, init scripts