# FlareSolverr на Тайге + обход блокировок индексеров > 🔴 **СОСТОЯНИЕ 2026-09-29 (ФИНАЛ СЕССИИ): инфраструктура чиста, НО поиск через CF-индексеры НЕ работает.** > **Prowlarr** — `IndexerStatus` **очищен через SQL** (было `EscalationLevel=9`, сутки), `health` → `[]`, > `indexerstatus` → `[]`, **`caps` всех 6 → 200**. Это максимум, что даёт инфраструктура. > **НО** реальный поиск: `total=79`, отдали **только NoNaMe (47) и RuTor (32)**; > RuTracker/Kinozal/Kinozal(M) → **429** через минуты после очистки, в логе > `FlareSolverrException: Empty cookies returned by FlareSolverr` (`FlareSolverr.cs:68`). > 🔴 **КОРЕНЬ (найден в этой сессии): у сессии нет куки `bb_data`** — только `cf_clearance` + `bb_guid`. > Это значит **логин RuTracker не выполняется**, а не «CF блокирует». Детали — раздел ниже. > 🔴🔴 **СВЕРКА С КРА́КЕНОМ (2026-09-29): «как на Кра́кене» = ТОЖЕ СЛОМАНО.** Alex спросил про > капча-солвер на Кра́кене — **его там НЕТ**, только FlareSolverr. Карантин на Кра́кене > **идентичен Тайге**: RuTracker/Kinozal/Kinozal(M) `EscalationLevel=9`, `DisabledTill=2026-09-27`. > Обе площадки имеют один и тот же незакрытый дефект. См. раздел «СВЕРКА С КРА́КЕНОМ». > 🔴🔴 **РЕШЕНИЕ НАЙДЕНО (2026-09-29): свой образ `flaresolverr-vnc` + noVNC.** > Капча-солвер невозможен (`CAPTCHA_SOLVER` официально non-functional), cookie в Prowlarr > не вписать → единственный путь: **ручной вход в Chrome внутри FS**. Собран образ > `flaresolverr-vnc:latest` (Xvfb+fluxbox+x11vnc+noVNC), профиль Chromium на persistent > volume, порт `6080` для noVNC. **Развёрнуто и работает.** > 🔴 **ДОСТУП ОТКРЫТ (2026-09-29): `https://vnc.mallexxx.duckdns.org/vnc.html`**, > логин `admin` / пароль `vnc-taiga`, роут в Caddy (TLS выпущен, **проверен → 200**). > Порт `6080` наружу НЕ проброшен — доступ через Caddy, роутер не нужен. > **Alex вошёл и видит Chrome** (проверено). Осталась его часть: логин + капча RuTracker, > затем проверка выживания cookies. См. раздел «РЕШЕНИЕ». > **Radarr/Sonarr/Lidarr** — health чистый; warning-и про индексе́ры живут в БД **Prowlarr**, не у них. > **Lidarr** — SkyHook работает, `musicCategory=lidarr` применён, поиск релизов отдаёт **43** FLAC. > ⚠️ Открыто: **RuTracker** — автоматический логин невозможен (нужен Alex, см. ниже); > **RuTor** — `no results in the configured categories` (на стороне трекера). > Контейнер `flaresolverr` (v3.5.2), порт `8191`, сеть `media_net`, `shm_size: 1gb`, > `LOG_LEVEL=warning`, **`PROXY_URL=socks5://vless-proxy:1080`**. > Compose — `/mnt/RED_2TB/docker/arr/docker-compose.yml` (6-й сервис). > Бэкапы: `~truenas_admin/docker-compose.yml.bak-20260928-flaresolverr`, > `~/backup-indexers-20260928-flaresolverr.json`, **`~/prowlarr.db.bak-20260928-032611`** (перед SQL-очисткой). > Связка: [[personal/plans/flaresolverr-taiga-deploy]], [[personal/plans/lidarr-taiga-and-indexer-unblock]], > [[family/projects/media-toolbox-taiga]], [[personal/tech/prowlarr-flaresolverr-cloudflare]], > [[family/how-to/arr-stack-kraken]]. ## ✅ РЕЗУЛЬТАТ (поиск «matrix» через `/api/v1/search`, замер 28 сен до капчи) ``` TOTAL 256 RuTor 100 ← был живой RuTracker 50 ← ВПЕРВЫЕ с 2026-05-20 NoNaMe 50 ← ВПЕРВЫЕ Kinozal 50 ← ВПЕРВЫЕ Byrutor 6 ``` ⚠️ **Это исторический замер, не текущее состояние.** На момент ~15:20 RuTracker ещё логинился и давал 50 результатов. Позже трекер стал отдавать **капчу** (см. раздел про RuTracker), и RuTracker/Kinozal уходят в карантин волнами → в поиске сейчас меньше трекеров. Смотреть `indexerstatus` перед тем, как повторять этот замер. `GET /api/v1/health` → `[]`, `GET /api/v1/indexerstatus` → `[]` **на момент замера.** Было 3/6, стало 6/6 (по выдаче — 5 трекеров; Kinozal (M) — зеркало Kinozal с magnet-приоритетом, в общую выдачу дублируется). ## 🔑 ГЛАВНОЕ ОТКРЫТИЕ: FS-СЕССИЯ НЕ НАСЛЕДУЕТ `PROXY_URL` Самый неочевидный пункт всей задачи. Симптом был **ложный**: Prowlarr писал `blocked by CloudFlare Protection`, а лог FS — мгновенную ошибку за **7 секунд** (не таймаут!). **Причина:** `PROXY_URL` (глобальный прокси) применяется к Chrome **в момент создания сессии**. Сессия, созданная **до** появления `PROXY_URL`, остаётся **без прокси** навсегда — в ней Chrome получает `net::ERR_NAME_NOT_RESOLVED` (DNS-блок!). Prowlarr шлёт запросы с параметром `session`, и global-прокси её не перебивает. Пруф — прямой вызов с сессией, созданной ДО прокси: ``` request.get kinozal + session:"prowlarr" (старая) → {"status":"error","message":"Error solving the challenge. Message: unknown error: net::ERR_NAME_NOT_RESOLVED (chrome=152.0.7977.82)"} ``` Тот же запрос с сессией, созданной **ПОСЛЕ** `PROXY_URL` → `Challenge solved! 200`. **Имя сессии Prowlarr — `prowlarr`** (обнаружено через `sessions.list`). **Фикс:** удалить устаревшую сессию — `sessions.destroy`; Prowlarr пересоздаёт её сам при следующем запросе, уже с рабочим `PROXY_URL`. ```bash docker exec prowlarr sh -c 'curl -s -X POST http://flaresolverr:8191/v1 \ -H "Content-Type: application/json" \ -d "{\"cmd\":\"sessions.destroy\",\"session\":\"prowlarr\"}"' ``` > ⚠️ **Правило на будущее:** после ЛЮБОЙ правки `PROXY_URL` в compose **убить сессию > `prowlarr`**, иначе старые сессии продолжат ходить без прокси и индексера будут > «blocked by CloudFlare» при живом FS. > ✅ При обычном перезапуске FS (watchtower/reboot) проблема НЕ повторится — сессия > создастся заново уже с `PROXY_URL`. ## 🔑 ВТОРОЕ ОТКРЫТИЕ: FlareSolverr сам идёт через прокси (`PROXY_URL`) На Кра́кене два механизма независимы: Cloudflare лечится FlareSolverr, DNS-блока нет. **На Тайге блоков ДВА (DNS + Cloudflare), и FlareSolverr обязан ходить через `vless-proxy`** — иначе он сам получит NXDOMAIN и не поможет. **Решение:** глобальная env-переменная FlareSolverr **`PROXY_URL=socks5://vless-proxy:1080`**. > ⚠️ Имя переменной — **`PROXY_URL`**, НЕ `HTTP_PROXY`/`HTTPS_PROXY` (проверено по DeepWiki > FlareSolverr §4.2 «Proxy Configuration»). Формат **со схемой обязателен** > (`socks5://host:port`); без схемы `urllib.parse` не разберёт. > Приоритет: request > session > global. `PROXY_USERNAME`/`PROXY_PASSWORD` не нужны — > `vless-proxy` без авторизации. **Почему срабатывает именно global:** Prowlarr обращается к FS с параметром `session`, а при наличии сессии request-прокси **игнорируется** → применяется global (`PROXY_URL`). ## ⚠️ ПИТФОЛЛ: `requestTimeout` = 60 с МАЛО, поднят до 180 Дефолтный `requestTimeout` прокси-элемента FlareSolverr в Prowlarr = **60 с**. Решение CF-челленджа на `/forum/login.php` RuTracker и на kinozal занимает **80–100 с** → `Error solving the challenge. Timeout after 60.0 seconds` в логе FS, Prowlarr отдаёт `500 InternalServerError [POST] at http://flaresolverr:8191/v1`, в UI — «blocked by CloudFlare». **Фикс:** `requestTimeout` = **180** (PUT `/api/v1/indexerproxy/2`). Проверка: `docker logs flaresolverr` → `Challenge solved!`, а не `Timeout`. > Замеры времени челленджа (kinozal.me/browse.php через FS): **78 с** холодный, > **20 с** прогретый (CF-клэренс привязан к IP прокси), POST-логин — **97 с**. ## ⚠️ ПИТФОЛЛ: параллельный `testall` устраивает гонку за Chrome Prowlarr тестирует все индексеры **одновременно**, а у FlareSolverr **один** Chrome. При `testall` челленджи сыпятся таймаутами; если тестировать **по одному** (sequential) — проходят. **Не верить результату параллельного `testall`** — гонять по одному. Дополнительно: `curl` без `--max-time` виснет, если FS не отвечает — всегда ставить лимит. ## ⚠️ ПИТФОЛЛ: тег нужен И на прокси, И на индексере — и на ОБА прокси Индексерам за DNS-блоком нужны **два** прокси-элемента и **два** тега: | Прокси | id | Тег | Назначение | |---|---|---|---| | `vless-socks5` | 1 | `proxy` (id=1) | обход **DNS-блока** провайдера | | `flaresolverr` | 2 | `flaresolverr` (id=2) | обход **Cloudflare** | Значит на индексер вешаются **оба** тега: `tags=[1,2]`. Один прокси не закрывает оба блока. Фактически навешено: id 1, 4, 5, 6 → `[1,2]`; id 2, 3 → `[1]` (RuTor/Byrutor живут на одном прокси). ## ⚠️ ПИТФОЛЛ: PUT `/api/v1/indexer/N` → 400, нужен `?forceSave=true` Prowlarr при PUT **сразу тестирует** индексер. Если FS в этот момент не прошёл (таймаут/гонка) — `HTTP 400` с `validationFailures`. Именно так «потерялись» теги после первого PUT: они откатились к `[1]`. **Рабочий путь:** `PUT /api/v1/indexer/N?forceSave=true` → **202** (сохраняет, тест пропускает). Тест гонять отдельно, по одному. То же для `/indexerproxy/N`. ## ⚠️ ПИТФОЛЛ: `Auth Failed` ≠ неверный пароль `RuTracker Auth Failed` в `indexer/testall` Prowlarr **не доказывает** неверный пароль. Проверять логин отдельным `request.post` на `/forum/login.php` через FS и смотреть **`final_url` + длину HTML**: залогиненная страница форума ≈ **250 KB** и форма `login_username` в ней ВСЁ РАВНО присутствует (шаблон) — по подстроке диагноз ставить нельзя. Скрипт-проверка: `/tmp/rt_login.py` (см. [[personal/tech/flaresolverr-taiga]]). ## ⚠️ ПИТФОЛЛ: health Radarr/Sonarr кэшируется — нужен restart `RemotePathMappingCheck` (и подобные) в health Radarr/Sonarr **кэшируется**: создание недостающих каталогов `/storage/Downloads/{radarr,sonarr}` ошибку **не снимает**. Нужен `docker restart radarr sonarr`, чтобы проверка прогналась заново. `PUT` через API кеш health тоже не сбрасывает. ## Практические замечания - **Логи FS пусты при `LOG_LEVEL=warning`** — это правильно: на `info` он пишет `login_password` трекеров в plaintext. Не поднимать уровень ради «посмотреть». - `sessions.create` → `ok`, `version 3.5.2` — быстрый smoke-тест живости FS. - Прямая проверка FS из prowlarr: ```bash docker exec prowlarr sh -c 'curl -s --max-time 150 -X POST http://flaresolverr:8191/v1 \ -H "Content-Type: application/json" \ -d "{\"cmd\":\"request.get\",\"url\":\"https://rutracker.org/forum/login.php\",\"maxTimeout\":130000}"' # ожидается: {"status":"ok","message":"Challenge solved!", ...} ``` - `sleep 35` после старта контейнера — Chrome поднимается ~30 с; раньше этого `:8191` может не отвечать. - `shm_size` и `sysctls` — **в блок сервиса** compose, не в `environment`. - **`ERR_NAME_NOT_RESOLVED` в ответе FS = сессия без прокси** (см. открытие выше), а не «FS сломан». - **Ключ API в `-H` ломается многоуровневым экранированием** (ssh → docker → sh). Рабочий приём: `printf "X-Api-Key: " > /tmp/h.txt` внутри контейнера, затем `curl -H @/tmp/h.txt`. - **`python3` внутри контейнера prowlarr НЕТ** — разбирать JSON хостовым `python3` (на Тайге есть `python3`, нет `curl` и `sqlite3`). ## Состояние индексеров после деплоя (2026-09-28, финал) | id | Индексер | Теги | Статус | |---|---|---|---| | 1 | RuTracker | `[1,2]` | ✅ valid (был красный с 2026-05-20) | | 2 | RuTor | `[1]` | ✅ valid | | 3 | Byrutor | `[1]` | ✅ valid | | 4 | NoNaMe Club | `[1,2]` | ✅ valid | | 5 | Kinozal | `[1,2]` | ✅ valid | | 6 | Kinozal (M) | `[1,2]` | ✅ valid | ## ✅ ЗАКРЫТО: Kinozal — «blocked by CloudFlare» при живом FS Самая долгая часть задачи. Симптом маскировался под таймаут, причина оказалась другой. **Что замерено (история диагностики):** - Прямой socks5 к `kinozal.me/browse.php` → **403 Just a moment** за **0.9 с** (CF реален). - FS `request.get` kinozal → `Challenge solved! 200`: **78 с** холодный, **20 с** прогретый. - FS `request.post` kinozal/takelogin.php → `Challenge solved! 200`, **97 с**. - Prowlarr: `blocked by CloudFlare Protection`, в логе FS — падение за **7 с** (не таймаут!). **Ложный след:** `HTTP request failed: [500:InternalServerError] [POST] at http://flaresolverr:8191/v1` и `Error solving the challenge. Timeout after 60/120/180 seconds` — выглядело как «челлендж дольше таймаута». Поднятие `requestTimeout` 60→120→180 **не помогло**. **Настоящая причина:** FS-сессия без прокси (см. главное открытие выше). Сессия `prowlarr`, созданная до появления `PROXY_URL`, падала с `ERR_NAME_NOT_RESOLVED` за 7 с, Prowlarr интерпретировал это как «CF блокирует» и уходил в retry → карантин. **Фикс:** `sessions.destroy` сессии `prowlarr` → пересоздана с прокси → Kinozal (5) и Kinozal (M) (6) прошли с первого раза (`{}`). **Что исключено (не тратить время повторно):** ресурсы FS в норме (710 MB / 21 GB, shm 1 GB, CPU 0.68%); канал прокси нормальный (kinozal через socks5 **0.6 с**, 908 KB/s); внутренний таймаут Prowlarr в `config.xml` не настраивается. ## Compose-сервис (вставлен в `/mnt/RED_2TB/docker/arr/docker-compose.yml`) ```yaml flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:latest container_name: flaresolverr restart: unless-stopped environment: - LOG_LEVEL=warning # НЕ info — info пишет пароли трекеров в plaintext - BROWSER_TIMEOUT=60000 - TZ=Asia/Novosibirsk - PROXY_URL=socks5://vless-proxy:1080 ports: - "8191:8191" networks: - media_net shm_size: 1gb # Кра́кен: 64 MB убивал Chrome sysctls: - net.ipv6.conf.all.disable_ipv6=1 ``` Порядок деплоя: бэкап compose → правка **локально** (не sed на сервере) → `scp` → `cp` → `cd /mnt/RED_2TB/docker/arr && docker compose up -d flaresolverr`. ⚠️ `docker compose up -d` **только из своего каталога**, иначе name-conflict (грабля Кра́кена). > ⚠️ **Swap на Тайге = 0** (`/proc/swaps` пуст). На Кра́кене мёртвый swap + 64 MB `/dev/shm` > убили Chrome в crash-loop. Здесь обошлось без swap: RAM 21 GB, доступно 5.6 GB, FS держит > 710 MB, CPU 0.68%. **Swap не трогали** — не нужен при таком объёме памяти. ## История - **2026-09-26** — разведка под Lidarr. Найдено: DNS-блок провайдера (NXDOMAIN на 4 трекера), `vless-proxy` не в `media_net`. Прокси-маршрут для Prowlarr починен в тот же день (3/6 индексеров). Остаток — Cloudflare на RuTracker/Kinozal. [[personal/plans/lidarr-taiga-and-indexer-unblock]] - **2026-09-28** — **FlareSolverr развёрнут** по задаче Alex «ставь как на Кра́кене + прокси-контейнер». Решено последовательно: (1) FS сам ходит через `vless-proxy` (`PROXY_URL`) — двойной обход DNS+CF; (2) `requestTimeout` 60→180; (3) теги `[1,2]` на все CF-индексеры; (4) **`sessions.destroy` сессии `prowlarr`** — последний блокер (сессия была создана до `PROXY_URL`). Итог: **6/6 индексеров, health `[]`, поиск 256 результатов.** RuTracker впервые `valid` за всё время существования стека (с 2026-05-20). - **2026-09-28 (поздний вечер)** — **добивка Radarr/Sonarr/Lidarr до чистого health.** Закрыто: `docker restart radarr sonarr` (+`lidarr`) → `RemotePathMappingCheck` ушла, health Radarr/Sonarr → `[]`. Снят карантин Kinozal/Kinozal(M) в Prowlarr тестом **полным объектом** (`{"id":N}` → 400 всегда). Новые питфоллы: **`test` требует полный объект**; **429 на `caps` = карантин Prowlarr → каскад во все arr**; **`proxyBypassFilter` Lidarr без `prowlarr`** → таймауты к Prowlarr из-за собственного прокси-конфига. Остаток: RuTor — несовпадение категорий (не блок), и 1 warning в Lidarr до перезапуска с новым bypass. ## 🔴 ОТКРЫТО 2026-09-28 (финал сессии): RuTracker отдаёт КАПЧУ на логин Хронология одного вечера — пароль один и тот же, результат разный: | Время | Проверка | `len` HTML | Итог | |---|---|---|---| | ~15:20 | `request.post /forum/login.php` | **251 792** | ✅ залогинен | | ~16:40 | `request.post /forum/login.php` | **13 335** | ❌ форма вернулась | Пароль в Prowlarr при этом **не менялся** (сверено: `username`/`password` из `/api/v1/indexer/1` совпадают с локальной копией). Причина смены результата — **трекер выдаёт капчу**: в HTML найден блок `cap_code` + метка `Код:`. Пишется это в лог Prowlarr как `NzbDrone.Core.Indexers.Exceptions.IndexerAuthException: RuTracker Auth Failed` и `Invalid Credentials for RuTracker [https://rutracker.org/forum/tracker.php?nm=...&f=...]`. 🔴 **Правильный признак «залогинен/нет» — РАЗМЕР страницы, а не подстрока.** - **~250 KB** = залогиненный форум. - **~13 KB** = форма логина (вернулась). Подстрока `login_username` присутствует **в обоих** случаях (HTML-шаблон + скрытая форма быстрого входа) — по ней диагноз ставить НЕЛЬЗЯ, это дало ложное «Auth Failed» двумя диагнозами подряд. **Обходного пути в Prowlarr нет:** форма индексера RuTracker принимает только `username`/`password` — поля для cookie-сессии (`bb_data`) не существует, вписать живую сессию из браузера нельзя. **Что делать (нужен Alex):** зайти на `rutracker.org` браузером с **этого же** исходящего IP (через тот же `vless-proxy`), ввести логин+пароль и **пройти капчу один раз**. После успешного входа капча обычно снимается. Если не поможет — сменить пароль на трекере и вписать новый в Prowlarr (`Indexers → RuTracker`), либо поискать у RuTracker обход капчи (в Cardigann-определении поддержки нет). ⚠️ Следствие: **RuTracker в карантине** в Prowlarr, поэтому его `caps` отдаёт **429** → каскад `429:TooManyRequests` в Radarr/Sonarr/Lidarr. Это нормальное поведение, лечится только восстановлением логина. См. питфолл про `429` ниже. ## 🔴🔴 ИТОГОВЫЙ КОРЕНЬ (2026-09-29): логин RuTracker НЕ ВЫПОЛНЯЕТСЯ — нет куки `bb_data` ⚠️ **Раздел ниже («капча привязана к сессии») оказался ЛОЖНЫМ СЛЕДОМ.** Он оставлен для истории диагностики, но вывод в нём неверен — читать этот раздел вместо него. **Что измерено в финале (одна серия замеров, `/tmp/fs_persist_session.sh`):** ``` сессия rt-login-test: len=254 673 (форум) cookies=0 сессия prowlarr: len=99 735 (НЕ форма!) cookies=2 ← [cf_clearance, bb_guid] новая сессия + POST: len=12 346 (форма) cookies=2 ← [bb_guid, cf_clearance] новая сессия + GET→POST: len=12 350 (форма) cookies=2 ``` 🔴 **Ключевое: в cookies НЕТ `bb_data`.** `bb_data` — кука авторизации RuTracker. Есть `cf_clearance` (CF пропускает челлендж) и `bb_guid` (гость), но `bb_data` отсутствует → **логин не состоялся**, страница — форум для неавторизованного. **Что видит Prowlarr (точная строка из лога, главная улика сессии):** ``` NzbDrone.Core.IndexerProxies.FlareSolverr.FlareSolverrException: "Empty cookies returned by FlareSolverr." at NzbDrone.Core.IndexerProxies.FlareSolverr.FlareSolverr.PostResponse(...) in FlareSolverr.cs:line 68 [Warn] RuTracker: Unable to connect to indexer [https://rutracker.org/forum/tracker.php?nm=radiohead]. [Error] Cardigann: An error occurred while processing indexer feed. [https://kinozal.me/browse.php?...] ``` ⚠️ **Это НЕ «blocked by CloudFlare Protection».** Сообщение `Empty cookies returned` означает, что FS прошёл челлендж (`Challenge solved!`), но **не вернул авторизационные cookies** — потому что логина не было. Две ошибки выглядят похоже, но причины разные: | Сообщение | Что значит | |---|---| | `blocked by CloudFlare Protection` | CF не пройден (сессия без прокси, `ERR_NAME_NOT_RESOLVED`) | | **`Empty cookies returned by FlareSolverr`** | **CF пройден, но логина нет → нет `bb_data`** | 🔴 **Почему свежая сессия не логинится.** `sessions.create` + POST → форма (12 KB). Prefetch `GET login.php` в той же сессии → POST → тоже форма (12 KB). То есть **предварительный GET не помогает** — это не «капча к cookie». Просто RuTracker не пропускает автоматический POST-логин из свежего Chrome-профиля FS. **Обходного пути в Prowlarr нет:** форма индексера принимает только `username`/`password`. Поля для cookie (`bb_data`) не существует — подставить живую сессию из браузера нельзя. ### Что нужно от Alex (единственный путь) 1. Зайти на `rutracker.org` **браузером через тот же исходящий IP** (`vless-proxy`), ввести логин+пароль, **пройти капчу**; либо 2. **Отключить капчу** для аккаунта в профиле на форуме — тогда автоматический логин заработает; 3. Проверить, что в браузере появляется кука **`bb_data`** (DevTools → Application → Cookies). Если она есть и трекер не требует капчу — логин из Prowlarr должен пойти. > ⚠️ **Не считать `Empty cookies returned` ошибкой прокси или CF** — это отсутствие логина. > Диагностика: `docker exec flaresolverr curl -s -X POST http://localhost:8191/v1 \ > -H "Content-Type: application/json" -d '{"cmd":"request.get","url":"https://rutracker.org/forum/index.php","maxTimeout":100000,"session":"prowlarr"}' \ > | jq -r '.solution.cookies[].name'` → если нет `bb_data`, логина нет. --- ## 🔴🔴 РЕШЕНИЕ (2026-09-29): свой образ `flaresolverr-vnc` + noVNC для ручной капчи Alex поставил задачу: **«ароматизировать процесс насколько возможно»** — уведомление в ТГ, вход браузером через тот же туннель, установка куки обратно. Разбор по фактам: **Что из исходной идеи не работает (проверено):** | Идея | Вердикт | Причина | |---|---|---| | Мой браузер через 3x-ui по тому же туннелю | ❌ | `vless-proxy` — **клиент**, не сервер. И `cf_clearance` привязан к **IP + User-Agent + TLS-fingerprint** — кука моего Chrome не подойдёт чужому Chrome | | Установка куки обратно в Prowlarr | ❌ | Индексер RuTracker принимает только `username`/`password`. Поля для cookie нет | | Капча-солвер (`CAPTCHA_SOLVER`) | ❌ | **Официально non-functional.** DeepWiki FS: «Currently non-functional». Issue #1452 закрыт без решения — адаптеры удалены из образа | | Ручной вход **внутри Chrome FS** + persistent профиль | ✅ | Единственный рабочий путь. Капчу решает человек, дальше автомат | > 🔴 **Капчу решает человек физически.** Это защита RuTracker, а не дефект конфига. > Задача инженерии — сжать участие Alex до **одного клика за жизнь cookie**. **Проверка 3x-ui / xray (факты):** ``` vless-proxy (xray-клиент): socks :1080 + http :1081 outbound VLESS → vpn.mallexxx.duckdns.org:443 (ws/tls, path /vless) xray-admin (3x-ui): панель :54321, внутри слушает 2053, сеть caddy_default (172.16.1.9) hermes-taiga: есть, сеть hermes_taiga_net ``` ### Свой образ `flaresolverr-vnc` — собран и развёрнут ✅ Compose-сервис заменён с `ghcr.io/flaresolverr/flaresolverr:latest` на локальный образ: ```yaml flaresolverr: image: flaresolverr-vnc:latest # ← свой образ container_name: flaresolverr restart: unless-stopped environment: - LOG_LEVEL=warning - BROWSER_TIMEOUT=60000 - TZ=Asia/Novosibirsk - PROXY_URL=socks5://vless-proxy:1080 ports: - "8191:8191" # API FS - "6080:6080" # ← noVNC volumes: - /mnt/RED_2TB/docker/arr/flaresolverr-config:/config # ← persistent профиль networks: - media_net shm_size: 1gb sysctls: - net.ipv6.conf.all.disable_ipv6=1 ``` **Файлы образа — `/mnt/RED_2TB/docker/arr/fs-vnc/`** (собирать оттуда): | Файл | Что | |---|---| | `Dockerfile` | база `ghcr.io/flaresolverr/flaresolverr:latest` + `x11vnc novnc websockify fluxbox supervisor` | | `supervisord.conf` | 5 процессов: `xvfb`(:99, 1920x1080x24) → `fluxbox` → `x11vnc`(:5900) → `novnc`(:6080) → `flaresolverr` | | `entrypoint-vnc.sh` | `XDG_CONFIG_HOME=/config/chromium-profile`, `DISPLAY=:99`, запуск supervisord | **Сборка:** `cd /mnt/RED_2TB/docker/arr/fs-vnc && docker build -t flaresolverr-vnc:latest .` (~215 с). ### 🔴 ПИТФОЛЛ: FS в headed-режиме (`HEADLESS=false`) — порт 8191 первый запрос рвёт `supervisord.conf` запускает FS с `HEADLESS=false` — иначе в noVNC нечего смотреть. Следствие: сразу после старта контейнера первый `curl` к `:8191` получает **`Connection reset by peer`**. Через ~5–10 с всё работает: ``` $ curl -s -X POST http://localhost:8191/v1 -d '{"cmd":"sessions.list"}' curl: (56) Recv failure: Connection reset by peer ← сразу после старта # sleep 5 {"status":"ok","sessions":[],"version":"3.5.2"} ← ✅ ``` Порт слушается (`netstat -tlnp` → `0.0.0.0:8191`), но Chrome в headed-режиме доводится дольше. **Проверять живость FS — с ретраем/паузой, не с первого запроса.** ### 🔴 ПИТФОЛЛ: `sessions.destroy` несуществующей сессии → HTTP 500 `{"cmd":"sessions.destroy","session":"whale-clean-test"}` на несуществующей сессии отдаёт **HTTP 500 InternalServerError**, а не «ok/not found». Скрипт проверки должен **не падать** на этом (обернуть в try) и использовать уникальное имя сессии (`whale`), иначе повторный прогон ломается на `destroy` несуществующей. ### ✅ Сервис работает ``` flaresolverr Up 0.0.0.0:6080->6080/tcp, 0.0.0.0:8191->8191/tcp API FS: {"status":"ok","version":"3.5.2"} noVNC: http://localhost:6080/vnc.html → 200 профиль: /mnt/RED_2TB/docker/arr/flaresolverr-config/chromium-profile ← создан ``` ⚠️ **Порт `8191` с Mac НЕ проброшен наружу** — `Connection refused`. Все скрипты проверки запускать **на хосте Тайги** (`scp` → `ssh ... python3`), не локально. ### Как пользоваться (процедура «ручная капча») 1. Открыть `https://vnc.mallexxx.duckdns.org/vnc.html` → логин `admin`, пароль `vnc-taiga` (роут в Caddy, **проверен 200**). Альтернатива — ssh-туннель на `6080`. 2. Внутри — рабочий стол fluxbox с Chrome (⚠️ Chrome надо **запустить**, см. питфолл ниже). 3. Зайти на `rutracker.org`, ввести логин/пароль, решить капчу. 4. Cookies лягут в `/config/chromium-profile` → **переживают рестарт контейнера**. 5. FS переиспользует профиль при следующих сессиях → автологин проходит без капчи. ### 🔴 ПИТФОЛЛ: «cannot set background» + чёрный экран в noVNC Симптомы, увиденные Alex: подключение проходит, fluxbox ругается `cannot set background`, меню есть, **окна нет — чёрный экран**. **Причина.** fluxbox/Xvfb **работают штатно** — это безвредный шум (`Failed to read: session.screen0.*`, `Missing charsets in String to FontSet conversion`). Реальная причина пустого экрана: **FS запускает Chrome только на время запроса и убивает его.** Между запросами в `:99` **нет ни одного окна** — смотреть нечего. **Проверка (на хосте Тайги):** ```bash # X-сервер жив? docker exec flaresolverr sh -c 'ls -la /tmp/.X11-unix/' # → srwxrwxrwx X99 ✅ # Chrome запущен? docker exec flaresolverr sh -c 'ps aux | grep chromium | grep -v grep | wc -l' # → 0 ← вот причина чёрного экрана ``` **Фикс — запустить Chrome вручную в том же display и оставить жить** (`-d` = detached, иначе убьётся вместе с exec): ```bash docker exec -d -e DISPLAY=:99 flaresolverr sh -c \ "chromium --no-sandbox --disable-gpu --disable-dev-shm-usage \ --user-data-dir=/config/chromium-profile/chromium \ --window-size=1280,900 --start-maximized rutracker.org > /tmp/chrome-manual.log 2>&1" sleep 12 docker exec flaresolverr sh -c 'ps aux | grep chromium | grep -v grep | wc -l' # → 12 ``` После этого в noVNC видно окно Chromium. **Alex подтвердил:** «ок, вижу хром». ⚠️ `--user-data-dir` указывать **точно как у FS** (`/config/chromium-profile/chromium`) — иначе профиль раздвоится и куки осядут в другом месте. **Сопутствующий шум (НЕ ошибки):** ``` ERROR:dbus/object_proxy.cc Failed to call method: org.freedesktop.DBus.NameHasOwner ERROR:dbus/bus.cc Failed to connect to the bus: /run/dbus/system_bus_socket WARNING:zygote_communication_linux.cc Failed to send GetTerminationStatus message ``` dbus/zygote ругань есть в любом контейнере без dbus — на работу Chrome в Xvfb не влияет. Отличить «Chrome упал» от «Chrome жив» по `EXIT=124` от `timeout`: **124 = жив** (таймаут сработал). ### План (оставшиеся шаги) | # | Шаг | Статус | |---|---|---| | 1 | Образ `flaresolverr-vnc` + noVNC + persistent профиль | ✅ **выполнено** | | 2 | Проверить, что cookies переживают рестарт контейнера | ⏳ ждёт ручного входа Alex | | 3 | `hermes-taiga`: уведомление в ТГ при `Empty cookies returned` | ⏳ не начато | | 4 | Подтвердить со стороны Prowlarr: поиск отдаёт CF-индексеры | ⏳ после п.2 | **Шаг 3 (дизайн).** hermes-taiga поллит `GET /api/v1/indexerstatus` (или грепает лог Prowlarr на `Empty cookies returned`/`429`) → при появлении карантина шлёт в ТГ: «RuTracker просит капчу → открой `http://<тайга>:6080/vnc.html`». Логика простая, ничего в стеке не ломает. **Бэкапы этой сессии:** | Файл | Путь | |---|---| | compose (до правки образа) | `/mnt/RED_2TB/docker/arr/docker-compose.yml.bak-20260928-profvol` (2723 B) | | ПДФ предыдущих правок | `docker-compose.yml.bak-20260928-flaresolverr`, `.bak-20260928-lidarr-proxy` | > ⚠️ **Опровергнута прошлая версия про `/config`.** Ранее в этом доке записано «на Тайге > `/config` НЕТ» — **неверно**: volume был (анонимный, от образа), но профиль Chromium жил > в `~/.config/chromium` **внутри** контейнера и умирал при пересоздании. Теперь профиль > явно смонтирован в `/config/chromium-profile` через `XDG_CONFIG_HOME`. Не путать: > наличие `/config` ≠ persistent профиль. --- ## 🔴🔴 СВЕРКА С КРА́КЕНОМ (2026-09-29): «как на Кра́кене» = ТОЖЕ СЛОМАНО Alex спросил «на кракене вроде был капча солвер для этого?». Проверено на живом Кра́кене — **капча-солвера там НЕТ, и карантин там тот же**. Это снимает главную ложную посылку задачи. ### Капча-солвера на Кра́кене нет ``` docker ps -a | grep -iE "solver|capsolve|2captcha|anti|capmonster" → только flaresolverr FS env: LOG_LEVEL, BROWSER_TIMEOUT, PATH, LANG, GPG_KEY, PYTHON_* → НЕТ CAPTCHA_SOLVER IndexerProxies на Кра́кене: (1, 'FlareSolverr', '{"host":"http://flaresolverr:8191/","requestTimeout":60}', 'FlareSolverr', ...) ``` Только FlareSolverr, `requestTimeout: 60` (на Тайге уже 180). **Никакого `CAPTCHA_SOLVER`, 2captcha, capsolver.** Если капча-солвер где-то и вспоминается — это не Кра́кен. ### Карантин на Кра́кене — идентичный Тайге ```sql -- Кра́кен: /srv/dev-disk-by-uuid-49e8f586-.../docker/prowlarr/config/prowlarr.db SELECT ProviderId, EscalationLevel, DisabledTill FROM IndexerStatus; ``` ``` 1 RuTracker EscalationLevel=9 DisabledTill=2026-09-27 ← В КАРАНТИНЕ 5 Kinozal 9 2026-09-27 ← В КАРАНТИНЕ 6 Kinozal (M) 9 2026-09-27 ← В КАРАНТИНЕ 2 RuTor 3 — 3 Byrutor 0 — 4 NoNaMe 0 — ``` **Ровно та же тройка, ровно тот же `EscalationLevel=9`.** То есть на Кра́кене карантин тоже стоит с 27 сентября и не снимался. Список индексеров на Кра́кене — **идентичен Тайге** (id 1–6, те же имена, тот же `impl`). > 🔴 **Вывод для будущих сессий:** не строить план на посылке «на Кра́кене работает, значит > и на Тайге заработает». На 2026-09-29 обе площадки имеют **одинаковый незакрытый дефект > авторизации RuTracker**. «Как на Кра́кене» ≠ «починить» — на Кра́кене тоже красное. ### Что реально отличается: у FS на Кра́кене есть `/config` ``` Кра́кен: IMAGE=ghcr.io/flaresolverr/flaresolverr:latest MOUNTS= /srv/.../docker-data/volumes/fcca43.../_data => /config ENV: НЕТ PROXY_URL (на Кра́кене DNS-блока нет) /config пуст (ls → total 8, только . и ..) sessions: [] Тайга: PROXY_URL=socks5://vless-proxy:1080 /config НЕТ ``` ⚠️ `/config` **пуст** и на Кра́кене, и сессий нет (`sessions: []`, version 3.5.2). То есть **persistent Chrome-профиль не используется** — гипотеза «профиль с cookies переживает рестарт» **опровергнута**. Это была ложная версия; не тратить на неё время. > ⚠️ `/config` на Кра́кене объявлен, но ничего не сохраняет → добавлять его на Тайге > **не нужно**. Причина `bb_data`-отсутствия не в профиле. Скрипт сверки: `/tmp/whale_login_check.py`, `/tmp/whale_login2.py` (запускать **на хосте Тайги**, порт `8191` наружу с Mac не проброшен → `Connection refused`). --- ## ⚠️ ЛОЖНЫЙ СЛЕД (оставлен для истории): «капча привязана к сессии» Самый запутанный пункт. Дефект выглядел как «неверный пароль», потом как «капча», на самом деле — **капча выдаётся только для «холодных» сессий**. Замеры в одном ходе (скрипты `/tmp/fs_session_cmp.py`, `/tmp/fs_search_check.py`): ``` A: request.post /forum/login.php БЕЗ session → len=13 335 ❌ форма логина вернулась B: request.post /forum/login.php С session=prowlarr → len=251 792 ✅ ЗАЛОГИНЕН C: request.get tracker.php?nm=...&f=... в той же сессии → len=254 745 ✅ выдача auth_failed_in_html=False, login_form=False ``` 🔴 **Вывод: логин через сессию `prowlarr` РАБОТАЕТ.** Капча отдаётся только новым (безымянным) сессиям — то есть `PROXY_URL` + переиспользование сессии `prowlarr` её обходят. Мой одиночный тест без сессии давал 13 KB и порождал ложный диагноз «капча блокирует всё». **Как проверить состояние RuTracker правильно:** ```python # ВСЕГДА с session=prowlarr, иначе получишь ложную капчу {"cmd":"request.post","url":"https://rutracker.org/forum/login.php", "postData":"login_username=...&login_password=...&login=...", "session":"prowlarr","maxTimeout":240000} ``` Признак «залогинен» — **len ≈ 250 KB**, формы нет. 13 KB = сессия холодная, а не «пароль плох». > ⚠️ **Не делать вывод о пароле по тесту БЕЗ сессии.** Всегда `session=prowlarr`. ### Как снялся карантин RuTracker (рабочая процедура) `health`/`indexerstatus` держат **кэш** (`disabledTill`), даже когда трекер уже отвечает. Снятие — **тем же тестом полным объектом**, что и для Kinozal: ```bash docker exec prowlarr curl -s -H "X-Api-Key: $PK" http://localhost:9696/api/v1/indexer/1 > /tmp/p1.json docker cp /tmp/p1.json prowlarr:/tmp/p1.json docker exec prowlarr curl -s -X POST -H "X-Api-Key: $PK" -H "Content-Type: application/json" \ --data-binary @/tmp/p1.json http://localhost:9696/api/v1/indexer/test # → {} с HTTP=200 = карантин снят docker exec prowlarr curl -s -H "X-Api-Key: $PK" http://localhost:9696/api/v1/indexerstatus # → [] docker exec prowlarr curl -s -o /dev/null -w "%{http_code}" "http://localhost:9696/1/api?t=caps&apikey=$PK" # → 200 ``` Проверено: `{}` + **200** → `indexerstatus` пуст, `caps` → **200**. ## 🔴🔴 ГЛАВНЫЙ ПИТФОЛЛ ФИНАЛА: `IndexerStatus` в `prowlarr.db` — снимается ТОЛЬКО SQL Самая долгая петля сессии. Симптом: «снимаю карантин тестом → warning возвращается → тест падает заново». Круг не сходился, потому что **причина не в прокси, не в FlareSolverr и не в пароле — она в БД Prowlarr.** **Пруф — дамп таблицы** (`sqlite3` на хосте Тайги ЕСТЬ, в контейнере НЕТ): ```bash DB=/mnt/RED_2TB/docker/arr/prowlarr/prowlarr.db sqlite3 "file:$DB?mode=ro" \ "SELECT Id, ProviderId, InitialFailure, MostRecentFailure, EscalationLevel, DisabledTill FROM IndexerStatus;" ``` ``` ProviderId Индексер EscalationLevel DisabledTill 5 Kinozal 2 2026-09-28 10:08 6 Kinozal M 2 — 4 NoNaMe 0 — 2 RuTor 0 — 1 RuTracker 9 2026-09-29 09:46 ← СУТКИ 3 Byrutor 0 — ``` `EscalationLevel` = степень эскалации (0–9), `9` — максимум, `DisabledTill` = **+24 ч**. Пока запись есть: `caps` отдаёт **429** → Prowlarr не пробует снова → фоновый health-чек Radarr/Sonarr/Lidarr бьёт в 429 → **warning каскадом во все четыре сервиса**. Отсюда парадокс «health Radarr пуст, а warning про индексе́ры живёт» — он живёт не у Radarr, а в БД Prowlarr. 🔴 **`POST /indexer/test` карантин НЕ снимает, а ПРОДЛЕВАЕТ.** Наблюдалось вживую: `DisabledTill` `15:44` → `21:45` после одного теста. Каждая «попытка починить тестом» удлиняла блокировку — это и была петля. Записи эскалируют, а не сбрасываются. ### Рабочий путь снятия (как на Кра́кене) ✅ ВЫПОЛНЕНО 2026-09-29 ```bash # 1. БЭКАП через .backup, НЕ cp (БД в WAL-режиме) DB=/mnt/RED_2TB/docker/arr/prowlarr/prowlarr.db sqlite3 "file:$DB?mode=ro" ".backup /home/truenas_admin/prowlarr.db.bak-$(date +%Y%m%d-%H%M%S)" # → /home/truenas_admin/prowlarr.db.bak-20260928-032611 (581 632 байт) # 2. стоп → удалить строки карантина → старт docker stop prowlarr sqlite3 "$DB" "DELETE FROM IndexerStatus;" # можно без WHERE — чистим все sqlite3 "$DB" "PRAGMA quick_check;" # → ok docker start prowlarr # 3. проверка curl -s -H "X-Api-Key: $PK" http://localhost:9696/api/v1/indexerstatus # → пусто for I in 1 2 3 4 5 6; do curl -s -o /dev/null -w "idx$I=%{http_code}\n" \ "http://localhost:9696/$I/api?t=caps&apikey=$PK"; done # → все 200 ✅ ``` **Результат прогона:** `IndexerStatus` → `rows=0`, `quick_check=ok`, `Indexers` = 6 определений на месте, `docker start prowlarr` поднялся, `health` → `[]`, `indexerstatus` → `[]`, **все 6 `caps` → 200**. ⚠️ Скрипт: `/tmp/clear_indexerstatus.sh` (в нём есть контроль «контейнер действительно остановлен» перед DELETE). 🔴 **НО это НЕ решает поиск.** Через минуты после очистки CF-индексеры снова в карантине, поиск `radiohead` → `total=79`, отдали только **NoNaMe (47) + RuTor (32)**. Потому что настоящая причина — **отсутствие логина** (`bb_data`), см. раздел «ИТОГОВЫЙ КОРЕНЬ». SQL-очистка снимает **симптом** (карантин), но не причину: пока логин не проходит, карантин будет возвращаться волнами. > ⚠️ **Честная оценка метода.** Снятие через SQL даёт `caps` 200 и пустой `indexerstatus`, > то есть **выглядит починенным**, но реальный поиск в этих индексерах не работает. > **Приёмка — только `GET /api/v1/search?query=X` с разбивкой `group_by(.indexer)`,** > а не `caps` и не `health`. Таблицы: `Indexers`, `IndexerStatus`, `IndexerProxies`, `ApplicationIndexerMapping`, `IndexerDefinitionVersions`. > ⚠️ **Урок об источниках истины.** health-эндпоинты arr-сервисов **не авторитет** о блокировках. > На Кра́кене это записано прямо: «`GET /api/v1/health` и `/api/v1/indexerstatus` НЕ показывают > причины блокировки» — смотреть `prowlarr.debug.txt` и таблицу `IndexerStatus`. На Тайге > `indexerstatus` причину показывал, но **снятие через API не срабатывало — только SQL.** ## 🔴 ПИТФОЛЛ: `Auth Failed` = следствие `IndexerStatus`, а НЕ неверный пароль Диагноз ставился трижды и дважды был неверным — фиксирую окончательно. Проверка логина через FS (сессия `prowlarr`): ``` login → len=254 410 ✅ search → len=254 745 ✅ auth_failed_in_html=False login_form=False ``` То есть **логин живой**, а Prowlarr в это же время отдаёт `RuTracker Auth Failed`. **Правильный признак «залогинен или нет» — РАЗМЕР HTML, не подстрока:** | `len` HTML | Что это | |---|---| | **~250 KB** | залогиненный форум ✅ | | **~13 KB** | форма логина вернулась ❌ | Подстрока `login_username` присутствует **в обоих** случаях (HTML-шаблон + скрытая форма быстрого входа) — по ней диагноз ставить НЕЛЬЗЯ. Именно это дало ложное «пароль неверен». ⚠️ **И капча тут ни при чём.** Наблюдалось: «холодная» (свежесозданная) FS-сессия получает форму с `cap_code` (`len=13 338`), а уже прогретая сессия `prowlarr` — залогиненный форум (`len=251 792`). То есть капча отдаётся **не по признаку пароля**, а свежим сессиям. Пароль всё время был верный — Alex подтвердил отдельно. > ⚠️ **Порядок диагностики при `Auth Failed` (не переставлять):** > 1. Проверить логин `request.post` на `/forum/login.php` через FS → судить по `len` (~250 KB = ок). > 2. Посмотреть `IndexerStatus` в `prowlarr.db` — если есть строка, **это и есть причина**. > 3. Только если п.1 показал ~13 KB — вопрос к паролю. > **Не требовать у Alex новый пароль, не пройдя п.2.** ## ✅ ЗАКРЫТО: пароль RuTracker — рабочий (первый диагноз был НЕВЕРЕН) **Итог 2026-09-28 (позже в тот же вечер):** сохранённая в Prowlarr пара (`mallexxx` / 8 символов) **логинится успешно**. Проверено `request.post` через FlareSolverr на `/forum/login.php`: ``` final_url = https://rutracker.org/forum/login.php ← НО форма не вернулась len = 251 792 ← полная страница форума (~250 KB) login_form_back = False ← форма логина НЕ переоткрылась ``` `login_form_back=False` + страница 251 KB = **сессия установлена**, это залогиненный форум. Скрипт проверки: `/tmp/rt_login.py` (копия на Тайге; `python3 /tmp/rt_login.py "$U" "$P"`). 🔴 **Почему первый диагноз был ложным.** Ранее вывод «пароль неверен» сделан по признаку `login_username` в HTML, но эта строка присутствует **и на залогиненной странице** (скрытая форма быстрого входа / HTML-шаблон). Признак «форма вернулась» надо проверять по **`final_url` + длине страницы**, а не по наличию подстроки `login_username` — это дало ложное «Auth Failed». > ⚠️ **Урок:** `Auth Failed` в `indexer/testall` Prowlarr **не означает неверный пароль**. > Прежде чем требовать новый пароль у Alex — проверить логин отдельным `request.post` > с `final_url` + `len` в ответе. Признак-подстрока ненадёжен. ⚠️ **Если Alex всё-таки сменил пароль на самом rutracker.org** — в Prowlarr лежит СТАРЫЙ (проверено: `username len=8`, `password len=8` через `/api/v1/indexer/1`), его надо обновить в `Indexers → RuTracker`, иначе после смены на трекере логин отвалится. ## ✅ ЗАКРЫТО: Radarr/Sonarr — каталоги категорий созданы Radarr/Sonarr ждали `/storage/Downloads/radarr` и `/storage/Downloads/sonarr` (Transmission пишет **плоско** в `/mnt/storage/Downloads`). Каталоги созданы: ```bash mkdir -p /mnt/RED_2TB/storage/Downloads/radarr /mnt/RED_2TB/storage/Downloads/sonarr ``` В контейнерах видны как `/storage/Downloads/{radarr,sonarr}`, владелец `abc:abc`. ⚠️ `RemotePathMappingCheck` в health **кэшируется** — после создания каталогов ошибка осталась, нужен `docker restart radarr sonarr` для перепроверки. См. [[family/plans/lidarr-taiga-deploy]]. ## ✅ ЗАКРЫТО 2026-09-28 (финал): Radarr/Sonarr/Lidarr вычищены | Что | Итог | |---|---| | `docker restart radarr sonarr` | ✅ выполнен → `RemotePathMappingCheck` **ушла** | | Карантин индексеров в Prowlarr (id 5, 6) | ✅ снят тестом полным объектом → `caps` 200 | | `PUT /api/v3/indexer/N?forceSave=true` в Radarr/Sonarr | ✅ 202 | | `docker restart radarr sonarr lidarr` | ✅ выполнен (+ отдельный `docker restart lidarr` после правки bypass) | | **health Radarr** | ✅ `[]` — чисто | | **health Sonarr** | ✅ `[]` — чисто | | health Lidarr | ✅ дефект `proxyBypassFilter` **закрыт**; остаток — общий карантин Prowlarr | | Библиотека Lidarr | 1 артист (`Radiohead`), 23 релиза | ✅ **`proxyBypassFilter` расширен и рестарт выполнен.** Проверка после рестарта показала: прежний симптом `Http request timed out` (запрос к Prowlarr уходил в прокси) **ушёл** — на его месте осталась честная ошибка `429:TooManyRequests` от Prowlarr, потому что Kinozal 5/6 снова ушли в карантин (из-за капчи/CF). То есть **дефект bypass закрыт**, а остаток теперь общий со всей инфраструктурой и лечится снятием карантина в Prowlarr. **Остаток (не блокирует, вне инфраструктуры):** RuTor в Radarr/Sonarr — `Query successful, but no results in the configured categories`. Это **не блокировка и не карантин**: RuTor не отдаёт результаты в категориях фильмов/сериалов. Проверено тестом полным объектом → caps отдаёт, карантина нет. Оставляем как есть — дефект самого трекера. ⚠️ **Карантин имеет свойство возвращаться.** После снятия Kinozal 5/6 и RuTracker снова оказались в карантине (карточки `disabledTill`), потому что их периодически тестирует сам Prowlarr, и тест снова падает (капча RuTracker / CF kinozal). **Пока капча RuTracker не пройдена, карантин будет возвращаться волнами** — это не регресс инфраструктуры. - **Приёмка Alex в UI:** `https://prowlarr.mallexxx.duckdns.org` → Indexers → 6 зелёных; `https://radarr.mallexxx.duckdns.org` / `sonarr` → System → Health пусто; `https://lidarr.mallexxx.duckdns.org` → артист ищется. ## ✅ Lidarr ↔ SkyHook: решено 2026-09-28 (встроенный прокси, НЕ env) Смежная задача, решена в этой же сессии. Полный разбор — [[family/plans/lidarr-taiga-deploy]]. `api.lidarr.audio` (метаданные SkyHook) за Cloudflare: - прямой запрос из контейнера → **403**; - через `socks5h://vless-proxy:1080` → **200**; - домен **резолвится** (`2606:4700:3031::ac43:df35`) — это **чисто CF, НЕ DNS-блок**. ⚠️ **FlareSolverr здесь бесполезен** — он обслуживает Prowlarr, а SkyHook зовёт сам Lidarr. 🔴 **ГЛАВНЫЙ ПИТФОЛЛ: env `HTTP_PROXY`/`HTTPS_PROXY` Lidarr НЕ ЧИТАЕТ.** Проверено: compose-env + рестарт → всё тот же **403**. .NET-клиент SkyHook игнорирует env. **Рабочее решение — встроенный прокси-конфиг Lidarr** (применяется без рестарта): ```bash # GET /api/v1/config/host -> proxyEnabled:false # PUT /api/v1/config/host/1 c полями: # proxyEnabled: true # proxyType: "http" # proxyHostname: "vless-proxy" # proxyPort: 1081 # ← HTTP-порт, НЕ 1080 (SOCKS5) # proxyBypassFilter: "localhost,127.0.0.1,vless-proxy,prowlarr,lidarr,radarr,sonarr,transmission,jellyfin,navidrome,caddy,gluetun,taiga" # proxyBypassLocalAddresses: true ``` 🔴 **`proxyBypassFilter` ОБЯЗАН содержать `prowlarr` и ВСЕ docker-имена стека.** Дефолт (`localhost,127.0.0.1,vless-proxy`) не покрывает имя `prowlarr`, и тогда внутренний запрос Lidarr → Prowlarr заворачивается в прокси и падает `Http request timed out`, хотя сам Prowlarr отвечает 200. `proxyBypassLocalAddresses=true` на docker-имена **не действует** — только на IP-литералы. Отсюда же следствие: после правки bypass нужен `docker restart lidarr`. Скрипт правки bypass: `/tmp/lidarr_bypass.py` (GET → patch → PUT → 202 → read-back). Скрипт: `/tmp/lidarr_set_proxy.py` (на хосте Тайги; там `python3` **есть**, `curl` — нет). **Результат:** `lookup?term=radiohead` → 10 результатов; артист добавлен; поиск релизов → 23 раздачи FLAC. Библиотека: 0 артистов → 1. ⚠️ **Ложный след при диагностике:** `api.lidarr.audio` отдаёт 403 **не всегда** — при исчерпанном CF-лимите 403 бывает и у `curl`, что выглядит как «прокси не работает». Различать: заголовок `x-rate-limit-remaining` присутствует только при живом ответе; и сравнивать **прямой** vs **через прокси** запрос в одном ходе. ⚠️ Откат: env-вариант убран из compose (бэкап `~truenas_admin/docker-compose.yml.bak-20260928-lidarr-proxy`). ## ✅ ЗАКРЫТО: Lidarr — путь загрузки настроен (`musicCategory`) Отдельный дефект, найден позже в тот же вечер. Вопрос Alex: «Lidarr при добавлении будет качать в музыку?» — ответ был **нет**, и это подтвердилось фактами. **Было (сломано):** ``` musicCategory = "" ← пусто! musicDirectory = "" musicImportedCategory= null ``` Следствие: Transmission получил бы задачу **без категории**, положил файл плоско в `/mnt/storage/Downloads`, а Lidarr ждал бы его в `/storage/Downloads/<категория>`. Скачивание прошло бы — **импорт в библиотеку упал**. **Стало (рабочий путь, проверено):** ``` Lidarr musicCategory = lidarr ← PUT ?forceSave=true → 202 Transmission: /mnt/storage/Downloads/lidarr ✅ существует (abc:abc) Lidarr: /storage/Downloads/lidarr ✅ существует RemotePathMapping: /mnt/storage/Downloads/ → /storage/Downloads/ ✅ rootFolder: /storage/Music (978 GB free, accessible) ✅ Скачается в: /storage/Music// ✅ Поиск релизов: 43 FLAC-раздачи (seeders 6/5/7) ✅ ``` 🔴 **`musicCategory` — дефолт `lidarr`** (не `music`!). Проверять по schema (`downloadclient/schema` → implementation `Transmission`) и сверять с реально существующим каталогом в Transmission. Radarr по той же схеме использует `radarr`, Sonarr — `sonarr`; каталоги `/mnt/storage/Downloads/{lidarr,radarr,sonarr}` уже созданы. Скрипт: `/tmp/lidarr_category.py` (GET downloadclient/1 → правка `musicCategory` → PUT `?forceSave=true` → 202 → read-back). ⚠️ У полей бывает **нет ключа `value`** (`musicDirectory` = `''` без `value`) — не падать на `f['value']`, использовать `f.get('value')`. > ⚠️ **`monitored=false`** у добавленного артиста — Lidarr не начнёт качать, пока > у артиста не включён мониторинг альбомов (`Lidarr → Artist → Monitor`). ## 🔴 ПИТФОЛЛ: `test` требует ПОЛНЫЙ объект, не `{id}` → 400 Во **всех** arr-сервисах (`Prowlarr`, `Radarr`, `Sonarr`, `Lidarr`) эндпоинт `POST /api/vN/indexer/test` с телом `{"id":N}` отдаёт **400 Bad Request**. Правильно — отправить **полный** объект индексера: ```bash curl -s -H "X-Api-Key: $K" http://localhost:PORT/api/v3/indexer > /tmp/idx.json docker cp /tmp/idx.json radarr:/tmp/idx.json docker exec radarr curl -s -X POST -H "X-Api-Key: $K" -H "Content-Type: application/json" \ --data-binary @/tmp/idx.json http://localhost:7878/api/v3/indexer/test # → {} с http=200 = тест пройден; 400 + validationFailures = реальная ошибка ``` `{}` + **200** = успех (не 204, не «пусто»). 🔴 **`POST /indexer/testall` НЕ РАБОТАЕТ в Radarr/Sonarr** — отдаёт **400**, а Sonarr ещё и **подвешивается >300 с** (в Prowlarr `testall` тоже вреден: один Chrome → гонка, см. питфолл про параллельный тест). **Единственный рабочий путь — `POST /indexer/test` по одному, полным объектом.** Проверено на всех четырёх сервисах. 🔴 **`GET /indexerstatus` есть ТОЛЬКО в Prowlarr** — в Radarr/Sonarr эндпоинт → **404**. Карантин в Radarr/Sonarr иначе: смотреть `health` (warning «Indexers unavailable due to failures») и обнулять `PUT /api/v3/indexer/N?forceSave=true`. ## 🔴 ПИТФОЛЛ: `429` на `/N/api?t=caps` у Prowlarr = карантин → каскад во все arr `GET http://prowlarr:9696/5/api?t=caps&apikey=…` → **429 TooManyRequests**, пока индексер в карантине. Следствие: **Radarr/Sonarr/Lidarr не могут синкнуть этот индексер** и показывают `Unable to connect to indexer … [429:TooManyRequests]`. Настоящая причина — не в них. **Порядок лечения (снизу вверх):** 1. Снять карантин в **Prowlarr** — `POST /api/v1/indexer/test` полным объектом (по одному). 2. Проверить `GET /api/v1/indexerstatus` → пусто и `caps` → **200**. 3. Пересохранить проблемный индексер в самом arr: `PUT /api/v3/indexer/N?forceSave=true` → **202** (сбрасывает `FailureCount`). 4. `docker restart radarr sonarr lidarr` — health пересчитывается только при старте. ## 🔴 ПИТФОЛЛ: `proxyBypassFilter` Lidarr без внутренних имён → таймауты к Prowlarr **Самый неочевидный дефект сессии.** После включения встроенного прокси Lidarr (`proxyEnabled=true`) его запросы к **Prowlarr** ушли в прокси и стали падать `Http request timed out`, хотя в Prowlarr тот же индексер отвечал 200. **Причина:** дефолтный bypass — `localhost,127.0.0.1,vless-proxy`, в нём **НЕТ `prowlarr`**. Имя `prowlarr` не попадает под `proxyBypassLocalAddresses` (это не IP-литерал), поэтому внутрикластерный `http://prowlarr:9696/…` инкапсулировался в HTTP-прокси и таймаутил. **Фикс** — дописать в `config/host.proxyBypassFilter` **все внутренние docker-имена**: ``` localhost,127.0.0.1,vless-proxy,prowlarr,lidarr,radarr,sonarr,transmission,jellyfin,navidrome,caddy,gluetun,taiga ``` Скрипт: `/tmp/lidarr_bypass.py` (GET → patch filter → PUT `/api/v1/config/host` → **202** → read-back). ⚠️ После правки — `docker restart lidarr`. > ⚠️ **Правило:** включая приложению прокси-конфиг, **сразу прописать в bypass все имена > своего стека**. Иначе сервис «уйдёт» в прокси и к соседям — симптом выглядит как > «сервер индексера недоступен», а виноват собственный прокси-конфиг. ## Общий вывод по прокси на Тайге (три разных механизма!) На одном хосте понадобились **три независимых способа** прокинуть трафик через `vless-proxy`: | Кто | Механизм | Ключ | |---|---|---| | Prowlarr (индексеры) | SOCKS5-прокси в Prowlarr + FlareSolverr | теги `[1,2]`, `PROXY_URL` у FS | | FlareSolverr (Chrome) | глобальный прокси образа | env `PROXY_URL=socks5://...` (**НЕ** HTTP_PROXY) | | Lidarr (SkyHook) | встроенный конфиг приложения | `config/host.proxyEnabled` (**env НЕ работает**) | ⚠️ **Не переносить рецепт одного сервиса на другой.** `arr`-сервисы внешне похожи, но механизм прокси у каждого свой; проверять фактическим запросом, а не по аналогии. ## История (финал сессии 2026-09-28) - **~15:20** — RuTracker логинится (`len 251 792`), поиск «matrix» → 256 результатов, health всех arr пуст. Замер зафиксирован в разделе «РЕЗУЛЬТАТ». - **~16:00** — Lidarr: `/release?artistId=1` → **0**. Найдена причина — `proxyBypassFilter` без `prowlarr`; внутренний запрос Lidarr→Prowlarr уходил в прокси и таймаутил. Фикс: filter расширен до всех docker-имён (PUT `config/host` → **202**, read-back). - **~16:10** — `docker restart lidarr`. Симптом-таймаут ушёл, но всплыла настоящая причина: `429:TooManyRequests` от Prowlarr → Kinozal 5/6 снова в карантине. - **~16:20** — карантин Kinozal/Kinozal(M) снят тестом полным объектом → `caps` 1/5/6 → 200. Radarr/Sonarr: `PUT ?forceSave=true` → 202, `docker restart` → `health` **`[]`**. - **~16:40** — RuTracker перестал логиниться: HTML сжался **251 KB → 13 KB**, в форме найден `cap_code` + метка `Код:` → диагноз «трекер требует капчу». Пара в Prowlarr **не менялась** (сверено байт-в-байт с локальной копией) — «пароль неверен» ложный. - **~17:00** — Alex сам починил логин на трекере. Проверка выявила **ключевое**: логин БЕЗ сессии → 13 KB (капча), логин **С `session=prowlarr`** → **251 792** ✅. Капча привязана к «холодной» сессии; сессия Prowlarr её обходит. См. раздел «ГЛАВНОЕ ОТКРЫТИЕ ПРО RuTracker». - **~17:10** — найден отдельный дефект Lidarr: `musicCategory` **пустая** → импорт скачанного упал бы. Исправлено на `lidarr` (202); сверены каталоги, маппинг, root folder. Поиск релизов: **43** FLAC-раздачи. - **~17:20** — карантин RuTracker снят тестом полным объектом → `{}` HTTP **200**, `indexerstatus` → `[]`, `caps` idx1 → **200**. Prowlarr полностью чист. - **Итог (~17:20):** инфраструктура Тайги чиста и проверена. Открыт **1** дефект — RuTor (`no results in the configured categories`, на стороне трекера). Остаток-механика: `docker restart radarr sonarr lidarr` для сброса **кэша health** со старым RuTracker (команда ждала апрува Alex, в этой сессии не выполнена). ## История (продолжение, 2026-09-29) - **Апрув получен**, `docker restart radarr sonarr lidarr` → **выполнен**. Health Lidarr стал **пустым**; Radarr/Sonarr всё ещё держали warning — потому что причина **не в них**, а в БД Prowlarr (см. ниже). - **Найдена настоящая петля.** Симптом: «снимаю карантин тестом → warning возвращается → тест падает». Дамп `IndexerStatus` показал **`EscalationLevel=9`, `DisabledTill=+24ч`** у RuTracker (ProviderId=1), плюс карантины у Kinozal 5/6. 🔴 **`POST /indexer/test` карантин не снимает, а ПРОДЛЕВАЕТ** (наблюдалось `15:44` → `21:45`). Это и была петля — каждая «попытка починить тестом» удлиняла блокировку. - **Сверка с Кра́кеном** (Alex спросил «на Кра́кене работает всё так? у нас точно similar?»). Прочитан [[family/how-to/arr-stack-kraken]]: на Кра́кене есть процедура **`sqlite3 ... "DELETE FROM IndexerStatus"`** — на Тайге она **не выполнялась ни разу**. Это было главное расхождение. - **Выполнено:** бэкап `~/prowlarr.db.bak-20260928-032611` (`.backup`, не `cp`) → `docker stop prowlarr` → `DELETE FROM IndexerStatus` (`rows=0`, `quick_check=ok`) → `docker start prowlarr`. Результат: `health` → `[]`, `indexerstatus` → `[]`, **все 6 `caps` → 200**. - 🔴 **НО поиск не заработал.** `GET /api/v1/search?query=radiohead` → `total=79`, отдали только **NoNaMe (47) + RuTor (32)**. CF-индексеры → **429** через минуты. - **Найден истинный корень.** Лог Prowlarr: `FlareSolverrException: Empty cookies returned by FlareSolverr` (`FlareSolverr.cs:68`). Замер cookies сессии: `[cf_clearance, bb_guid]` — **куки `bb_data` НЕТ**, то есть **логин RuTracker не выполняется**. Свежая сессия + POST → форма (12 KB); prefetch `GET login.php` + POST → тоже форма. Предварительный GET **не помогает**. - **Вывод сессии:** инфраструктура (прокси, FS, теги, БД) исправна и вычищена. Блокер **вне инфраструктуры** — RuTracker не пропускает автоматический логин без капчи. Решение требует Alex: пройти капчу браузером через `vless-proxy` либо отключить капчу у аккаунта. См. раздел «ИТОГОВЫЙ КОРЕНЬ». ### 🧠 Уроки этой сессии (для будущих) 1. **«caps 200» ≠ «поиск работает».** Prowlarr может отдавать `caps` 200, пустой `indexerstatus` и `health: []`, при этом реальный поиск через индексер не идёт. **Приёмка — `search` с `group_by(.indexer)`**, потому что пустой ответ трекера выглядит как успех инфраструктуры. 2. **`429` на `caps` — не «карантин в Prowlarr» как отдельная сущность, а запись в `IndexerStatus`.** Лечить SQL, не тестами. Тест **продлевает** блокировку. 3. **`Empty cookies returned` ≠ `blocked by CloudFlare`.** Первое — нет логина (`bb_data`), второе — CF не пройден. Симптомы похожи, причины разные, лечения разные. 4. **Bypass-фильтр прокси обязан содержать имя сервиса-соседа**, иначе внутренние запросы уходят в прокси (Lidarr → Prowlarr). Признак — `Http request timed out` при живом соседе. 5. **Не сверять артефакт с соседним артефактом.** Здесь долго сверялись `caps`/`health` между собой, а они оба — производные одного состояния БД. Сверять с **постановкой задачи** (Alex: «у меня должно качаться»), то есть с реальным поиском. ### Что делать при возврате симптома «индексера недоступны» (обновлено 2026-09-29) 1. `GET /api/v1/indexerstatus` в Prowlarr → кто в карантине (`disabledTill`). 2. 🔴 **Снять карантин через SQL, НЕ тестом** — `POST /indexer/test` его **продлевает** (`EscalationLevel` растёт, `DisabledTill` удлиняется): ```bash DB=/mnt/RED_2TB/docker/arr/prowlarr/prowlarr.db sqlite3 "file:$DB?mode=ro" ".backup /home/truenas_admin/prowlarr.db.bak-$(date +%Y%m%d-%H%M%S)" docker stop prowlarr sqlite3 "$DB" "DELETE FROM IndexerStatus;" docker start prowlarr ``` 3. `GET /N/api?t=caps` → **200** (429 = ещё в карантине). ⚠️ Это **не** доказательство работы. 4. **Приёмка — реальный поиск**, не `caps` и не `health`: ```bash curl -s -m 240 -H "X-Api-Key: $PK" "http://localhost:9696/api/v1/search?query=radiohead&type=search" \ | jq -r 'group_by(.indexer)[] | "\(.[0].indexer): \(length)"' ``` Если CF-индексеров нет в выдаче — смотреть **cookies** (`bb_data`), а не `caps`: ```bash docker exec flaresolverr curl -s -X POST http://localhost:8191/v1 -H "Content-Type: application/json" \ -d '{"cmd":"request.get","url":"https://rutracker.org/forum/index.php","maxTimeout":100000,"session":"prowlarr"}' \ | jq -r '.solution.cookies[].name' # нет bb_data → логин не прошёл → нужно вмешательство Alex (капча), инфраструктура ни при чём ``` 5. Если снова падает RuTracker — **не требовать пароль**, пока не проверены `bb_data` и капча. ## История (продолжение, 2026-09-29 — сессия «ручная капча») - **Постановка Alex:** «ароматизировать насколько возможно — уведомление в ТГ от hermes-taiga, соединение моего браузера через 3x-ui через тот же туннель, выдача и установка куки обратно». - **Разбор идей — три из четырёх отвергнуты фактами** (см. таблицу в разделе «РЕШЕНИЕ»): свой браузер через 3x-ui → `vless-proxy` это **клиент**, плюс `cf_clearance` привязан к UA/fingerprint; установка куки в Prowlarr → полей нет; капча-солвер → **официально non-functional** (DeepWiki FS + issue #1452). - **Исследован Кра́кен** (Alex: «на кракене вроде был капча солвер?»). Проверено на живом: солвера **нет** (только FS, `requestTimeout: 60`), карантин **идентичен Тайге** (`EscalationLevel=9`, `DisabledTill=2026-09-27`). Миф про «рабочий Кра́кен» развеян. - **Проверена инфраструктура 3x-ui/xray:** `vless-proxy` = xray-клиент (socks :1080 + http :1081, VLESS → `vpn.mallexxx.duckdns.org:443` ws/tls path `/vless`); `xray-admin` = 3x-ui, панель `:54321`. - **Собран и развёрнут свой образ `flaresolverr-vnc:latest`** — база FS + Xvfb + fluxbox + x11vnc + noVNC, под `supervisor`, 5 процессов. Профиль Chromium вынесен на persistent volume через `XDG_CONFIG_HOME=/config/chromium-profile`, FS запущен с `HEADLESS=false`. Файлы: `/mnt/RED_2TB/docker/arr/fs-vnc/{Dockerfile,supervisord.conf,entrypoint-vnc.sh}`. Compose: образ подменён, добавлены `6080:6080` и volume `/mnt/RED_2TB/docker/arr/flaresolverr-config:/config`. Бэкап `docker-compose.yml.bak-20260928-profvol`. - **Проверено:** `docker compose config -q` → OK; сборка ~215 с; контейнер `Up`; API `{"status":"ok","version":"3.5.2"}`; `http://localhost:6080/vnc.html` → **200**; каталог профиля создан. - **Новые питфоллы:** headed-Chrome → **первый запрос к `:8191` рвёт соединение** (`Connection reset by peer`), нужна пауза ~5–10 с; `sessions.destroy` несуществующей сессии → **HTTP 500**. - **Открытый вопрос:** проброшен ли порт `6080` наружу (duckdns + NAT) — проверяется только браузером Alex. - **Остаток:** ручной вход Alex в Chrome через noVNC → проверить, что cookies (`bb_data`) легли в профиль и переживают рестарт → шаг 3 (уведомление в ТГ). --- ## 🔴 ПИТФОЛЛ: порт `6080` НЕ доступен снаружи — нужен роут в Caddy (2026-09-29) **Проблема.** noVNC слушает `0.0.0.0:6080` внутри docker, но **наружу через NAT роутера порт 6080 не проброшен** (и проброшен быть не может — доступа к роутеру нет). Alex ткнул в это прямо: «а ты его пробросил блядь?!». Открытие `http://mallexxx.duckdns.org:6080/vnc.html` снаружи **не сработает**. **Решение — роут в Caddy** (тот же приём, что для `prowlarr`/`lidarr`/`jellyfin`): HTTPS-домен через уже проброшенные 8088/8443, отдельный порт наружу не нужен. ### 🔴 ПИТФОЛЛ: Caddy НЕ в сети `media_net` → `flaresolverr:6080` не резолвится Базовое состояние Caddy: сети `caddy_default` + `transmission_default`. Имени `flaresolverr` в них **нет** — `reverse_proxy flaresolverr:6080` упадёт на DNS. **Фикс (обратимый, без правки compose):** ```bash ssh truenas_admin@mallexxx.duckdns.org 'docker network connect media_net caddy' # caddy_default=172.16.1.11 media_net=172.16.17.9 transmission_default=172.16.12.3 ``` Альтернатива — указать IP `172.16.17.8`, но он **меняется** при пересоздании контейнера; подключение к сети устойчивее (Caddy резолвит по имени). ### Caddyfile — добавленный блок Файл `/mnt/RED_2TB/docker/caddy/Caddyfile` (владелец `truenas_admin`, сам каталог — `root`, поэтому бэкап кладём в домашний каталог, не рядом): ``` vnc.mallexxx.duckdns.org { basic_auth { admin $2a$14$tcfG4J1HSonHGX1rb3rsPeTkDWPmo7rpSbg/TAHhV3sRbWztWmqVa } reverse_proxy flaresolverr:6080 } ``` > 🔴 `basic_auth` **обязателен**: noVNC без пароля = открытый рабочий стол с залогиненным > RuTracker в интернете. > > 🔴 **ПИТФОЛЛ: не переиспользовать чужой bcrypt-хэш.** В первой версии блока был скопирован > хэш от `books-admin` — тот же, что у `books`/`library`. Это дало **401 даже с паролем**, > потому что логин в паре с этим хэшем — `books-admin`, а не `admin`: `basic_auth` сверяет > **пару (логин, пароль)**, а не хэш отдельно. Лечится генерацией своего: > ```bash > docker exec caddy caddy hash-password --plaintext "vnc-taiga" > # → $2a$14$tcfG4J1HSonHGX1rb3rsPeTkDWPmo7rpSbg/TAHhV3sRbWztWmqVa > ``` > Правильные креды: логин **`admin`**, пароль **`vnc-taiga`**. > ⚠️ Пароль хэшируется **до** заливки Caddyfile; в `caddy reload` ошибок не будет — просто 401. **Бэкап:** `~truenas_admin/Caddyfile.bak-20260928-novnc` (2124 B). ⚠️ `cp Caddyfile.bak-...` рядом с оригиналом → **Permission denied** (каталог root). Копировать в `~`. ### ✅ РЕЗУЛЬТАТ: роут проверен, работает Порядок, который дал рабочий результат: 1. `docker network connect media_net caddy` — **до** reload, иначе DNS не резолвится. 2. `scp` нового Caddyfile → `docker exec caddy caddy validate --config /etc/caddy/Caddyfile` → `Valid configuration`. 3. `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`. Проверка (с Mac, снаружи): ```bash curl -s -o /dev/null -w "%{http_code}\n" --max-time 25 \ -u admin:vnc-taiga https://vnc.mallexxx.duckdns.org/vnc.html # → 200 ``` ⚠️ **Первый curl может вернуть `000` (exit 35, TLS-ошибка)** — это не провал: Caddy в этот момент ещё выпускает сертификат. Сертификат **выпустился успешно** (`grep -i acme` → `authorization finalized`, `authz_status: valid`, `tls-alpn-01`), `000` был из-за гонки с выпуском. **Повторить curl через 10–20 с.** ### Два способа доступа (оба без правок роутера) | Способ | Команда / адрес | Когда | |---|---|---| | **SSH-туннель** (мгновенно) | `ssh -L 6080:truenas_admin@mallexxx.duckdns.org:6080 -N truenas_admin@mallexxx.duckdns.org` → `http://localhost:6080/vnc.html` | прямо сейчас, ничего не меняя | | **Caddy-роут** (постоянно) | `https://vnc.mallexxx.duckdns.org` (basic_auth) | постоянное решение | ### Порядок правки Caddy (проверенный) 1. Бэкап: `cp /mnt/RED_2TB/docker/caddy/Caddyfile ~/Caddyfile.bak-<дата>-<тег>` 2. `docker network connect media_net caddy` (**один раз**, до reload) 3. Правка Caddyfile **локально** (не sed на сервере) → `scp` 4. `docker exec caddy caddy reload --config /etc/caddy/Caddyfile` ⚠️ DNS-запись `vnc.mallexxx.duckdns.org` — duckdns требует добавить поддомен отдельно (или использовать wildcard `*.mallexxx.duckdns.org`, если он уже настроен на 8088/8443).