1207 lines
86 KiB
Markdown
Executable File
1207 lines
86 KiB
Markdown
Executable File
# 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: <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<timestamp>`),
|
||
иначе повторный прогон ломается на `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/<Artist>/ ✅
|
||
Поиск релизов: 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).
|
||
|
||
|