Files
obsidian-vault/personal/tech/flaresolverr-taiga.md
T

28 KiB
Executable File
Raw Blame History

FlareSolverr на Тайге + обход блокировок индексеров

✅ СОСТОЯНИЕ 2026-09-28 (поздний вечер): ГОТОВО на всех четырёх arr-сервисах. Prowlarr — 6/6 индексеров, health → [], indexerstatus → []. Radarr — health → []. Sonarr — health → []. Lidarr — работает (SkyHook + 23 релиза); 1 warning Kinozal (M) лечится docker restart lidarr после правки proxyBypassFilter (см. питфолл в конце). Контейнер 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 (снимок 6 индексеров до правки тегов). Связка: 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)

TOTAL 256
  RuTor      100   ← был живой
  RuTracker   50   ← ВПЕРВЫЕ с 2026-05-20
  NoNaMe      50   ← ВПЕРВЫЕ
  Kinozal     50   ← ВПЕРВЫЕ
  Byrutor      6

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.

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:
    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)

  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.

✅ ЗАКРЫТО: пароль 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). Каталоги созданы:

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 ✅ выполнен
health Radarr ✅ [] — чисто
health Sonarr ✅ [] — чисто
health Lidarr ⚠️ 1 warning Kinozal (M) — дефект proxyBypassFilter, см. питфолл ниже
Библиотека Lidarr 1 артист (Radiohead), 23 релиза

Остаток (не блокирует): RuTor в Radarr/Sonarr — Query successful, but no results in the configured categories. Это не блокировка и не карантин: RuTor не отдаёт результаты в категориях фильмов/сериалов. Проверено тестом полным объектом → caps отдаёт, карантина нет.

  • Приёмка Alex в UI: https://prowlarr.mallexxx.duckdns.org → Indexers → 6 зелёных; 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 (применяется без рестарта):

# 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"
#   proxyBypassLocalAddresses: true

Скрипт: /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).

🔴 ПИТФОЛЛ: test требует ПОЛНЫЙ объект, не {id} → 400

Во всех arr-сервисах (Prowlarr, Radarr, Sonarr, Lidarr) эндпоинт POST /api/vN/indexer/test с телом {"id":N} отдаёт 400 Bad Request. Правильно — отправить полный объект индексера:

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 — тот же класс грабли, он ещё и подвешивает Sonarr (>300 с) — гонять по одному.

🔴 ПИТФОЛЛ: 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-сервисы внешне похожи, но механизм прокси у каждого свой; проверять фактическим запросом, а не по аналогии.