From 71ccf6a456706185029fb020c488af119f00c13f Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 20 Sep 2026 19:04:33 +0600 Subject: [PATCH 1/4] [2026-09-20] eagle: family/how-to/arr-stack-kraken.md family/how-to/kraken-watchtower.md family/how-to/openmediavault-rpi5.md personal/tech/docker-data-root-mount-race.md personal/tech/watchtower-docker-updates.md --- family/how-to/arr-stack-kraken.md | 68 ++++++++++ family/how-to/kraken-watchtower.md | 125 ++++++++++++++++++ family/how-to/openmediavault-rpi5.md | 2 +- personal/tech/docker-data-root-mount-race.md | 2 + personal/tech/watchtower-docker-updates.md | 132 +++++++++++++++++++ 5 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 family/how-to/kraken-watchtower.md create mode 100644 personal/tech/watchtower-docker-updates.md diff --git a/family/how-to/arr-stack-kraken.md b/family/how-to/arr-stack-kraken.md index ccef09ab..1ba2b412 100644 --- a/family/how-to/arr-stack-kraken.md +++ b/family/how-to/arr-stack-kraken.md @@ -355,6 +355,74 @@ sudo docker start prowlarr - `POST /api/v3/indexer/test` с телом `{"indexerId":N}` → HTTP 400 (валидирует как НОВЫЙ индексер, требует Name/Implementation). Для теста всех сразу: `POST /api/v3/indexer/testall`. - `GET /api/v1/health` в Prowlarr и `/api/v1/indexerstatus` НЕ показывают причины блокировки. Смотреть `.../docker/prowlarr/config/logs/prowlarr.debug.txt` (grep по имени индексера и `Cloudflare`/`403`). +## Обновление Radarr / Sonarr (2026-09-20) + +Watchtower их не обновлял (см. [[family/how-to/kraken-watchtower]]), поэтому обновлено вручную: +**Radarr 6.1.1.10360 → 6.4.4.10685**, **Sonarr 4.0.17.2952 → 4.0.20.3014**. + +```bash +# Sonarr — метаданные проекта правильные, обычный up: +cd /srv/.../docker/sonarr && sudo docker compose pull sonarr && sudo docker compose up -d sonarr +``` + +### ⚠️ Ловушка: Radarr принадлежал ЧУЖОМУ compose-проекту + +`docker compose up -d radarr` из `docker/radarr/` падал: +`Conflict. The container name "/radarr" is already in use`. + +Причина: контейнеры `radarr` и `transmission` были созданы **17.05.2026 из общего проекта `docker`** (файл `/srv/.../docker/docker-compose.yml`, **сейчас его нет — удалён**). Метаданные: `com.docker.compose.project=docker`. При этом `docker/radarr/docker-compose.yml` существовал и не использовался. + +Проверка, к какому проекту принадлежит контейнер: +```bash +sudo docker inspect radarr -f '{{index .Config.Labels "com.docker.compose.project"}} {{index .Config.Labels "com.docker.compose.project.config_files"}}' +``` + +Фикс (**данные в `config/` не трогаются**, только контейнер): +```bash +sudo docker stop radarr && sudo docker rm radarr +cd /srv/.../docker/radarr && sudo docker compose up -d radarr +# стало: project=radarr file=.../docker/radarr/docker-compose.yml, сеть media_net +``` +`transmission` остался в проекте `docker` (его compose-файл в `docker/transmission/`), но подключён к `media_net` — работает. + +### Диагностические грабли (Radarr/Sonarr API) + +- `POST /api/v3/indexer/test` с телом `{"indexerId":N}` → **HTTP 400** (валидирует как НОВЫЙ индексер, требует Name/Implementation/AppProfileId). Использовать **`POST /api/v3/indexer/testall`**. +- То же для клиентов: **`POST /api/v3/downloadclient/testall`**. +- Триггер `UrlBase`: Radarr `/radarr/api/v3/...`, Sonarr `/sonarr/api/v3/...`. + +### Итоговое состояние compose-проектов и сетей (2026-09-20) + +После всех правок важно, потому что **`docker compose up -d` надо запускать из своего каталога**, иначе будет конфликт имени контейнера. + +| Контейнер | Compose-проект | Файл | Сеть | +|---|---|---|---| +| radarr | `radarr` ✅ | `docker/radarr/docker-compose.yml` | `media_net` | +| sonarr | `sonarr` ✅ | `docker/sonarr/docker-compose.yml` | `media_net` | +| prowlarr | `prowlarr` ✅ | `docker/prowlarr/docker-compose.yml` | `media_net` | +| flaresolverr | (в том же файле prowlarr) | `docker/prowlarr/docker-compose.yml` | `media_net` | +| transmission | `docker` ⚠️ | `docker/transmission/docker-compose.yml` | `docker_default` + `media_net` | +| watchtower | `watchtower` | `docker/watchtower/docker-compose.yml` | — | + +⚠️ `transmission` остался в проекте `docker` (создан 17.05.2026 из удалённого ныне `docker/docker-compose.yml`). Его compose-файл существует, но **не используется** — при `up -d` из `docker/transmission/` будет тот же конфликт имени, что был у radarr. Чинить так же: `stop` → `rm` → `up -d` из своего каталога (данные в `config/` не трогаются). + +Проверка принадлежности любого контейнера: +```bash +sudo docker inspect -f '{{index .Config.Labels "com.docker.compose.project"}} {{index .Config.Labels "com.docker.compose.project.config_files"}}' +``` + +### Версии после обновления (2026-09-20) + +| Сервис | Версия | +|---|---| +| Radarr | **6.4.4.10685** | +| Sonarr | **4.0.20.3014** | +| Prowlarr | **2.6.5.5623** | +| FlareSolverr | 3.5.2 | +| Watchtower | **1.22.2** (`nickfedor/watchtower`, см. [[family/how-to/kraken-watchtower]]) | + +Автообновлением занимается Watchtower — **проверить его конфиг перед тем, как ждать обновлений**: [[family/how-to/kraken-watchtower]], теория — [[personal/tech/watchtower-docker-updates]]. + ## Notes - See [[arr-stack-taiga]] for Taiga (secondary) arr stack diff --git a/family/how-to/kraken-watchtower.md b/family/how-to/kraken-watchtower.md new file mode 100644 index 00000000..51cecaf8 --- /dev/null +++ b/family/how-to/kraken-watchtower.md @@ -0,0 +1,125 @@ +--- +updated: '2026-09-20' +title: Watchtower — Kraken +created: '2026-09-20' +type: tech +namespace: family +tags: + - watchtower + - docker + - updates + - infra + - kraken +related: + - '[[family/how-to/arr-stack-kraken]]' + - '[[personal/tech/watchtower-docker-updates]]' + - '[[personal/tech/jellyfin-db-schema-mismatch]]' + - '[[personal/tech/docker-data-root-mount-race]]' +--- +# Watchtower на Kraken (RPi5 / OMV / arm64) + +> **Создано:** 2026-09-20. **Статус:** ✅ работает, версия 1.22.2 (форк nickfedor). +> ⏳ **Открытый пункт:** `--label-enable` включён, но label НЕТ ни у одного контейнера → **сейчас Watchtower не обновит ничего**. Ждёт решения Alex: вариант 1 (повесить label на radarr/sonarr/prowlarr/flaresolverr) или вариант 2 (убрать `--label-enable`, обновлять все 12). +> **Связанные:** [[family/how-to/arr-stack-kraken]], [[personal/tech/watchtower-docker-updates]] (реюзабельная теория), [[personal/tech/jellyfin-db-schema-mismatch]], [[personal/tech/docker-data-root-mount-race]] + +## Что было сломано (2026-09-20) + +Watchtower стоял на `containrrr/watchtower` **без единого флага** и **не обновил ни один контейнер за ~2.5 месяца**. + +Четыре независимые причины: + +| # | Причина | Как выглядело в логе | +|---|---|---| +| 1 | Не задан `--interval` | `Scheduling first run: ... in 23 hours 59 minutes` — каждый рестарт контейнера сбрасывал таймер, а рестарты были | +| 2 | `DOCKER_API_VERSION=1.40` (старый API) | `Unable to update container "/prowlarr": no available image info` | +| 3 | Образ `containrrr/watchtower` мёртв | last push **2023-11-11** (проверено через Docker Hub API) | +| 4 | Нет label на целевых контейнерах | `Scanned=12 Updated=0` | + +Итог до фикса: `Session done Failed=0 Scanned=12 Updated=0`, а единственная попытка обновления упала с `no available image info`. + +## Фикс (ВЫПОЛНЕН 2026-09-20) + +`containrrr/watchtower` → **`nickfedor/watchtower:1.22.2`** (активный форк; у containrrr последний push 2023-11-11). + +```bash +D=/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker/watchtower +sudo cp $D/docker-compose.yml /home/kraken/arr-fix-backup-20260920/watchtower-compose.bak +cd $D && sudo docker compose pull watchtower && sudo docker compose up -d watchtower +``` + +Compose (`docker/watchtower/docker-compose.yml`): +```yaml +services: + watchtower: + image: nickfedor/watchtower:1.22.2 + container_name: watchtower + restart: always + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: --interval 86400 --cleanup --label-enable + # DOCKER_API_VERSION=1.40 УДАЛЁН — именно он ломал обновление +``` + +Флаги: +- `--interval 86400` — явные 24ч (без флага таймер сбрасывался каждым стартом) +- `--cleanup` — удалять старые образы (диск на 87%, иначе забьёт) +- `--label-enable` — обновлять ТОЛЬКО контейнеры с label `com.centurylinklabs.watchtower.enable=true` + +## Проверка (обязательна — «запущено» ≠ «работает») + +```bash +# 1) версия и API +sudo docker logs --tail 20 watchtower +# → Watchtower 1.22.2 using Docker API v1.54 (был v1.40) +# → Next scheduled run: ... in 23 hours 59 minutes ← таймер виДЕН + +# 2) РЕАЛЬНЫЙ прогон без изменений +sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + nickfedor/watchtower:1.22.2 --run-once --monitor-only +# → Update session completed failed=0 scanned=13 updated=0 +# → "Found new image" container=transmission ← баг no-available-image-info ВЫЛЕЧЕН +``` + +## ⚠️ КРИТИЧНО: `--label-enable` и Jellyfin + +**Watchtower уже один раз сломал Jellyfin** (см. [[personal/tech/jellyfin-db-schema-mismatch]]): переключил мажорную версию 10.11.8 → 12.1, БД мигрировала вперёд, сервер перестал стартовать с `no such column: p.Permission_Permissions_Guid`, Jellyfin отдавал 503. + +Поэтому **Jellyfin нельзя давать в автообновление без пина тега**. Если ставить ему label — сначала заменить `image: jellyfin/jellyfin` (без тега = latest) на пиновый, например `jellyfin/jellyfin:12.1`. + +Правило: `latest` + автомажор = риск сломать БД (EF Core не умеет даунгрейд схемы). Для сервисов с миграциями БД пинить мажорную версию. + +## Диагностика Watchtower + +```bash +sudo docker ps --format "{{.Names}}\t{{.Image}}\t{{.Status}}" | grep watchtower +sudo docker logs --tail 40 watchtower +# кто помечен для автообновления: +for c in $(sudo docker ps --format "{{.Names}}"); do + echo "$c -> $(sudo docker inspect $c -f '{{index .Config.Labels "com.centurylinklabs.watchtower.enable"}}')" +done +``` + +Грабли: +- `Unable to update container: no available image info` — старый `DOCKER_API_VERSION`, либо несовместимость containrrr-версии с новым dockerd. +- **Рестарт контейнера сбрасывает таймер** — без `--interval` это делает Watchtower бесполезным. +- `--run-once` **нельзя** запускать без `--monitor-only`, если не хочешь реальных обновлений. +- Watchtower пишет в stdout (`docker logs`), в отличие от Jellyfin. + +## Бэкап + +`/home/kraken/arr-fix-backup-20260920/watchtower-compose.bak` + остальные бэкапы в той же папке: +- `radarr-config-preupgrade.tar.gz` (58M), `sonarr-config-preupgrade.tar.gz` (20M), `prowlarr-config-preupgrade.tar.gz` (3.9M) +- `prowlarr.db.bak`, `watchtower-compose.bak`, `networks.txt`, 4× `-inspect.json`, 3× compose-файла + +## Что дальше (открытые пункты) + +| # | Пункт | Статус | +|---|---|---| +| 1 | Решить вариант 1 / вариант 2 для `--label-enable` и проставить label | ⏳ ждёт Alex | +| 2 | `Allowed Hosts is not configured` warning в Radarr/Sonarr/Prowlarr — ограничить, какие hostname могут обращаться | ⏳ отдельная задача | +| 3 | Найдены новые образы при прогоне: `portainer`, `cloudflared`, `transmission` — обновить при необходимости | ℹ️ не делалось (transmission без label, portainer/cloudflared — свои тонкости) | +| 4 | Home Assistant на Kraken — `Exited (128)` ~2 месяца, не поднимался (см. [[family/how-to/kraken-access]]) | ⏳ отдельная задача | + +## Теория (реюзабельно) + +Общие причины «Watchtower не обновляет» без привязки к Kraken — [[personal/tech/watchtower-docker-updates]]. diff --git a/family/how-to/openmediavault-rpi5.md b/family/how-to/openmediavault-rpi5.md index 78cb144b..400ed9aa 100644 --- a/family/how-to/openmediavault-rpi5.md +++ b/family/how-to/openmediavault-rpi5.md @@ -272,7 +272,7 @@ cd /home/kraken/ && sudo docker compose restart # рестарт cd /home/kraken/ && sudo docker compose pull && sudo docker compose up -d # обновить ``` -> ⚠️ Watchtower: нужна переменная `DOCKER_API_VERSION=1.54` — иначе крашится (API mismatch) +> ⚠️ Watchtower: `DOCKER_API_VERSION` **убирать** (2026-09-20). Ранее здесь стояло `DOCKER_API_VERSION=1.40`, и именно он вместе с «no available image info» ломал обновление. Пиннинг версии API вообще не нужен — новая версия Watchtower сама согласует её с dockerd (`using Docker API v1.54`). Полный разбор: [[family/how-to/kraken-watchtower]], теория — [[personal/tech/watchtower-docker-updates]]. > ⚠️ sudo через SSH требует `< /dev/null` для каждой команды с tee/pipe --- diff --git a/personal/tech/docker-data-root-mount-race.md b/personal/tech/docker-data-root-mount-race.md index 6388a3dc..d7e45203 100644 --- a/personal/tech/docker-data-root-mount-race.md +++ b/personal/tech/docker-data-root-mount-race.md @@ -95,6 +95,8 @@ ssh kraken 'docker ps -q | wc -l' # ожидаем ~12, НЕ 0 > ⚠️ **Не путать с другим дефектом:** после этого reboot `jellyfin` поднялся, но отдавал **503** — это **отдельная** проблема (сервер старше БД, `no such column: p.Permission_Permissions_Guid`), НЕ связанная с гонкой монтирования. См. [[personal/tech/jellyfin-db-schema-mismatch]]. При диагностике «сервис не работает после reboot» различать: контейнер не поднялся (гонка) vs поднялся, но падает внутри (своя ошибка приложения). +> ℹ️ **Обновление 2026-09-20 (позже в тот же день):** `radarr` был **пересоздан** (переведён из общего проекта `docker` в свой `docker/radarr`, обновлён до 6.4.4) — см. [[family/how-to/arr-stack-kraken]]. `watchtower` сменил образ на `nickfedor/watchtower:1.22.2` — см. [[family/how-to/kraken-watchtower]]. Число контейнеров и их состав могли измениться; проверка `docker ps -q | wc -l` по-прежнему корректна как индикатор гонки, но ожидаемое число сверять заново. + ## Крон не догоняет пропущенное окно Общий питфолл для сервисов на этом узле: если Kraken лежал, cron-задачи (бэкап `0 4 * * *`, t610-подобные) **пропускаются без компенсации**. Для критичных — добавлять `@reboot`-строку с проверкой «артефакт за сегодня уже есть?». diff --git a/personal/tech/watchtower-docker-updates.md b/personal/tech/watchtower-docker-updates.md new file mode 100644 index 00000000..b9786943 --- /dev/null +++ b/personal/tech/watchtower-docker-updates.md @@ -0,0 +1,132 @@ +--- +title: Watchtower — почему не обновляет контейнеры +created: '2026-09-20' +updated: '2026-09-20' +type: tech +namespace: personal +tags: [watchtower, docker, updates, infra, pitfall] +related: + - "[[family/how-to/kraken-watchtower]]" + - "[[personal/tech/docker-data-root-mount-race]]" + - "[[personal/tech/jellyfin-db-schema-mismatch]]" +--- + +# Watchtower — почему не обновляет контейнеры + +Реюзабельная теория. Живой разбор на Kraken — в [[family/how-to/kraken-watchtower]]. + +**Главный вывод: `docker ps` показывает `Up (healthy)` — это ничего не говорит о том, что Watchtower хоть раз что-то обновил.** Отсутствие обновлений не даёт ни ошибки, ни алерта. На Kraken Watchtower «работал» 2.5 месяца и не обновил ни один из 12 контейнеров. + +## Четыре причины (проверять в этом порядке) + +### 1. Не задан `--interval` → таймер сбрасывается каждым стартом +Без флага интервал = 24ч **от момента старта процесса**. Любой рестарт контейнера (reboot, `docker restart`, обновление самого Watchtower) обнуляет отсчёт. Если контейнер рестартуют чаще раза в сутки — **проверка не наступает никогда**. + +Признак в логе: +``` +level=info msg="Scheduling first run: ... in 23 hours, 59 minutes, 59 seconds" +level=info msg="Waiting for running update to be finished..." +``` +Вторая строка — процесс проснулся, увидел незавершённый апдейт и **снова уснул**. Признак, что цикл заклинило. + +**Фикс:** `--interval 86400` явно, либо `--schedule "0 0 4 * * *"` (cron-синтаксис из 6 полей), если нужен запуск в тихое время. + +### 2. `DOCKER_API_VERSION` запинен на старую версию +`DOCKER_API_VERSION=1.40` в environment **ломает** чтение метаданных образа. Симптом: +``` +level=info msg="Found new lscr.io/linuxserver/prowlarr:latest image (3e9bd62ca90c)" +level=info msg="Unable to update container \"/prowlarr\": no available image info. Proceeding to next." +``` +Watchtower **нашёл** новый образ, но не может обновиться. В новых версиях API показывается сам: `using Docker API v1.54`. + +**Фикс:** убрать `DOCKER_API_VERSION` из environment вообще. Watchtower сам согласует версию с dockerd. + +### 3. Образ `containrrr/watchtower` не развивается +Last push `containrrr/watchtower` — **2023-11-11** (проверено Docker Hub API). Он несовместим с современным dockerd, отсюда и `no available image info` — это не только про API-версию. + +**Фикс:** активный форк `nickfedor/watchtower` (актуальная версия 1.22.2, теги `latest`, `nightly`, semver). + +```bash +# проверить дату образа +curl -s "https://hub.docker.com/v2/repositories/containrrr/watchtower/tags?page_size=5" \ + | jq -r '.results[] | "\(.name) updated=\(.last_updated)"' + +# проверить поддержку своей архитектуры (например arm64 для RPi) +curl -s "https://hub.docker.com/v2/repositories/nickfedor/watchtower/tags/1.22.2" \ + | jq -r '.images[] | "\(.architecture) \(.os)"' +``` + +### 4. `--label-enable` без единого label → не обновит НИЧЕГО +С флагом `--label-enable` Watchtower трогает только контейнеры с label +`com.centurylinklabs.watchtower.enable=true`. Если label нет ни у кого — **сам по себе флаг делает Watchtower бесполезным**. + +Проверка, кто помечен: +```bash +for c in $(docker ps --format "{{.Names}}"); do + echo "$c -> $(docker inspect $c -f '{{index .Config.Labels "com.centurylinklabs.watchtower.enable"}}')" +done +``` +⚠️ `docker inspect` на контейнере без label вернёт **пустую строку**, а не «false» — не путать с `false` (явное отключение). + +## Рабочий конфиг + +```yaml +services: + watchtower: + image: nickfedor/watchtower:1.22.2 + container_name: watchtower + restart: always + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: --interval 86400 --cleanup --label-enable + # НЕ добавлять DOCKER_API_VERSION +``` +- `--interval 86400` — сутки, видно в логе рядом со `Next scheduled run` +- `--cleanup` — удалять старые образы; без него диск забивается (на Kraken 87%) +- `--label-enable` — оптин: обновляется только то, что явно помечено + +## Проверка (обязательна) + +`Up` + отсутствие ошибок ≠ работа. Нужен живой прогон: +```bash +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + nickfedor/watchtower:1.22.2 --run-once --monitor-only +``` +`--monitor-only` обязателен, иначе `--run-once` **реально обновит** контейнеры. + +Что должно быть в выводе: +``` +level=info msg="Watchtower 1.22.2 using Docker API v1.54" +level=info msg="Found new image" container= new_id=<...> +level=info msg="Update session completed" failed=0 scanned=N skipped=0 updated=0 +``` +`Found new image` = баг с метаданными вылечен. `updated=0` в monitor-only — нормально. + +## ⚠️ Автообновление может сломать сервис: пинить мажор версии + +Тип `latest` + автообновление = переход на новую **мажорную** версию без предупреждения. Для сервисов с миграциями БД (EF Core, Prisma, любые forward-only миграции) это необратимо: + +- Jellyfin на Kraken: `latest` уехал 10.11.8 → 12.1, БД мигрировала вперёд, откатить схему нельзя → сервер отдавал **503**, `no such column: ...`. Детали: [[personal/tech/jellyfin-db-schema-mismatch]]. + +**Правило:** сервисам с БД и миграциями — пиновый тег (`image: jellyfin/jellyfin:12.1`), НЕ `latest` + watchtower. Либо не давать им label, либо сначала пин. + +## Питфоллы диагностики + +- `docker logs watchtower` — Watchtower пишет в **stdout**, в отличие от Jellyfin (тот пишет в файл). Смотреть логи легко. +- Таймстемпы в логе Watchtower — **UTC**, локальное время сервиса может быть другим. +- Единожды увиденный `Found new image` не значит, что обновление применилось — нужна следующая строка (`Unable to update` / `Updated`). +- Проверять надо **фактическую** дату запущенного образа, а не тег: + ```bash + docker inspect -f '{{index .Config.Labels "org.opencontainers.image.version"}}' + docker inspect -f '{{index .Config.Labels "build_version"}}' + ``` + +## Урок + +Watchtower — компонент, который **молча не работает**. Его нельзя «поставить и забыть»: обязательны (а) явный `--interval`, (б) отсутствие `DOCKER_API_VERSION`, (в) периодический `--run-once --monitor-only` как health-check, (г) осознанное решение, каким контейнерам вообще разрешено автообновление. + +## Связанные + +- [[family/how-to/kraken-watchtower]] — живой разбор и точные команды на Kraken +- [[personal/tech/jellyfin-db-schema-mismatch]] — что ломает автообновление мажора +- [[personal/tech/docker-data-root-mount-race]] — другой дефект «контейнеры пропали» From 9432cee44e95ee7b002b6b4ec0f44db9f5baf72f Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 20 Sep 2026 19:14:40 +0600 Subject: [PATCH 2/4] [2026-09-20] eagle: family/how-to/arr-stack-kraken.md family/how-to/kraken-watchtower.md personal/tech/watchtower-docker-updates.md --- family/how-to/arr-stack-kraken.md | 14 +++++ family/how-to/kraken-watchtower.md | 66 ++++++++++++++++++---- personal/tech/watchtower-docker-updates.md | 6 +- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/family/how-to/arr-stack-kraken.md b/family/how-to/arr-stack-kraken.md index 1ba2b412..900097dd 100644 --- a/family/how-to/arr-stack-kraken.md +++ b/family/how-to/arr-stack-kraken.md @@ -423,6 +423,20 @@ sudo docker inspect -f '{{index .Config.Labels "com.docker.compose.projec Автообновлением занимается Watchtower — **проверить его конфиг перед тем, как ждать обновлений**: [[family/how-to/kraken-watchtower]], теория — [[personal/tech/watchtower-docker-updates]]. +## Автообновление (Watchtower) — 2026-09-20 + +Все сервисы стека (`radarr`, `sonarr`, `prowlarr`, `flaresolverr`, `transmission`) **плюс `jellyfin` и `portainer`** размечены label `com.centurylinklabs.watchtower.enable=true` → обновляются автоматически (7 контейнеров, проверено `scanned=7`). Полный разбор и список того, что НЕ обновляется: [[family/how-to/kraken-watchtower]]. + +Актуальные версии на 2026-09-20: + +| Сервис | Версия | +|---|---| +| Radarr | 6.4.4.10685 | +| Sonarr | 4.0.20.3014 | +| Prowlarr | 2.6.5.5623 | +| FlareSolverr | 3.5.2 | +| Watchtower | 1.22.2 (nickfedor) | + ## Notes - See [[arr-stack-taiga]] for Taiga (secondary) arr stack diff --git a/family/how-to/kraken-watchtower.md b/family/how-to/kraken-watchtower.md index 51cecaf8..c79deb3b 100644 --- a/family/how-to/kraken-watchtower.md +++ b/family/how-to/kraken-watchtower.md @@ -18,10 +18,45 @@ related: --- # Watchtower на Kraken (RPi5 / OMV / arm64) -> **Создано:** 2026-09-20. **Статус:** ✅ работает, версия 1.22.2 (форк nickfedor). -> ⏳ **Открытый пункт:** `--label-enable` включён, но label НЕТ ни у одного контейнера → **сейчас Watchtower не обновит ничего**. Ждёт решения Alex: вариант 1 (повесить label на radarr/sonarr/prowlarr/flaresolverr) или вариант 2 (убрать `--label-enable`, обновлять все 12). +> **Создано:** 2026-09-20. **Статус:** ✅ ЗАВЕРШЕНО — версия 1.22.2 (форк nickfedor), label проставлены на 7 контейнеров, проверено прогоном `scanned=7 failed=0`. > **Связанные:** [[family/how-to/arr-stack-kraken]], [[personal/tech/watchtower-docker-updates]] (реюзабельная теория), [[personal/tech/jellyfin-db-schema-mismatch]], [[personal/tech/docker-data-root-mount-race]] +## ✅ РЕШЕНИЕ (2026-09-20): какие контейнеры обновляются автоматом + +Решение Alex: «вариант 1 + jellyfin, portainer, transmission». Итого **7 контейнеров размечены** label `com.centurylinklabs.watchtower.enable=true`: + +| Контейнер | Где label | Примечание | +|---|---|---| +| `radarr` | `docker/radarr/docker-compose.yml` | | +| `sonarr` | `docker/sonarr/docker-compose.yml` | | +| `prowlarr` | `docker/prowlarr/docker-compose.yml` | | +| `flaresolverr` | `docker/prowlarr/docker-compose.yml` | тот же файл | +| `jellyfin` | `docker/jellyfin/docker-compose.yml` | ⚠️ тег `latest` — см. ниже | +| `portainer` | `docker/portainer/docker-compose.yml` | данные в `/data`, пересоздание безопасно | +| `transmission` | `docker/transmission/docker-compose.yml` | 244 торрента в `./` (config), пересоздание данные не задело | + +**НЕ размечены (сознательно):** +- `watchtower` — сам себя (иначе зацикливание) +- `hermes-kraken` — агент Hermes +- `xray-reverse-bridge` — VPN-мост +- `rclone`, `cloudflared` + +Проверка после простановки: +```bash +sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + nickfedor/watchtower:1.22.2 --run-once --monitor-only --label-enable +# → Update session completed failed=0 scanned=7 updated=0 ← ровно 7, не 13 +``` + +### Про Jellyfin и тег (решение Alex) + +Алекс явно потребовал: **«пусть ставит до всех публичных релизов»** → стоит `image: jellyfin/jellyfin:latest`, Watchtower поставит в т.ч. мажор 13. + +Моя рекомендация была пинить `12` (после инцидента `jellyfin-db-schema-mismatch`, где контейнер остался на старом образе при уже мигрированной БД и отдавал 503). **Алекс выбрал `latest` — риск принят осознанно.** Если Jellyfin однажды отдаст 503 после автообновления — смотреть [[personal/tech/jellyfin-db-schema-mismatch]], бэкап БД: `/home/kraken/backups/jellyfin-label-20260920-190935/`. + +⚠️ Важное следствие `--cleanup`: старые образы удаляются, откатиться на предыдущую версию после автообновления будет **некуда**. + + ## Что было сломано (2026-09-20) Watchtower стоял на `containrrr/watchtower` **без единого флага** и **не обновил ни один контейнер за ~2.5 месяца**. @@ -73,20 +108,29 @@ sudo docker logs --tail 20 watchtower # → Watchtower 1.22.2 using Docker API v1.54 (был v1.40) # → Next scheduled run: ... in 23 hours 59 minutes ← таймер виДЕН -# 2) РЕАЛЬНЫЙ прогон без изменений +# 2) РЕАЛЬНЫЙ прогон без изменений — БЕЗ label (сравнение) sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ nickfedor/watchtower:1.22.2 --run-once --monitor-only # → Update session completed failed=0 scanned=13 updated=0 # → "Found new image" container=transmission ← баг no-available-image-info ВЫЛЕЧЕН + +# 3) С label (актуальный режим) → должно быть ровно 7 +sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + nickfedor/watchtower:1.22.2 --run-once --monitor-only --label-enable +# → Update session completed failed=0 scanned=7 updated=0 ``` -## ⚠️ КРИТИЧНО: `--label-enable` и Jellyfin +## ⚠️ КРИТИЧНО: Watchtower и Jellyfin — история и принятое решение -**Watchtower уже один раз сломал Jellyfin** (см. [[personal/tech/jellyfin-db-schema-mismatch]]): переключил мажорную версию 10.11.8 → 12.1, БД мигрировала вперёд, сервер перестал стартовать с `no such column: p.Permission_Permissions_Guid`, Jellyfin отдавал 503. +**Watchtower уже один раз сломал Jellyfin** (см. [[personal/tech/jellyfin-db-schema-mismatch]]): контейнер остался на старом образе 10.11.8 при уже мигрированной до 12.1 БД → `no such column: p.Permission_Permissions_Guid` → 503. -Поэтому **Jellyfin нельзя давать в автообновление без пина тега**. Если ставить ему label — сначала заменить `image: jellyfin/jellyfin` (без тега = latest) на пиновый, например `jellyfin/jellyfin:12.1`. +Разбор инцидента показывает: **сама миграция БД прошла нормально**, упало из-за рассинхрона «старый сервер + новая схема». То есть мажорный апдейт сам по себе БД не ломает. -Правило: `latest` + автомажор = риск сломать БД (EF Core не умеет даунгрейд схемы). Для сервисов с миграциями БД пинить мажорную версию. +**Решение Alex (2026-09-20):** тег `latest`, обновляемся до всех публичных релизов, включая мажор 13. Риск принят осознанно. Бэкап БД перед пересозданием: `/home/kraken/backups/jellyfin-label-20260920-190935/` (24 МБ). + +**Если Jellyfin отдаёт 503 после автообновления** — это тот же класс проблемы: смотреть `personal/tech/jellyfin-db-schema-mismatch`, проверить `docker exec jellyfin /jellyfin/jellyfin --version` против версии в `__EFMigrationsHistory`. + +⚠️ Следствие `--cleanup`: старые образы удаляются, откат на предыдущую версию **после** автообновления невозможен. Если нужен откат — только полный restore БД из бэкапа. ## Диагностика Watchtower @@ -115,10 +159,10 @@ done | # | Пункт | Статус | |---|---|---| -| 1 | Решить вариант 1 / вариант 2 для `--label-enable` и проставить label | ⏳ ждёт Alex | -| 2 | `Allowed Hosts is not configured` warning в Radarr/Sonarr/Prowlarr — ограничить, какие hostname могут обращаться | ⏳ отдельная задача | -| 3 | Найдены новые образы при прогоне: `portainer`, `cloudflared`, `transmission` — обновить при необходимости | ℹ️ не делалось (transmission без label, portainer/cloudflared — свои тонкости) | -| 4 | Home Assistant на Kraken — `Exited (128)` ~2 месяца, не поднимался (см. [[family/how-to/kraken-access]]) | ⏳ отдельная задача | +| 1 | `Allowed Hosts is not configured` warning в Radarr/Sonarr/Prowlarr — ограничить, какие hostname могут обращаться | ⏳ отдельная задача | +| 2 | Home Assistant на Kraken — `Exited (128)` ~2 месяца, не поднимался (см. [[family/how-to/kraken-access]]) | ⏳ отдельная задача | + +✅ Закрыто 2026-09-20: label проставлены, решение по Jellyfin принято (`latest`), первый прогон с label прошёл (`scanned=7 failed=0`). ## Теория (реюзабельно) diff --git a/personal/tech/watchtower-docker-updates.md b/personal/tech/watchtower-docker-updates.md index b9786943..fd655004 100644 --- a/personal/tech/watchtower-docker-updates.md +++ b/personal/tech/watchtower-docker-updates.md @@ -108,7 +108,11 @@ level=info msg="Update session completed" failed=0 scanned=N skipped=0 updated=0 - Jellyfin на Kraken: `latest` уехал 10.11.8 → 12.1, БД мигрировала вперёд, откатить схему нельзя → сервер отдавал **503**, `no such column: ...`. Детали: [[personal/tech/jellyfin-db-schema-mismatch]]. -**Правило:** сервисам с БД и миграциями — пиновый тег (`image: jellyfin/jellyfin:12.1`), НЕ `latest` + watchtower. Либо не давать им label, либо сначала пин. +**Правило (общее):** сервисам с forward-only миграциями БД безопаснее пиновый тег (`image: jellyfin/jellyfin:12.1`), а не `latest` + автообновление. + +⚠️ **Но это рекомендация, не аксиома — на Kraken решено иначе.** Alex 2026-09-20 явно выбрал `latest` для Jellyfin: «пусть ставит до всех публичных релизов», т.е. включая мажор 13. Риск принят осознанно, бэкап БД делается перед пересозданием. См. [[family/how-to/kraken-watchtower]] § «Про Jellyfin и тег». + +Отдельно важный нюанс: **упал не мажорный апдейт как таковой**, а рассинхрон «контейнер на старом образе + уже мигрированная БД». Сама миграция прошла нормально. То есть мажорный апдейт БД не ломает — ломает откат сервера назад без отката схемы. ## Питфоллы диагностики From 20f2b2a39d8392cda55637d39c347c9455f01f63 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 20 Sep 2026 19:19:43 +0600 Subject: [PATCH 3/4] [2026-09-20] eagle: family/how-to/arr-stack-kraken.md --- family/how-to/arr-stack-kraken.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/family/how-to/arr-stack-kraken.md b/family/how-to/arr-stack-kraken.md index 900097dd..ac43681d 100644 --- a/family/how-to/arr-stack-kraken.md +++ b/family/how-to/arr-stack-kraken.md @@ -241,7 +241,7 @@ curl -s -H "X-Api-Key: $PKEY" "http://localhost:9696/prowlarr/api/v1/search?quer ## Radarr Quality Profiles на Kraken (проверено 2026-09-04) -Via `http://kraken:7878/radarr/api/v3/qualityprofile` (X-Api-Key из config.xml; **UrlBase=`/radarr`**). Radarr v6.1.1.10360, Linuxserver image, net `docker_default`. +Via `http://kraken:7878/radarr/api/v3/qualityprofile` (X-Api-Key из config.xml; **UrlBase=`/radarr`**). Linuxserver image, сеть `media_net` (с 2026-09-20; ранее ошибочно жил в `docker_default`). Версия — см. таблицу актуальных версий ниже. | id | Профиль | Разрешённые качества | Cutoff | |----|---------|----------------------|--------| @@ -401,10 +401,15 @@ cd /srv/.../docker/radarr && sudo docker compose up -d radarr | sonarr | `sonarr` ✅ | `docker/sonarr/docker-compose.yml` | `media_net` | | prowlarr | `prowlarr` ✅ | `docker/prowlarr/docker-compose.yml` | `media_net` | | flaresolverr | (в том же файле prowlarr) | `docker/prowlarr/docker-compose.yml` | `media_net` | -| transmission | `docker` ⚠️ | `docker/transmission/docker-compose.yml` | `docker_default` + `media_net` | +| transmission | `transmission` ✅ | `docker/transmission/docker-compose.yml` | `media_net` | | watchtower | `watchtower` | `docker/watchtower/docker-compose.yml` | — | -⚠️ `transmission` остался в проекте `docker` (создан 17.05.2026 из удалённого ныне `docker/docker-compose.yml`). Его compose-файл существует, но **не используется** — при `up -d` из `docker/transmission/` будет тот же конфликт имени, что был у radarr. Чинить так же: `stop` → `rm` → `up -d` из своего каталога (данные в `config/` не трогаются). +✅ **`transmission` тоже исправлен (2026-09-20, позже в той же сессии).** Был в проекте `docker`, пересоздан так же: `stop` → `rm` → `up -d` из `docker/transmission/`. Данные **не пострадали**: 244 торрента в `./torrents/` + 244 resume-файла на месте, RPC вернул `torrents: 244`. Проверка перед пересозданием обязательна — считать торренты ДО и ПОСЛЕ: +```bash +sudo ls $D/transmission/torrents/ | wc -l # до и после должно совпасть +``` + +**Общее правило:** если `docker compose up -d` даёт `Conflict. The container name "/X" is already in use` — контейнер принадлежит чужому (возможно, удалённому) compose-проекту. Смотреть `com.docker.compose.project` и `project.config_files`, затем `stop` → `rm` → `up -d` из правильного каталога. Данные в bind-mount (`config/`, `torrents/`) при этом не трогаются. Проверка принадлежности любого контейнера: ```bash @@ -425,17 +430,7 @@ sudo docker inspect -f '{{index .Config.Labels "com.docker.compose.projec ## Автообновление (Watchtower) — 2026-09-20 -Все сервисы стека (`radarr`, `sonarr`, `prowlarr`, `flaresolverr`, `transmission`) **плюс `jellyfin` и `portainer`** размечены label `com.centurylinklabs.watchtower.enable=true` → обновляются автоматически (7 контейнеров, проверено `scanned=7`). Полный разбор и список того, что НЕ обновляется: [[family/how-to/kraken-watchtower]]. - -Актуальные версии на 2026-09-20: - -| Сервис | Версия | -|---|---| -| Radarr | 6.4.4.10685 | -| Sonarr | 4.0.20.3014 | -| Prowlarr | 2.6.5.5623 | -| FlareSolverr | 3.5.2 | -| Watchtower | 1.22.2 (nickfedor) | +Все сервисы стека (`radarr`, `sonarr`, `prowlarr`, `flaresolverr`, `transmission`) **плюс `jellyfin` и `portainer`** размечены label `com.centurylinklabs.watchtower.enable=true` → обновляются автоматически (7 контейнеров, проверено `scanned=7`). Полный разбор и список того, что НЕ обновляется: [[family/how-to/kraken-watchtower]]. Теория: [[personal/tech/watchtower-docker-updates]]. ## Notes From cbaaa76ad7c876f77114b98aee2780188168a31e Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 20 Sep 2026 19:24:47 +0600 Subject: [PATCH 4/4] [2026-09-20] eagle: family/projects/watchlist-automation.md --- family/projects/watchlist-automation.md | 35 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/family/projects/watchlist-automation.md b/family/projects/watchlist-automation.md index f7986282..86f37c81 100644 --- a/family/projects/watchlist-automation.md +++ b/family/projects/watchlist-automation.md @@ -1,7 +1,7 @@ --- created: '2026-05-20' -updated: '2026-09-04' -status: active +updated: '2026-09-20' +status: broken tags: - kraken - watchlist @@ -62,14 +62,39 @@ Jellyfin (8096) → rescan → виден контент **Важно:** `process_thumbs` автоматически определяет отступ из `## Фильмы` и сохраняет при переносе. `SECTION_THUMBDN = "## Новинки👎"` (без пробела) — должно точно совпадать с заголовком. +## 🔴 Pipeline МЁРТВ с 2026-06-20 (аудит 2026-09-20) + +**Автодобавление фильмов НЕ работает.** Скрипты живы, но их никто не запускает. + +Доказательства (проверено 2026-09-20): +- `crontab -l` юзера `kraken` — watchlist-строк **НЕТ**. Есть только `sync-vault.sh` (каждый час) и два `pgs-to-srt` (часовой + 03:00). +- root crontab и `/etc/cron.d/`: `grep -rl watchlist` → пусто. +- systemd timers (user + system) → 0 штук. +- Внутри Hermes-контейнера на Кракене: `docker exec hermes-kraken /opt/hermes/.venv/bin/hermes cron list` → **"No scheduled jobs."** +- Последний коммит автором `Hermes` (= nightly-скрипт) — **2026-06-20**. Распределение по месяцам: май 1, июнь 9, июль/август/сентябрь — **0**. Единственные коммиты в vault после июня — от `eagle`, `syncthing`, `taiga`. + +Скрипты существуют и исполняемы, но не в кроне: +``` +~/scripts/watchlist-nightly.sh mtime 2026-05-29 +~/scripts/watchlist-discover.sh mtime 2026-05-29 +``` + +**Побочный эффект — файл засран `❓`-мусором.** Так как `resolve --recheck` не бегает, ambiguous-строки копят дампы кандидатов: «Крестный отец» ×4 блока по 6 строк, «Nightmare Alley» ×31 строка, «Stand by me» ×40 строк, «Фарго» ×30. Секции `👍/👎` не обрабатываются — 40+ позиций висят в «Новинки», не переехав в основной список. + +Аудит завершён без изменений на Кракане — ничего не трогалось. Три варианта для Alex: (1) восстановить крон, (2) сначала почистить `❓`-мусор, (3) оставить как есть. + ## Cron Jobs (на Кракене с 2026-05-27) Весь watchlist pipeline работает на Кракене (мигрировал с Eagle 2026-05-27). | Job | Расписание | Скрипт | |-----|-----------|--------| -| `watchlist-nightly` | ежедн. 01:00 | `~/.hermes/scripts/watchlist-nightly.sh` | -| `watchlist-discover` | вс 09:00 | `~/.hermes/scripts/watchlist-discover.sh` | +| `watchlist-nightly` | ежедн. 01:00 | `~/scripts/watchlist-nightly.sh` | +| `watchlist-discover` | вс 09:00 | `~/scripts/watchlist-discover.sh` | + +⚠️ Фактический путь — `~/scripts/`, **не** `~/.hermes/scripts/` (в доке ранее было ошибочно). Оба скрипта вызывают CLI напрямую через `uv run --project $WS`, без LLM. `uv` лежит в `~/.local/bin/uv`. + +`WS` в обоих скриптах: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/watchlist-sync` — **другой UUID**, чем фактический корень репо (см. ниже). Возможный источник поломки: проверить, что путь резолвится. **watchlist-nightly.sh** (на Кракене): 1. `sync-vault.sh` (pull) → `process-thumbs --apply` → `sync-vault.sh` (push) @@ -146,7 +171,9 @@ Jellyfin library mapping: Movies → `movies`, Cartoons → `mixed` (movies + ep ## Open Tasks +- 🔴 **[2026-09-20] Восстановить cron для watchlist pipeline** — pipeline мёртв с 20 июня (см. раздел выше). Решение за Alex: восстановить крон / сначала почистить `❓`-мусор / оставить как есть. - 🔴 **[2026-09-04] Решить стратегию качества загрузки новых фильмов** (см. профили в [[arr-stack-kraken]]). Корень — захардкоженный `qualityProfileId: 1` (`Any`) в `watchlist_sync/arr.py`. Пока НЕ менялось (НИЧЕГО не правилось, ждём решение Alex). Вопрос юзеру: сохранить 4K (→ создать профиль «2160p без Remux/BR-DISK» и сменить id в arr.py) или опустить до 1080p (id 4); и менять ли и для Sonarr (сериалы) тоже. +- 🟡 Почистить `❓`-мусор в movies-watchlist.md (повторяющиеся дампы кандидатов после многомесячного простоя) - 🟡 Передавать Transmission locations через router script при каждом импорте (сейчас вручную) - 🔴 rsync невыполненных фильмов с HTPC на Кракен (`Фильмы не перенесенные с htpc на кракен.md`) - 🟡 Watchlist sync-up: добавить перенесённые фильмы в нужные разделы