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

593 lines
44 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FlareSolverr на Тайге + обход блокировок индексеров
> ✅ **СОСТОЯНИЕ 2026-09-28 (поздний вечер, ФИНАЛ): ГЛАВНЫЙ ДЕФЕКТ ЗАКРЫТ — RuTracker починен Alex'ом.**
> **Prowlarr** — `health` → `[]`, `indexerstatus` → `[]`, `caps` 1/5/6 → **200**, 6/6 настроены, RuTracker **вне карантина**.
> **Radarr/Sonarr/Lidarr** — на момент последнего аудита держали **кэш health** со старым `RuTracker`;
> лечится `docker restart radarr sonarr lidarr` (команда ждала апрува Alex — не выполнена в этой сессии).
> **Lidarr** — SkyHook работает, `musicCategory=lidarr` применён (202), поиск релизов отдаёт **43** FLAC-раздачи.
> ⚠️ Открыто **1**: **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` (снимок 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`, замер 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` ниже.
## 🔑 ГЛАВНОЕ ОТКРЫТИЕ ПРО RuTracker: капча ПРИВЯЗАНА К СЕССИИ
Самый запутанный пункт. Дефект выглядел как «неверный пароль», потом как «капча»,
на самом деле — **капча выдаётся только для «холодных» сессий**.
Замеры в одном ходе (скрипты `/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**.
## ✅ ЗАКРЫТО: пароль 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 полностью чист.
- **Итог:** инфраструктура Тайги чиста и проверена. Открыт **1** дефект — RuTor
(`no results in the configured categories`, на стороне трекера). Остаток-механика:
`docker restart radarr sonarr lidarr` для сброса **кэша health** со старым RuTracker
(команда ждала апрува Alex, в этой сессии не выполнена).
### Что делать при возврате симптома «индексера недоступны»
1. `GET /api/v1/indexerstatus` в Prowlarr → кто в карантине (`disabledTill`).
2. Снять карантин: `POST /api/v1/indexer/test` **полным объектом**, по одному (не `testall`).
3. `GET /N/api?t=caps` → должен быть **200** (429 = ещё в карантине).
4. В Radarr/Sonarr: `PUT /api/v3/indexer/N?forceSave=true` → 202, затем `docker restart`.
5. Если снова падает RuTracker — это **капча**, а не пароль: проверить логин
`request.post /forum/login.php` через FS и смотреть **размер** HTML (250 KB = ОК, 13 KB = капча).