209 lines
10 KiB
Markdown
Executable File
209 lines
10 KiB
Markdown
Executable File
---
|
||
title: Arr stack — TrueNAS Taiga
|
||
created: '2026-05-23'
|
||
updated: '2026-09-29'
|
||
type: tech
|
||
namespace: family
|
||
tags: [arr, taiga, truenas, media, operations]
|
||
related:
|
||
- "[[personal/tech/flaresolverr-taiga]]"
|
||
- "[[family/how-to/truenas-infrastructure]]"
|
||
- "[[family/how-to/arr-stack-kraken]]"
|
||
---
|
||
|
||
# Arr stack — TrueNAS Taiga
|
||
|
||
Каноническая документация arr-стека на TrueNAS **Taiga**. Kraken сюда не входит.
|
||
|
||
## Текущее состояние
|
||
|
||
Проверено 2026-09-29 после полного `force-recreate`:
|
||
|
||
- `flaresolverr`, `prowlarr`, `radarr`, `sonarr`, `lidarr`, `jellyfin`, `transmission` запущены.
|
||
- `docker compose config -q` проходит.
|
||
- Lidarr → SkyHook: 10 результатов через VLESS proxy.
|
||
- Lidarr → Transmission: штатный test проходит.
|
||
- Prowlarr → RuTracker: реальный search возвращает 50 результатов.
|
||
- Prowlarr → Kinozal: реальный search возвращает 14 результатов.
|
||
- FlareSolverr: health `ok`, session `prowlarr` создаётся с proxy и pre-login.
|
||
- 3x-ui egress закреплён: Sweden master → Poland failover → текущий auto-resolve.
|
||
- Три последовательных proxy-запроса сохраняют один внешний IP.
|
||
- FlareSolverr watcher автоматически восстанавливает session и RuTracker login после потери.
|
||
|
||
Health-warning у Sonarr/Lidarr может показывать старый quarantine индексаторов. Проверять нужно реальным search и `IndexerStatus`, а не одной строкой health.
|
||
|
||
## Архитектура
|
||
|
||
| Компонент | Container | Порт | Назначение |
|
||
|---|---|---:|---|
|
||
| Prowlarr | `prowlarr` | 9696 | индексаторы и sync |
|
||
| Radarr | `radarr` | 7878 | фильмы |
|
||
| Sonarr | `sonarr` | 8989 | сериалы |
|
||
| Lidarr | `lidarr` | 8686 | музыка и SkyHook |
|
||
| FlareSolverr | `flaresolverr` | 8191 | Cloudflare/browser |
|
||
| Transmission | `transmission` | 9091 | torrent download client |
|
||
| Jellyfin | `jellyfin` | 8096 | media server |
|
||
| VLESS proxy | `vless-proxy` | 1080/1081 | SOCKS5/HTTP proxy |
|
||
|
||
Compose:
|
||
|
||
```text
|
||
/mnt/RED_2TB/docker/arr/docker-compose.yml
|
||
```
|
||
|
||
Конфигурация сервисов: `/mnt/RED_2TB/docker/arr/<service>`. Media mount внутри arr-контейнеров: `/storage`.
|
||
|
||
## Маршрутизация
|
||
|
||
1. Lidarr → `api.lidarr.audio` идёт через `http://vless-proxy:1081`.
|
||
2. FlareSolverr/Chrome → RuTracker идёт через `socks5://vless-proxy:1080`.
|
||
3. Локальный Transmission идёт напрямую по `transmission:9091`.
|
||
|
||
### Sticky egress для трекеров
|
||
|
||
Настройки 3x-ui находятся на Taiga в `/mnt/RED_2TB/docker/xray-admin/x-ui.db`. Для пользователя `vless-space` используется цепочка:
|
||
|
||
```text
|
||
space-master → sub1-sweden-yt
|
||
space-failover → sub1-poland-yt
|
||
space-auto → sub1-* / leastLoad
|
||
```
|
||
|
||
Master и первый failover не должны быть заменены общим `leastLoad`: смена egress-IP между challenge и повторным запросом инвалидирует Cloudflare-cookie.
|
||
|
||
Lidarr должен иметь:
|
||
|
||
```text
|
||
proxyEnabled=true
|
||
proxyType=http
|
||
proxyHostname=vless-proxy
|
||
proxyPort=1081
|
||
proxyBypassLocalAddresses=true
|
||
proxyBypassFilter=transmission,prowlarr
|
||
```
|
||
|
||
Pitfall: `proxyBypassLocalAddresses=false` помогает SkyHook, но одновременно отправляет локальный Transmission через VLESS и ломает его. Внешний и локальный маршруты разделены намеренно.
|
||
|
||
## FlareSolverr и RuTracker
|
||
|
||
Entrypoint:
|
||
|
||
```text
|
||
/mnt/RED_2TB/docker/arr/flaresolverr-entrypoint.sh
|
||
```
|
||
|
||
При старте он ждёт `/health`, создаёт session `prowlarr` с `socks5://vless-proxy:1080`, читает credentials RuTracker из Prowlarr SQLite в режиме `immutable=1`, выполняет pre-login и запускает основной процесс. В compose важны `PROXY_URL`, `BROWSER_TIMEOUT=180000`, `shm_size: 1gb`, `restart: unless-stopped` и read-only mount каталога Prowlarr.
|
||
|
||
После старта watcher проверяет egress-IP каждую минуту и login-состояние RuTracker каждые пять минут. При смене IP или потере login он пересоздаёт session и выполняет pre-login заново.
|
||
|
||
RuTracker должен иметь оба Prowlarr-тега:
|
||
|
||
```text
|
||
proxy + flaresolverr = [1,2]
|
||
```
|
||
|
||
Подробности: [[personal/tech/flaresolverr-taiga]].
|
||
|
||
## Перезапуск и приёмка
|
||
|
||
```bash
|
||
ssh truenas_admin@mallexxx.duckdns.org \
|
||
'cd /mnt/RED_2TB/docker/arr && docker compose config -q && docker compose up -d --force-recreate flaresolverr prowlarr radarr sonarr lidarr'
|
||
ssh truenas_admin@mallexxx.duckdns.org \
|
||
'cd /mnt/RED_2TB/docker/arr && docker compose ps'
|
||
```
|
||
|
||
FlareSolverr session:
|
||
|
||
```bash
|
||
curl -fsS -H 'Content-Type: application/json' \
|
||
-d '{"cmd":"sessions.list"}' http://127.0.0.1:8191/v1
|
||
```
|
||
|
||
Ожидается `status=ok` и session `prowlarr`.
|
||
|
||
SkyHook:
|
||
|
||
```bash
|
||
curl -H "X-Api-Key: $LIDARR_KEY" \
|
||
'http://127.0.0.1:8686/api/v1/artist/lookup?term=Astrix'
|
||
```
|
||
|
||
Ожидается непустой JSON-массив и запись VLESS о `api.lidarr.audio:443`.
|
||
|
||
RuTracker проверять реальным search, а не только `indexer/test`:
|
||
|
||
```bash
|
||
curl -H "X-Api-Key: $PROWLARR_KEY" \
|
||
'http://127.0.0.1:9696/api/v1/search?query=radiohead&type=search&indexerIds=1'
|
||
```
|
||
|
||
Ожидается непустой массив без `error` у результатов.
|
||
|
||
## Pitfalls и исправления
|
||
|
||
### Session не наследует proxy задним числом
|
||
|
||
`PROXY_URL` применяется при создании Chrome session. После изменения proxy session нужно пересоздать. Entrypoint делает это автоматически при старте FlareSolverr.
|
||
|
||
### Профиль прокси меняется между запросами
|
||
|
||
Симптом: FlareSolverr успешно решает challenge, но Prowlarr получает `Auth Failed` или timeout на следующем запросе. Причина — 3x-ui `leastLoad` выбрал другой профиль и внешний IP изменился. Исправление — pinned master/failover chain и watcher relogin; timeout сам по себе проблему не решает.
|
||
|
||
### Prowlarr API маскирует password
|
||
|
||
GET индексатора возвращает `********`. Нельзя использовать такой JSON для pre-login. Рабочий pre-login читает SQLite read-only из отдельного контейнера.
|
||
|
||
### `indexer/test` не является единственной приёмкой
|
||
|
||
Он может тестировать объект с замаскированным password и вернуть `Auth Failed`, хотя реальный search работает. Приёмка — реальный `/api/v1/search` плюс FS request с cookie `bb_session`.
|
||
|
||
### Размер HTML не доказывает login
|
||
|
||
Страница Cloudflare/Chromium может быть большой. Надёжный признак — `bb_session` и успешный запрос через ту же session.
|
||
|
||
### Quarantine может быть историческим
|
||
|
||
Перед очисткой сделать SQLite backup. Остановить Prowlarr, удалить только `IndexerStatus`, выполнить `PRAGMA quick_check`, запустить снова и повторить реальный search. Всю БД не удалять.
|
||
|
||
### `testall` создаёт ложные timeout
|
||
|
||
Параллельные browser challenges перегружают Chrome. Проверять один индексатор за раз с большим timeout.
|
||
|
||
## Массовая закачка альбомов
|
||
|
||
Альбомы скачиваются пачкой, по одному ходить не нужно:
|
||
|
||
| Сценарий | Действие |
|
||
|---|---|
|
||
| Новый артист | `Monitor` → **All** + `Start search for missing albums` — очередь на все отсутствующие альбомы |
|
||
| Уже добавлен | `Artist → Edit → Monitor: All` + **Search Monitored** |
|
||
| Вся библиотека | `Wanted → Missing → Search All` |
|
||
| Много артистов сразу | `Library Import` (`Monitor: All` каждому) или `POST /api/v1/artist` в цикле |
|
||
|
||
Один альбом за раз — только при `Monitor: Single Album` или ручном поиске лупы у альбома.
|
||
|
||
Приёмка пакетного поиска — реальный `queue`/`History` в Lidarr, а не строка health: при открытом
|
||
дефекте download-client очередь формируется, но раздачи не стартуют.
|
||
|
||
## Troubleshooting
|
||
|
||
| Симптом | Проверка | Исправление |
|
||
|---|---|---|
|
||
| SkyHook 403 | host config Lidarr и VLESS log | proxy `vless-proxy:1081`, local bypass оставить включённым |
|
||
| Transmission auth error | download-client test | синхронизировать password с текущим Transmission `PASS`; host `transmission:9091` |
|
||
| RuTracker Auth Failed | session, cookies, real search | пересоздать session/pre-login; не использовать `********` |
|
||
| DNS/Cloudflare timeout | VLESS log, FS cookies, tags | проверить `[1,2]` и `BROWSER_TIMEOUT=180000` |
|
||
| Старый health quarantine | `IndexerStatus` и real search | backup + очистка только `IndexerStatus` |
|
||
| сервис не пережил restart | compose, mounts, restart policy | проверить bind mounts и `restart: unless-stopped` |
|
||
|
||
## Backup и безопасность
|
||
|
||
Перед изменением Prowlarr DB или compose сохранять backup рядом с исходным файлом. Пароли и API keys в Obsidian не записывать.
|
||
|
||
## Связанные документы
|
||
|
||
- [[personal/tech/flaresolverr-taiga]] — FlareSolverr, session, pre-login и диагностика.
|
||
- [[family/how-to/truenas-infrastructure]] — общий TrueNAS.
|
||
- [[family/how-to/arr-stack-kraken]] — отдельный стек Kraken; не смешивать с Taiga.
|