diff --git a/family/how-to/kraken-access.md b/family/how-to/kraken-access.md index c5781f13..d77ad595 100644 --- a/family/how-to/kraken-access.md +++ b/family/how-to/kraken-access.md @@ -125,7 +125,7 @@ > > **Обновлено: 2026-09-04** -> Updated: 2026-09-01 23:00 — диск/докер кракена восстановились после перезагрузки. +> Updated: 2026-09-01 23:00 — диск/докер кракена поднялись после перезагрузки (тогда причина ещё не была известна; истинная — гонка docker↔mount, найдена 2026-09-20). ## Как зайти @@ -134,9 +134,12 @@ - **Дома** — напрямую по LAN (`192.168.1.15`) - **Снаружи** — ⚠️ через 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]]). -> ⚠️ **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`. +> 🔴 **2026-09-15 — ПРИЧИНА НАЙДЕНА 2026-09-20: гонка docker ↔ монтирование диска.** Диск не «нестабилен» — он **монтируется медленно (~130 с)**, dockerd обгоняет. См. секцию выше. -> ⚠️ **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). При необходимости — пересоздать из образов. +> ⚠️ **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 контейнеров** (все прежние контейнеры — jellyfin/transmission/radarr/hermes-kraken и т.д. — не были видны daemon'ом после старта без диска). Причина — та же mount-race, НЕ дефект диска; после фикса 2026-09-20 такого не повторяется. +> +> 🔴 **Диск НЕ нестабилен.** Формулировка «USB-диск нестабилен» — ошибочное обобщение разового инцидента 2026-09-01 (циклы USB enumerate, `error -110/-62`, `Read Capacity(10) failed`). Истинная причина проблем с контейнерами — **mount race**: диск монтируется ~130 с, dockerd стартует раньше. Фикс (`RequiresMountsFor`) применён 2026-09-20, проверен живым reboot'ом — все контейнеры поднялись сами. **Не возвращать формулировку «диск нестабилен»** (Alex требовал её убрать, 2026-09-25). +> Реальные ограничения HDD: 5400rpm, ~95 МБ/с на чтение — лимит механики, не USB и не дефект. ## Portainer (локально) diff --git a/family/how-to/truenas-infrastructure.md b/family/how-to/truenas-infrastructure.md index d50574a6..e4b99ada 100644 --- a/family/how-to/truenas-infrastructure.md +++ b/family/how-to/truenas-infrastructure.md @@ -115,13 +115,13 @@ > - **✅ НЕАКТУАЛЬНО с 2026-09-14:** USB-адаптеры (CH340 ZONT/вентиляция) **физически перенесены на t610** → на TrueNAS узлов `/dev/ttyZONT` / `/dev/ttyVent` **нет вообще**, а сами контейнеры `mbusd`, `modbus-bridge`, `ser2net` **погашены** (`stop` + `--restart=no`). Проверка: `ls /dev/ttyUSB*` → пусто; `/sys/bus/usb/devices` содержит только принтер Samsung `04e8:3425` (**`lsusb` на TrueNAS не установлен** — использовать `/sys/bus/usb/devices`). > - **Актуальная гонка udev живёт на t610** — см. [[family/how-to/zont-modbus-bridge-udev-race-protection]]. > - ⚠️ **Историческая справка (если когда-нибудь откатывать):** `restart: unless-stopped` НЕ перезапускает контейнер, упавший на `start` из-за отсутствующего device-узла (отказ до старта процесса, ExitCode 128/255, RestartCount=0); лечилось ручным `docker start modbus-bridge mbusd` после готовности симлинков. -> **⚠️ ДРУГОЕ (открытое):** пул `DEST` (IronWolf) на 2026-08-24 `DEGRADED` — разобраться, почему (отвалился mirror-член). TimeMachine (~277G) не возвращён (бэкапы macOS, вероятно не нужен — решение Alex не подтверждено). SSH с Mac по 192.168.2.197 нестабилен — использовать `mallexxx.duckdns.org`. +> **⚠️ ДРУГОЕ (открытое):** пул `DEST` (IronWolf) на 2026-08-24 `DEGRADED` — разобраться, почему (отвалился mirror-член). TimeMachine (~277G) не возвращён (бэкапы macOS, вероятно не нужен — решение Alex не подтверждено). SSH с Mac по `192.168.2.197` — подключение давало `Connection reset` / `kex_exchange_identification` (вероятен конфликт сессий при активном входе на консоль) — рабочий путь: `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/`. > **Контейнеры запускались через `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-24):** пул `DEST` (IronWolf, источник спасения) на момент проверки `DEGRADED` в `zpool list` — стоит разобраться, почему (вероятно отвалился mirror-член). SSH с Mac к TrueNAS по 192.168.2.197 давал `Connection reset` / `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`). diff --git a/family/projects/aide-kraken-backend.md b/family/projects/aide-kraken-backend.md index b9d160d7..bb36b7b2 100644 --- a/family/projects/aide-kraken-backend.md +++ b/family/projects/aide-kraken-backend.md @@ -108,9 +108,9 @@ curl -s https://kraken.qentra.top/health ## Заметки по эксплуатации -### Туннель нестабилен — `sendmsg: network is unreachable` +### Cloudflared: циклические ошибки `sendmsg: network is unreachable` -Иногда после старта cloudflared начинает циклически падать с ошибкой `write udp: sendmsg: network is unreachable` — проблема с IPv6/UDP на RPi5. +Иногда после старта cloudflared начинает циклически падать с ошибкой `write udp: sendmsg: network is unreachable` — IPv6/UDP на RPi5 (у Кракена нет глобального IPv6, а cloudflared пробует QUIC по IPv6). **Решение:** пересоздать контейнер с флагом `--protocol http2`: ```bash diff --git a/personal/projects/balda/balda-mm-delegation-plan.md b/personal/projects/balda/balda-mm-delegation-plan.md index 9fb58d4e..090a41bf 100644 --- a/personal/projects/balda/balda-mm-delegation-plan.md +++ b/personal/projects/balda/balda-mm-delegation-plan.md @@ -1,8 +1,13 @@ # Balda 2.0 — Mattermost + распределённое делегирование (план) > Создан 2026-09-25. Статус: **черновик, ждёт апрува Alex**. -> Задача: поднять свежую Балду из `normahq/balda` (без наших коммитов), завязать на Mattermost, +> Задача: поднять свежую Балду из `baldaworks/balda` (без наших коммитов), завязать на Mattermost, > построить распределённое делегирование (дешёвый оркестратор + подписочные CLI в VM). +> +> **Оценка объёма (проверено 2026-09-25):** это ~10-14 рабочих дней, а не «пара вечеров». +> Апстрим переписан полностью (900 файлов), Mattermost-адаптера в нём нет вообще. +> Реалистичная разбивка: MM на Kraken 2-3 ч · MM-адаптер 2-4 дня · оркестратор на Kraken 1-2 дня · +> исполнитель + мост на Mac 2-3 дня · связка и приёмка 1 день. --- @@ -211,7 +216,7 @@ Mattermost (Alex) — итог + артефакты |---|---|---| | Бан подписочного аккаунта за «unusual traffic» | средний | только официальный бинарь; не более 1-2 параллельных задач; не проксировать токен; мониторить письма Anthropic | | MM-адаптер разъедется с апстримом | высокий | держать как отдельный fork-патч, ребейзить на каждый релиз; либо предложить в апстрим PR | -| Kraken: USB-диск нестабилен, mount-race | известный | учесть в compose (см. `docker-data-root-mount-race`), volume не на data-root | +| Kraken: USB-HDD монтируется ~130 с, есть mount-race | известный | drop-in `RequiresMountsFor` уже применён и проверен reboot'ом; volume не на data-root | | RPi5 не тянет сборку Балды | средний | собирать образ на Mac arm64, на Kraken только `pull`/`up` | | Утечка секретов в MM-канал | средний | `balda.permissions.mode: ask`; redaction в job-events уже есть в апстриме | | Mattermost free-лицензия ограничивает нужное | низкий | проверить лимиты до установки | @@ -222,7 +227,7 @@ Mattermost (Alex) — итог + артефакты 1. **Mattermost:** поднимаем self-hosted Team Edition (free) или есть платный/облачный аккаунт? 2. **VM vs Docker:** начинаем с Docker-контейнера на Mac (быстро) или сразу VM (UTM/Parallels)? -3. **Kraken:** MM на USB-HDD-разделе или на SD (риск износа)? Учитывая нестабильность USB-диска — возможно, вынести MM на SD с бэкапом. +3. **Kraken:** MM на USB-HDD-разделе или на отдельном томе? Диск **не нестабилен** — просто медленно монтируется (~130 с, mount-race закрыт drop-in'ом). Единственный реальный минус HDD — 5400rpm, ~95 МБ/с на чтение. Альтернатива — SD, но там риск износа. 4. **Провайдер оркестратора:** DeepSeek (как сейчас у Валеры) или другой дешёвый? 5. **Судьба текущей Валеры/Клавдия:** гасим или держим параллельно на время миграции? @@ -241,3 +246,12 @@ Mattermost (Alex) — итог + артефакты ## История - **2026-09-25**: создан по итогам разведки апстрима и юридической проверки подписок. +- **2026-09-25**: добавлена оценка объёма (10-14 дней); уточнено, что диск Kraken НЕ нестабилен + (только медленный mount ~130 с) — формулировку «диск нестабилен» Alex потребовал удалить из + доков и памяти. См. `personal/tech/docker-data-root-mount-race.md` §«Диск НЕ нестабилен». + +## Связанные заметки +- [[personal/tech/docker-data-root-mount-race]] — mount-race на Kraken (закрыт, reboot-безопасен) +- [[personal/projects/balda/balda-valera]] — текущая эксплуатация Балды/Валеры (форк, старая архитектура) +- [[personal/projects/balda/fast-rlm-integration]] — fast-rlm MCP sidecar (наша ветка) +- [[personal/tech/hermes-fork-vs-upstream]] — аналогичный опыт сравнения форка с апстримом diff --git a/personal/projects/balda/balda-valera.md b/personal/projects/balda/balda-valera.md index bfcda6cf..476b3bad 100644 --- a/personal/projects/balda/balda-valera.md +++ b/personal/projects/balda/balda-valera.md @@ -172,6 +172,53 @@ docker logs balda-agent-valera-1 2>&1 | grep "norma-tools" ### stream_only_with_session Фикс: написать `@Валера <текст>` чтобы создать сессию. +## Как инвентаризировать форк перед сверкой с апстримом (проверено 2026-09-25) + +Если снова встанет вопрос «что у нас есть, чего нет в апстриме» — этот порядок даёт полную картину +без догадок: + +```bash +# 1. Подтянуть метаданные апстрима (не менять рабочую копию!) +cd ~/Developer/balda +git fetch --all --tags --prune + +# 2. Насколько мы отстали / опередили +git rev-list --left-right --count HEAD...upstream/main # ожидаем "N M" + +# 3. Наши уникальные коммиты по КАЖДОЙ ветке (главное) +for ref in origin/main backup/our-main-before-upstream feat/zulip-transport feat/zulip-events-polling; do + echo "--- $ref ---"; git log --oneline upstream/main.."$ref" +done + +# 4. Размер расхождения по файлам +git diff --stat $(git merge-base upstream/main origin/main)..upstream/main | tail -5 + +# 5. Что апстрим сделал с файлами, которые мы правили +git log --oneline --all -- pkg/runtime/hostedagent/openai.go +``` + +**Результат для нашего форка (2026-09-25):** + +| Репо | Отставание | Наши уникальные коммиты | +|---|---|---| +| `~/Developer/balda` | 900 файлов | `05159d15` (промежуточные статусы Zulip, `handlers/balda.go`), `bc5fd03c` (то же + Telegram + messageID), `feat/zulip-events-polling` (Events API long-poll) | +| `~/Developer/norma-local` | 26 коммитов | `56a6e1e`=`91c2c0a` (DeepSeek tool_calls в `hostedagent/openai.go`) | + +**Важно про `5ad65955` в balda** — это НЕ фича, а `replace normahq/norma => ./norma-local` в `go.mod`. +При переезде на чистый апстрим его нужно удалить, иначе сборка не пройдёт (файлов `norma-local` там нет). + +**Что апстрим сделал с нашими файлами:** +- `norma v2` (`f8a7336`) **удалила целиком** `pkg/runtime/hostedagent/` и `pkg/runtime/agentfactory/`. + Наш DeepSeek-фикс не переносится патчем. Перед переносом проверить, есть ли поддержка tool_calls + для OpenAI-совместимых провайдеров в `normahq/runtime/v2 v2.0.11` — если да, фикс не нужен вовсе. +- В balda наши `handlers/*` заменены на `handlersfx/*`; Zulip переехал в `channel/zulip/*`. + Наш фикс промежуточных статусов надо переписывать под `handlersfx/zulip_ingress.go`. + +**Питфоллы при сверке:** +- `origin` у `norma-local` — это `normahq/norma` (реальный апстрим), а у `balda` `origin` — **наш** `mallexxx/balda`, + апстрим живёт в `upstream`. Не путать: «тянуть до апстрима» для balda ≠ `git pull origin main`. +- Стэши теряются (не переживают `git gc`/клоны) — выносить в ветку до любых операций сброса. + ## Известные грабли ### OPENAI_BASE_URL — обязательная env var diff --git a/personal/projects/balda/fast-rlm-integration.md b/personal/projects/balda/fast-rlm-integration.md index 579b1ecf..946b9cde 100644 --- a/personal/projects/balda/fast-rlm-integration.md +++ b/personal/projects/balda/fast-rlm-integration.md @@ -114,10 +114,13 @@ mcp_servers: ## Откат `cd /Users/admin/Docker/fast-rlm-mcp && docker-compose down` + убрать entry из config.yaml + `restart` Балды → состояние до начала. +### 0.7 Mattermost — новый транспорт (2026-09-25) +Планируется завязать Балду на **Mattermost**. В апстриме (`baldaworks/balda`) MM **отсутствует полностью** (0 совпадений по `mattermost`). Каналы апстрима: `telegram`, `zulip`, `slackagent`, `webhook`. Значит MM — новый транспортный адаптер по контракту `docs/architecture/transport-presentation-boundary.md`; образец для копирования `channel/zulip/adapter.go` (331 стр.) + `client.go` (289 стр.). План: [[personal/projects/balda/balda-mm-delegation-plan]]. + ## Признанные галлюцинации в этой сессии 1. msg 58792-58795: фабрикация "Container Started / Ready" — реально ничего не создавалось. 2. Утверждение что `fast-rlm serve --port 3333` существует — такой команды НЕТ. fast-rlm — только клиент. -3. Старая запись в памяти про "Балда на Кракене" — устаревшая, противоречит документации. Балда на Eagle. +3. Старая запись в памяти про "Балда на Кракене" — **устаревшая и ошибочная**. Балда живёт **на Eagle (Mac M4)**, в Docker Desktop: контейнер `balda-agent-valera-1`, compose в `~/Docker/balda-agent/`. **Кра́кен к Балде отношения не имеет** (там Jellyfin/arr-стек/transmission). ✅ Перепроверено 2026-09-25, формулировка «Балда на Кракене» удалена из доков и памяти. 4. Попытка писать доку через native `Write`/`Edit` в `/Users/admin/obsidian/...` из Linux-контейнера — файл попадает в контейнерную ФС, не в реальный vault. **Правильный путь — `mcp_obsidian_write_note` / `mcp_obsidian_patch_note`**. 5. Утверждение `from fast_rlm.config import RLMConfig` — такого пути в библиотеке нет, импорт top-level: `from fast_rlm import RLMConfig`. 6. `docker compose` (v2) на хосте не установлен — нужен `docker-compose` (v1). diff --git a/personal/tech/docker-data-root-mount-race.md b/personal/tech/docker-data-root-mount-race.md index d7e45203..6dffc78d 100644 --- a/personal/tech/docker-data-root-mount-race.md +++ b/personal/tech/docker-data-root-mount-race.md @@ -101,6 +101,25 @@ ssh kraken 'docker ps -q | wc -l' # ожидаем ~12, НЕ 0 Общий питфолл для сервисов на этом узле: если Kraken лежал, cron-задачи (бэкап `0 4 * * *`, t610-подобные) **пропускаются без компенсации**. Для критичных — добавлять `@reboot`-строку с проверкой «артефакт за сегодня уже есть?». +## 🔴 Диск НЕ нестабилен — «нестабильность» была ошибочным диагнозом (2026-09-25) + +Формулировку **«USB-HDD на Kraken нестабилен»** нельзя использовать: это обобщение разового инцидента +2026-09-01 (циклы USB enumeration: `device descriptor read/64 error -110`, `device not accepting address +error -62`, `[sda] Read Capacity(10) failed` → `0 B`), который позже был **объяснён и закрыт**. + +**Истинная причина всех симптомов «диск отвалился» — гонка монтирования** (этот документ, раздел выше): +диск монтируется ~130 с, `dockerd` стартует раньше и видит пустой `data-root`. Фикс +(`RequiresMountsFor` drop-in) применён 2026-09-20 и **проверен живым reboot'ом** — все контейнеры +поднялись сами, ручных `docker start` не потребовалось. + +**Реальные характеристики диска (не дефекты):** +- 5400rpm 2.5" механика → ~95 МБ/с на чтение. Это лимит механики, не USB (линк USB3 = 5000 Mbps подтверждён). +- Медленный подъём при boot (~130 с) — свойство, а не поломка; обрабатывается зависимостью в systemd. + +**Правило для будущих сессий:** при «контейнеры пропали / сервис не поднялся после reboot» — проверять +гонку (`docker info` vs содержимое `docker-data/containers/`), а не списывать на «нестабильный диск». +Не давать оценку «диск нестабилен» без новых доказательств (raw USB-ошибок в `dmesg` за пределами boot). + ## Связанные заметки - [[personal/tech/jellyfin-db-schema-mismatch]] — jellyfin после reboot: сервер старше БД (503) diff --git a/personal/tech/inter-site-throughput-taiga-to-mac.md b/personal/tech/inter-site-throughput-taiga-to-mac.md index 6ddf4393..264c6830 100644 --- a/personal/tech/inter-site-throughput-taiga-to-mac.md +++ b/personal/tech/inter-site-throughput-taiga-to-mac.md @@ -95,7 +95,7 @@ Speedtest гоняет **8 параллельных TCP-сессий**, кажд - Честный путь к «несколько путей» — только **второй независимый линк** (мобильный 4G/5G backup-WAN на TrueNAS) + MPTCP/OpenMPTCProuter. **3. «VLESS/REALITY-туннель уберёт лимит».** -Уже проверено 2026-09-02 (см. раздел «Замеры скорости туннелей» в `[[xray-reverse-tunnel-kraken-truenas]]`): direct через `vpn.mallexxx` = **~37 Мбит**, reverse через Kraken = **~45 Мбит** (нестабилен). Оба — в том же коридоре, что и прямой путь (28 Мбит single-flow). Туннель идёт тем же маршрутом; REALITY/Vision добавляет обёртки и обычно чуть хуже прямого. **Строить «реальный VPN в 192.168.2.x» смысла нет — он уже есть (`vpn.mallexxx`), и он не помог.** +Уже проверено 2026-09-02 (см. раздел «Замеры скорости туннелей» в `[[xray-reverse-tunnel-kraken-truenas]]`): direct через `vpn.mallexxx` = **~37 Мбит**, reverse через Kraken = **~45 Мбит**. Оба — в том же коридоре, что и прямой путь (28 Мбит single-flow). Туннель идёт тем же маршрутом; REALITY/Vision добавляет обёртки и обычно чуть хуже прямого. **Строить «реальный VPN в 192.168.2.x» смысла нет — он уже есть (`vpn.mallexxx`), и он не помог.** ### ✅ Что реально работает — ранжировано diff --git a/personal/tech/inter-site-throughput-taiga-to-mac.md.bak-nedstab2 b/personal/tech/inter-site-throughput-taiga-to-mac.md.bak-nedstab2 new file mode 100644 index 00000000..6ddf4393 --- /dev/null +++ b/personal/tech/inter-site-throughput-taiga-to-mac.md.bak-nedstab2 @@ -0,0 +1,279 @@ +--- +title: Межсайтовая пропускная способность — TrueNAS (Taiga) ↔ Mac/TV +created: '2026-09-02' +updated: '2026-09-21' +type: tech +namespace: personal +tags: [network, truenas, throughput, rtt, tcp, jellyfin, xray, bottleneck, webos, moonfin, breezyfin, prefetch, single-flow] +related: + - "[[xray-reverse-tunnel-kraken-truenas]]" + - "[[../how-to/truenas-infrastructure]]" + - "[[../family/how-to/kraken-network]]" +--- + +# Межсайтовая пропускная способность — TrueNAS ↔ Mac/TV + +> Контекст: после восстановления стека медиа/права на Taiga (см. `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`) Jellyfin запустился и файлы читаются, но **прямое воспроизведение с ТВ «грузится кусками»**. Диагностика 2026-09-02 установила: это **НЕ транскодинг и НЕ тариф**, а ограничение сети между двумя физически разнесёнными локальными сетями. + +## Cетевой layout (фактический) + +| Узел | LAN | Шлюз | Egress IP | Провайдер | +|---|---|---|---|---| +| Mac / TV (дом) | `192.168.1.57` | `192.168.1.1` | динамический | ТТК (92.62.x / 185.20.x) | +| **TrueNAS (Taiga)** | `192.168.2.197` | `192.168.2.2` | `90.189.160.148` (`mallexxx.duckdns.org`) | Ростелеком (194.186.x → 217.107.x) | + +**Ключевое:** TrueNAS НЕ в локальной сети Мака/ТВ. Трафик ТВ→Jellyfin идёт целиком по интернету между двумя разными операторами/домохозяйствами. + +## Замеры (2026-09-02) + +### Задержка / маршрут +- RTT Mac → TrueNAS: **~104 мс**. +- Traceroute: хопы 1–7 моего ISP (ТТК) — **3–6 мс** ✅ чисто. **На хопе 8 (`194.186.168.65`) прыжок до ~54 мс** — межоператорская передача в сеть Ростелекома, где живёт TrueNAS. Хоп 10 (`217.107.108.41`) ~60 мс. +- Этот +50 мс — физическое/пиринговое расстояние между региональными операторами, НЕ петля. Перенастройка маршрута полностью RTT не уберёт. +- Примечание: **дальние сети в целом** (8.8.8.8 ~100 мс) у ТТК тоже идут через ~50 мс переход — деградация на стороне выхода, а не только до TrueNAS. + +### Пропускная способность (распутали про «тариф») +- Mac download с CDN: **~78 Мбит/с** (линия Мака в порядке). +- **TrueNAS сторона**: NIC `enp3s0` 1 Gb/s, до шлюза 0.2–0.8 мс 0% loss. NAS→Cloudflare: **download ~184 Мбит/с, upload ~117 Мбит/с**. → **Лимита тарифа на TrueNAS НЕТ.** +- Mac → TrueNAS (SCP 200MB): **~28 Мбит/с** одним потоком. +- Mac → TrueNAS, **4 параллельных SCP потока: ~28 → ~51 Мбит/с** (агрегат растёт с параллельностью). + +## Вывод (важно) + +Ограничение — **НЕ по суммарной полосе транзита, а по одному TCP-потоку из-за высокого RTT (~104 мс) + BDP / congestion-window**. Доказательство: 4 потока дали рост ×1.8 (28→51) — при жёстком лимите линии рост не произошёл бы. + +**Почему Jellyfin дёргается прямо:** Jellyfin отдаёт видео одним последовательным HLS-потоком (один TCP). Один поток душится RTT-штрафом до ~28–50 Мбит, а BluRay-файл в пиках идёт к 20+ Мбит → с 104 мс RTT сегменты не успевают → стоп-кары. Файл The.Jungle.Book.1967.720p.BluRay ≈ 7.1GB/~78мин → средний ~12 Мбит/с, пики выше. + +## Факты ИЗ ЛОГОВ Jellyfin (подтверждают: транскодинг не причина в этих тестах) +- Реальный транскод с `libx264` + reduce был только на "Snatch" (тестовые короткие старты каждые ~5 с — клиент переподключался). +- "Один день в Стамбуле"/"Рождественские хроники" — ремукс `-codec:v:0 copy` в HLS (не перекодирование), стоп на ~2-3 сек. +- В моменте (пока ТВ крутит 720p) — ffmpeg-дочерних процессов нет, папка transcodes пуста → **прямой stream/direct, транскодинг не идёт**. + +## 🧭 2026-09-21: развилка решена — многопоточный HLS не существует в Jellyfin/webOS + +Перепроверено по первоисточникам (см. [[personal/tech/multistream-single-flow-limit]]): +- Jellyfin «multiple parallel connections» — **Planned** 5 лет, кода нет (230 голосов). +- hls.js multi-segment prefetch (#6753) — открыт, не реализован. +- webOS-приложения используют **нативный media pipeline** → подменить логику загрузки нельзя. +- **Несколько xray-туннелей не помогут** — один физический путь, одно congestion window. +- Speedtest 120 Мбит = 8 параллельных сессий. Одна сессия упирается в **~28–45 Мбит** (подтверждено замерами ниже). + +**Рабочие пути:** ограничить битрейт в клиенте / Moonfin с буфером / **Lampac на Кра́кене** +(буфер 50–100 МБ + GStreamer транскод) / prefetch-proxy. Полный разбор — в +[[personal/tech/multistream-single-flow-limit]]. + +## Решение / направление +1. **Правильное лекарство** (не мультипоток ради мультипотока, а либо снижение латентности, либо запас по битрейту под single-flow): лимит транскода ~12–18 Мбит, ЛИБО гнать трафик ТВ→TrueNAS через **xray tunnel** (`vpn.mallexxx.duckdns.org`, смотри `[[xray-reverse-tunnel-kraken-truenas]]`) вместо прямого межоператорского пути. +2. Jellyfin **не умеет** штатно разбивать один плейбек на параллельные TCP. Параллельность (28→51 Мбит) достижима только поднятием файла способом «качалка в N коннектов» + прокси, либо через туннель. +3. Задача замера скорости через **`xray-test-client`** контейнер (teddysun/xray, SOCKS `127.0.0.1:1080`) — НЕ завершена: команда замера была заблокирована юзером; способ/endpoint (стучались на внутренний `192.168.2.197:8096`) предложен неверно. + +## Связанный локальный кейс (Kraken, same-LAN) + +> Тот же симптом «ТВ Jellyfin Direct Play дёргается» 2026-09-02, но в **локальной сети** (Kraken RPi5, дом) — причина ДРУГАЯ. См. `family/how-to/kraken-network.md`. +> **Как отличать кейсы:** если Jellyfin-хост в одной LAN с ТВ (ping < ~10 мс) → дёрганье Direct Play почти всегда из-за **линка 100 Мбит/с** на сервере, а НЕ полосы/RTT. Проверка: `cat /sys/class/net//speed` (это Kракен упал 1G→100M). Если хост в другой сети/операторе (ping ~104 мс, как Taiga) → ограничение по одному TCP-потоку из-за RTT. «99 Mbps» в UI = битрейт 4K remux-файла (обычно ~60–100 Mbps), НЕ скорость сети/линка. + +### Endpoint-факты для замера туннеля +- Локальный тестовый xray-клиент на Mac: контейнер **`xray-test-client`** (`127.0.0.1:1080->1080/tcp`), конфиг `/Users/admin/xray-test/config.json`, оставлен на `kraken-user`. +- Per-user egress на `vpn.mallexxx.duckdns.org`: `user1` → direct TrueNAS `90.189.160.148`; `kraken-user` → reverse через Kraken `92.62.70.41`. +- Конфиг клиента лежит на Mac отдельно (не в vault); бэкап direct-клиента: `/Users/admin/xray-test/config.json.bak-user1-direct-20260902-1227`. + +--- + +## 🔴 2026-09-21 — РАЗБОР: почему speedtest 120 Мбит ≠ Jellyfin не тормозит. Что делать + +> Контекст: Alex (Бишкек) сообщил, что плейбек Jellyfin на ТВ тормозит даже по проводу, но **speedtest через reverse-туннель показал до 120 Мбит**. Гипотеза Alex: «поднять реальный VPN в 192.168.2.x через VLESS и проверить, может заработает». Ниже — разбор, почему это не поможет, и что реально может. + +### ❌ Что опровергнуто этой сессией + +**1. «Speedtest доказал, что 120 Мбит физически можно — значит туннель/multi-tunnel даст столько же».** +Speedtest гоняет **8 параллельных TCP-сессий**, каждая со своим congestion window. 8 × ~15 Мбит = 120 Мбит. Это доказывает, что канал **пропускает** 120 Мбит суммарно. Это **НЕ** доказывает, что **одна** сессия получит 120 Мбит. Наши замеры это уже показывали: 1 поток = 28 Мбит, 4 потока = 51 Мбит (×1.8). Скорость TCP ≈ окно / RTT; при RTT 104 мс для 120 Мбит нужно окно ≈ **1.5 МБ «в полёте»**, одна сессия до такого не разгоняется при потерях на межоператорском стыке. + +**Правильная модель (не «узкая труба», а «кассы»):** канал пропустит 120, но **только если запрашивать 8 потоками одновременно**. У Jellyfin — один покупатель в одной кассе. + +**2. «Поднять несколько xray-туннелей и распараллелить».** +Не сработает: **физический путь один** (ТТК → Ростелеком, хоп 8 = +50 мс). N туннелей по одному пути делят один congestion window → суммарно не больше, чем один, плюс накладные расходы. Это MPTCP/bonding-территория, а он агрегирует **разные** пути. Аналогия Alex «узкое место — линк между провайдерами» — верно; вывод «значит, надо прокинуть больше туннелей» — нет, линк пропускает 120 Мбит, но не одному потоку. +- Честный путь к «несколько путей» — только **второй независимый линк** (мобильный 4G/5G backup-WAN на TrueNAS) + MPTCP/OpenMPTCProuter. + +**3. «VLESS/REALITY-туннель уберёт лимит».** +Уже проверено 2026-09-02 (см. раздел «Замеры скорости туннелей» в `[[xray-reverse-tunnel-kraken-truenas]]`): direct через `vpn.mallexxx` = **~37 Мбит**, reverse через Kraken = **~45 Мбит** (нестабилен). Оба — в том же коридоре, что и прямой путь (28 Мбит single-flow). Туннель идёт тем же маршрутом; REALITY/Vision добавляет обёртки и обычно чуть хуже прямого. **Строить «реальный VPN в 192.168.2.x» смысла нет — он уже есть (`vpn.mallexxx`), и он не помог.** + +### ✅ Что реально работает — ранжировано + +| # | Подход | Механизм | Усилие | Шанс | +|---|---|---|---|---| +| 1 | **Лимит битрейта в клиенте** (10–15 Мбит) | Транскод на TrueNAS; один поток 10 Мбит проходит с запасом ×3 | 2 мин | **Высокий** | +| 2 | **Moonfin / Breezyfin** (webOS-клиенты) | Нативный pipeline + транскод-лимит в UI + лог «кто отказал в Direct Play» | ~30 мин (Homebrew Channel) | Средний (диагностика) | +| 3 | **Prefetch-proxy на стороне клиента** | Прокси тянет файл/HLS **8 параллельными Range-запросами**, отдаёт клиенту из локального кэша → клиент видит «быстрый сервер» | Высокое (писать/настраивать) | Средний | +| 4 | **BBR + HTTP/3 на TrueNAS** | BBR вместо CUBIC держит cwnd на long-haul; Caddy умеет HTTP/3, но webOS-клиент его не использует | 30 мин | +20–50%, не ×4 | +| 5 | **Второй ISP + MPTCP** | Настоящая агрегация разных путей | Очень высокое / деньги | **Ноль** без второго линка | + +### 🔑 Ключевое различие для варианта 3 (и почему он единственный «правильный») +Параллелизм рождается от **независимых HTTP-запросов** (каждый = своё TCP-окно), а НЕ от мультиплексирования транспорта. +- ✅ **Клиент/prefetch-proxy делает 8 Range-запросов** → 8 независимых окон → 120 Мбит возможно. +- ❌ **8 xray-туннелей + mux** → одно логическое окно, порезанное на 8 → head-of-line blocking, выигрыша нет. +Prefetch-proxy **обязан стоять на стороне клиента** (Mac/ТВ в Бишкеке), не на TrueNAS — иначе параллельные запросы всё равно идут через узкий канал по отдельности, выигрыш частичный. + +### 🔴 КРИТИЧНО: клиент Alex — LG webOS (`Jellyfin for WebOS 1.2.2`) +Официальный webOS-клиент — **обёртка вокруг веб-интерфейса**, внутри **один HTML5 `