121 lines
7.3 KiB
Markdown
121 lines
7.3 KiB
Markdown
---
|
||
title: Prowlarr FlareSolverr — Cloudflare-обход и починка индексеров
|
||
created: '2026-09-20'
|
||
updated: '2026-09-20'
|
||
type: tech
|
||
namespace: personal
|
||
tags: [prowlarr, flaresolverr, cloudflare, rutracker, kinozal, torrent, arr, kraken, infra]
|
||
related:
|
||
- "[[family/how-to/arr-stack-kraken]]"
|
||
- "[[personal/projects/media-pipeline-pitfalls]]"
|
||
---
|
||
|
||
# Prowlarr + FlareSolverr — обход Cloudflare
|
||
|
||
Зеркало ключевых питфоллов скилла `torrent-agent-pipeline` (§ Питфоллы).
|
||
Контекст: 2026-09-20, Kraken. RuTracker / Kinozal / Kinozal (M) были «красными» в Prowlarr.
|
||
|
||
## Схема
|
||
|
||
```
|
||
Prowlarr (Kraken:9696) → FlareSolverr (Kraken:8191) → Cloudflare-защищённый трекер
|
||
⚠️ прокси применяется ТОЛЬКО при одинаковом tag на прокси И на индексере
|
||
```
|
||
|
||
Все контейнеры — в общей внешней сети `media_net`: radarr, sonarr, prowlarr, transmission, flaresolverr.
|
||
Проверять фактическую сеть, а не compose-файл:
|
||
```bash
|
||
ssh kraken 'sudo docker inspect -f "{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}" radarr sonarr prowlarr transmission flaresolverr'
|
||
```
|
||
|
||
## 🔴 Главная засада: прокси без tag молча не применяется
|
||
|
||
Созданный прокси (`POST /api/v1/indexerproxy`) с `tags: []` **не используется вообще** — в UI и логе Prowlarr об этом ни слова, запросы продолжают идти напрямую в Cloudflare. Прокси применяется к индексерам только когда у прокси И у каждого индексера стоит **один и тот же tag id**.
|
||
|
||
```bash
|
||
KEY=$(grep -oP "(?<=<ApiKey>)[^<]+" /srv/.../docker/prowlarr/config/config.xml)
|
||
|
||
# 1. создать тег → получить id (обычно 1)
|
||
curl -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
|
||
-d '{"label":"flaresolverr"}' http://localhost:9696/prowlarr/api/v1/tag
|
||
|
||
# 2. повесить tag на ПРОКСИ: GET целиком → jq .tags=[1] → PUT
|
||
curl -s -H "X-Api-Key: $KEY" http://localhost:9696/prowlarr/api/v1/indexerproxy/1 | jq ".tags=[1]" > /tmp/p.json
|
||
curl -X PUT -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d @/tmp/p.json \
|
||
http://localhost:9696/prowlarr/api/v1/indexerproxy/1
|
||
|
||
# 3. повесить ТОТ ЖЕ tag на индексера (RuTracker=1, Kinozal=5, Kinozal M=6)
|
||
curl -s -H "X-Api-Key: $KEY" http://localhost:9696/prowlarr/api/v1/indexer/1 | jq ".tags=[1]" > /tmp/i.json
|
||
curl -X PUT -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d @/tmp/i.json \
|
||
http://localhost:9696/prowlarr/api/v1/indexer/1
|
||
```
|
||
|
||
**Пруф работы — только лог FlareSolverr, не лог и не UI Prowlarr:**
|
||
```bash
|
||
ssh kraken 'sudo docker logs --tail 30 flaresolverr'
|
||
# → Challenge detected. Title found: Just a moment...
|
||
# → Challenge solved!
|
||
```
|
||
Непустой `GET /api/v1/indexerproxy` **не означает**, что прокси работает.
|
||
Требуется Prowlarr ≥ 2.6 (в 2.5.2 прокси-модель только вводилась).
|
||
|
||
## 🔴 Блокировка индексера в SQLite — рестарт НЕ снимает
|
||
|
||
Prowlarr сам выключает упавший индексер на 24ч (`Temporarily ignoring indexer X till +24h`), состояние в таблице `IndexerStatus` в `prowlarr.db`. `docker restart prowlarr` его **не сбрасывает** — запрос продолжает отдавать `429 Indexer is disabled till ...`.
|
||
|
||
```bash
|
||
# бэкап перед правкой БД
|
||
cp /srv/.../docker/prowlarr/config/prowlarr.db <backup>/
|
||
ssh kraken 'sudo docker stop prowlarr'
|
||
sqlite3 /srv/.../docker/prowlarr/config/prowlarr.db "DELETE FROM IndexerStatus WHERE ProviderId IN (1,5,6);"
|
||
ssh kraken 'sudo docker start prowlarr'
|
||
```
|
||
`ProviderId` = id индексера. **В контейнерах `sqlite3` НЕТ** — на хосте Kraken `/usr/bin/sqlite3` ЕСТЬ.
|
||
|
||
## ⚠️ Безопасность: FlareSolverr логирует пароли в plaintext
|
||
|
||
На `LOG_LEVEL=info` его лог печатает `postData` запроса, т.е. `login_username=...&login_password=...` **открытым текстом**. Ставить `LOG_LEVEL=warning` в compose.
|
||
Проверка после понижения: `docker logs --since 5m flaresolverr | grep -c login_password` → `0`.
|
||
|
||
```yaml
|
||
flaresolverr:
|
||
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||
environment:
|
||
- LOG_LEVEL=warning # ← не info: info пишет пароли трекеров
|
||
- BROWSER_TIMEOUT=60000
|
||
ports:
|
||
- 8191:8191
|
||
networks:
|
||
- media_net
|
||
```
|
||
|
||
## RuTor не фильтрует по категориям
|
||
|
||
В caps заявлены `2000(Movies)/5000(TV)/8000(Other)`, но с `cat=5000` отдаёт **0** результатов, без `cat` — 100. Prowlarr сам пишет в полях индексера: *«RuTor does not return categories in its search results. To sync to your apps, include 8000(Other)»*. В Sonarr/Radarr ставить категорию RuTor = `8000`, не `5000`.
|
||
|
||
## 429 в Sonarr/Radarr от упавшего индексера
|
||
|
||
`HTTP request failed: [429:TooManyRequests] [GET] at [http://prowlarr:9696/prowlarr/N/api?t=caps...]` — это **не** rate-limit трекера, а самоисключение Prowlarr. Не «ждать и повторять» — снимать `IndexerStatus`.
|
||
|
||
## Диагностические грабли
|
||
|
||
- **`POST /api/v3/indexer/test` с `{"indexerId": N}` не работает** (Radarr v6.1.1, Sonarr, Prowlarr v2.5.2) → HTTP 400 с `validationFailures` (`'Name' must not be empty`, … `'Priority' must be between 1 and 50`). Эндпоинт валидирует тело как **новый** индексер. Ответ — массив, поэтому `jq '.validationFailures'` падает с `Cannot index array with string`.
|
||
Рабочая альтернатива — `testall`:
|
||
```bash
|
||
curl -s -X POST -H "X-Api-Key: $KEY" "http://localhost:7878/radarr/api/v3/indexer/testall" \
|
||
| jq -r '.[] | "\(.id)\t\(.isValid)\t\(.validationFailures[0].errorMessage // "")"'
|
||
# Sonarr: порт 8989, UrlBase /sonarr
|
||
```
|
||
- **Prowlarr маскирует упавшие индексеры** — `GET /api/v1/health` и `/api/v1/indexerstatus` могут быть **пустыми**, пока индексер красный. Диагноз снимать из лога `<config>/logs/prowlarr.debug.txt` (НЕ `logs/prowlarr.txt`). Искать: `grep -iE "rutracker|kinozal|Cloudflare|429"`.
|
||
- **«Кто живой» быстрее всего — поиском**, не caps-тестом:
|
||
```bash
|
||
curl -s -H "X-Api-Key: $KEY" "http://localhost:9696/prowlarr/api/v1/search?query=matrix&type=search" \
|
||
| jq -r 'group_by(.indexer)[] | "\(.[0].indexer): \(length)"'
|
||
```
|
||
По умолчанию до 100 результатов на индексер — «156 всего» ≠ «по 26 на каждый».
|
||
|
||
## Источники
|
||
|
||
- Скилл: `torrent-agent-pipeline` (§ Питфоллы)
|
||
- Живой разбор: [[family/how-to/arr-stack-kraken]] — секции про починку индексера 2026-09-20
|