[2026-05-22] taiga sync: .obsidian/community-plugins.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/main.js
This commit is contained in:
@@ -1,153 +0,0 @@
|
||||
---
|
||||
title: "*arr Stack на Кракене — Pitfalls & Config"
|
||||
namespace: work
|
||||
type: reference
|
||||
tags:
|
||||
- kraken
|
||||
- radarr
|
||||
- sonarr
|
||||
- prowlarr
|
||||
- arr
|
||||
- pitfalls
|
||||
created: '2026-05-19'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
confidence: 0.9
|
||||
---
|
||||
# *arr Stack на Кракене — Pitfalls & Config
|
||||
|
||||
## Архитектура
|
||||
|
||||
Prowlarr (9696) → Radarr (7878) + Sonarr (8989) → Transmission (9091) → Jellyfin (8096)
|
||||
|
||||
## Web UI (nginx reverse proxy)
|
||||
|
||||
Все сервисы доступны через nginx на порту 80 (urlBase настроен в каждом сервисе):
|
||||
|
||||
| Сервис | URL | Прямой порт |
|
||||
|--------|-----|-------------|
|
||||
| Sonarr | http://kraken/sonarr | 8989 |
|
||||
| Radarr | http://kraken/radarr | 7878 |
|
||||
| Prowlarr | http://kraken/prowlarr | 9696 |
|
||||
| Jellyfin | http://kraken/jellyfin | 8096 |
|
||||
| Transmission | http://kraken/transmission | 9091 |
|
||||
|
||||
Конфиг: `/etc/nginx/openmediavault-webgui.d/media-services.conf` (используем `^~` prefix чтобы перебить OMV regex `.json` location).
|
||||
|
||||
**⚠️ Pitfall:** OMV имеет regex `location ~* \.json$` который перехватывает все JSON запросы (в т.ч. `/sonarr/initialize.json`). Без `^~` сервисы открываются белым экраном.
|
||||
|
||||
## Docker Networks
|
||||
|
||||
| Сервис | Сети |
|
||||
|--------|------|
|
||||
| Radarr | docker_default |
|
||||
| Sonarr | media_net + docker_default |
|
||||
| Prowlarr | docker_default + media_net |
|
||||
| Transmission | docker_default |
|
||||
| Jellyfin | (отдельно) |
|
||||
|
||||
Sonarr изначально был только в `media_net` → не видел Transmission → ошибки download client. Добавлен в `docker_default` в `docker-compose.yml`.
|
||||
|
||||
## watchlist-sync .env URLs
|
||||
|
||||
После установки urlBase — API переехало на base path:
|
||||
```
|
||||
RADARR_URL=http://localhost:7878/radarr
|
||||
SONARR_URL=http://localhost:8989/sonarr
|
||||
JELLYFIN_URL=http://localhost:8096/jellyfin
|
||||
```
|
||||
|
||||
## API ключи (prefixes)
|
||||
|
||||
| Сервис | Prefix | Полный ключ |
|
||||
|--------|--------|-------------|
|
||||
| Radarr | `cbcb8ec3` | в `family/projects/media-toolbox-kraken.md` |
|
||||
| Sonarr | `15fbec32` | в `family/projects/media-toolbox-kraken.md` |
|
||||
| Prowlarr | `134ac38a` | в `family/projects/media-toolbox-kraken.md` |
|
||||
|
||||
**Получить полный ключ:**
|
||||
```bash
|
||||
docker exec <svc> grep ApiKey /config/config.xml
|
||||
```
|
||||
|
||||
Prefixes в памяти только для идентификации — никогда не хардкодить полные ключи в промптах.
|
||||
|
||||
## ⚠️ DNS Pitfall — Pi-hole блокирует skyhook.sonarr.tv
|
||||
|
||||
**Симптом:** поиск при добавлении сериала/фильма через Sonarr/Radarr не запускается.
|
||||
|
||||
**Причина:** Pi-hole блокирует `skyhook.sonarr.tv` (и возможно другие *arr endpoints).
|
||||
|
||||
**Фикс:** прописать явный DNS в `docker-compose.yml` для Sonarr и Radarr:
|
||||
```yaml
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
```
|
||||
|
||||
Применено: 2026-05-18. Файлы: `/srv/.../docker/radarr/docker-compose.yml` и `sonarr/docker-compose.yml`.
|
||||
|
||||
## Root folders
|
||||
|
||||
- Radarr: `/media/movies-radarr`
|
||||
- Sonarr: `/media/series-sonarr`
|
||||
|
||||
(Router script создаёт symlinks из этих папок в тематические библиотеки Jellyfin.)
|
||||
|
||||
## Prowlarr → Sonarr/Radarr sync — правильная настройка
|
||||
|
||||
**Корень проблемы "неправильный URL":** Prowlarr при sync проставляет в Sonarr/Radarr URL вида `http://prowlarr:9696/N/` вместо `http://prowlarr:9696/prowlarr/N/`. Это происходит если в настройках Application → `prowlarrUrl` не указан urlBase.
|
||||
|
||||
**Правильное значение** в Prowlarr → Settings → Apps → (Sonarr/Radarr) → Prowlarr URL:
|
||||
```
|
||||
http://prowlarr:9696/prowlarr
|
||||
```
|
||||
(без trailing slash, с urlBase `/prowlarr`)
|
||||
|
||||
После изменения — запустить принудительный sync:
|
||||
```bash
|
||||
curl -X POST "http://localhost:9696/prowlarr/api/v1/command?apikey=KEY" \
|
||||
-H "Content-Type: application/json" -d '{"name":"ApplicationIndexerSync"}'
|
||||
```
|
||||
|
||||
## Grab limit 429 — решение через магнет-ссылки
|
||||
|
||||
NoNaMe Club, RuTracker и другие дают 429 при скачивании torrent-файлов (дневной лимит).
|
||||
|
||||
**Фикс:** включить `preferMagnetUrl: true` для каждого индексера в Prowlarr → Indexers → (индексер) → Torrent Base Settings → Prefer Magnet URL.
|
||||
|
||||
Через API:
|
||||
```bash
|
||||
curl -s "http://localhost:9696/prowlarr/api/v1/indexer/ID?apikey=KEY" | \
|
||||
jq '(.fields[] | select(.name=="torrentBaseSettings.preferMagnetUrl") | .value) = true' | \
|
||||
curl -X PUT "http://localhost:9696/prowlarr/api/v1/indexer/ID?apikey=KEY" \
|
||||
-H "Content-Type: application/json" -d @-
|
||||
```
|
||||
|
||||
Применено для индексеров: RuTracker (1), RuTor (2), Byrutor (3), NoNaMe Club (4).
|
||||
|
||||
## Kinozal — лимит на скачивание торрент-файлов
|
||||
|
||||
Kinozal (стандартный) даёт 429 на скачивание. Решение — **Kinozal (M)** (магнет-версия, definitionFile: `kinozal-magnet`). Добавлен в Prowlarr как отдельный индексер с теми же credentials. Синкается в Sonarr и Radarr через Applications.
|
||||
|
||||
## Индексеры — текущий состав (Prowlarr)
|
||||
|
||||
| ID | Имя | Тип | Примечание |
|
||||
|----|-----|-----|-----------|
|
||||
| 1 | RuTracker | semi-private | блокируется при rate limit на сутки |
|
||||
| 2 | RuTor | public | поиск по imdbid |
|
||||
| 3 | Byrutor | public | |
|
||||
| 4 | NoNaMe Club | semi-private | нет логина, только анонимный |
|
||||
| 5 | Kinozal | semi-private | оставлен, но Kinozal (M) предпочтительнее |
|
||||
| 6 | Kinozal (M) | semi-private | магнет, без grab limit ✅ |
|
||||
|
||||
## Sonarr — поиск русских сериалов
|
||||
|
||||
Sonarr берёт название из TVDB. Для русских сериалов TVDB ставит английский перевод как primary. Prowlarr отправляет оба варианта (через `addrussian` и alternate titles), но это зависит от индексера.
|
||||
|
||||
**Работающий путь:** Kinozal (M) с `addrussian: true` и `stripcyrillic: false` — находит по русскому названию. Подтверждено: Кибердеревня найдена и скачана.
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[family/projects/media-toolbox-kraken]] — полный статус проекта
|
||||
- [[tech/kraken-network]] — инфра Кракена
|
||||
@@ -1,111 +0,0 @@
|
||||
---
|
||||
title: "*arr Stack на Тайге — Setup & Config"
|
||||
created: '2026-05-22'
|
||||
updated: '2026-05-22'
|
||||
last_synced: '2026-05-22'
|
||||
type: reference
|
||||
namespace: work
|
||||
tags:
|
||||
- taiga
|
||||
- arr
|
||||
- media
|
||||
- jellyfin
|
||||
- pitfall
|
||||
confidence: 0.9
|
||||
sources:
|
||||
- family/projects/media-toolbox-taiga.md
|
||||
---
|
||||
# *arr Stack на Тайге — Setup & Config
|
||||
|
||||
Задеплоен 2026-05-20 на TrueNAS (Taiga). Аналог [[tech/arr-stack-kraken]], но c Caddy вместо nginx и иными путями.
|
||||
|
||||
## Архитектура
|
||||
|
||||
```
|
||||
Prowlarr (9696) → Radarr (7878) + Sonarr (8989) → Transmission (9091) → Jellyfin (8096)
|
||||
router.py создаёт симлинки: staging → категоризированные библиотеки
|
||||
```
|
||||
|
||||
**Compose-файл:** `/mnt/RED_2TB/docker/arr/docker-compose.yml`
|
||||
**Конфиги:** `/mnt/RED_2TB/docker/arr/{prowlarr,radarr,sonarr,jellyfin}/`
|
||||
**PUID/PGID:** 921/921 (user `transmission`)
|
||||
|
||||
## Web UI (Caddy + HTTPS)
|
||||
|
||||
| Сервис | URL |
|
||||
|--------|-----|
|
||||
| Radarr | https://radarr.mallexxx.duckdns.org |
|
||||
| Sonarr | https://sonarr.mallexxx.duckdns.org |
|
||||
| Prowlarr | https://prowlarr.mallexxx.duckdns.org |
|
||||
| Jellyfin | https://jellyfin.mallexxx.duckdns.org |
|
||||
| Transmission | https://transmission.mallexxx.duckdns.org |
|
||||
|
||||
Caddy: subdomain-based routing, Let's Encrypt автоматически.
|
||||
|
||||
## Хранилище
|
||||
|
||||
`/mnt/RED_2TB/storage/` → в контейнерах `/storage/`
|
||||
|
||||
| Папка | Назначение | Jellyfin |
|
||||
|-------|-----------|----------|
|
||||
| `radarr/` | Radarr root (staging) | ❌ |
|
||||
| `sonarr/` | Sonarr root (staging) | ❌ |
|
||||
| `Movies/` | Фильмы (симлинки + старый контент) | ✅ Movies |
|
||||
| `Cartoons/` | Мультики | ✅ Cartoons |
|
||||
| `series/` | Сериалы | ✅ Series |
|
||||
| `cartoons-series/` | Мультсериалы | ✅ Cartoon Series |
|
||||
| `documentaries/` | Документалки | ✅ Documentaries |
|
||||
| `documentaries-series/` | Документальные сериалы | ✅ Documentary Series |
|
||||
| `Downloads/` | Торренты (Transmission) | ❌ |
|
||||
|
||||
## Remote Path Mapping (Radarr + Sonarr)
|
||||
|
||||
Transmission: `/mnt/storage/Downloads/` → `/mnt/storage/`
|
||||
Radarr/Sonarr: `/storage/`
|
||||
|
||||
Маппинг в каждом `arr`:
|
||||
- host: `transmission`, remotePath: `/mnt/storage/Downloads/`, localPath: `/storage/Downloads/`
|
||||
|
||||
## Prowlarr — прокси для заблокированных индексеров
|
||||
|
||||
vless-proxy в `media_net` как `vless-proxy:1080` (SOCKS5). Настройка: Settings → Indexers → Add Proxy → SOCKS5.
|
||||
|
||||
**Индексеры:** RuTracker (через прокси), RuTor, Byrutor (enableRss: false), NoNaMe Club, Kinozal, Kinozal (M) — `preferMagnetUrl: true` для всех.
|
||||
|
||||
## router.py
|
||||
|
||||
`/mnt/RED_2TB/docker/arr/media-pipeline/router.py`
|
||||
|
||||
```bash
|
||||
# Dry-run, затем apply:
|
||||
ssh truenas_admin@mallexxx.duckdns.org "python3 /mnt/RED_2TB/docker/arr/media-pipeline/router.py"
|
||||
ssh truenas_admin@mallexxx.duckdns.org "python3 /mnt/RED_2TB/docker/arr/media-pipeline/router.py --apply"
|
||||
```
|
||||
|
||||
## Отличия от Кракена
|
||||
|
||||
| | Kraken | Taiga |
|
||||
|--|--------|-------|
|
||||
| Reverse proxy | nginx path-based (`/sonarr`) | Caddy subdomain-based |
|
||||
| HTTPS | нет | автоматически (Let's Encrypt) |
|
||||
| PUID/PGID | 1000/1000 | 921/921 (transmission) |
|
||||
| Staging папки | `movies-radarr/`, `series-sonarr/` | `radarr/`, `sonarr/` |
|
||||
| Прокси для индексеров | нет | vless-proxy SOCKS5 |
|
||||
| Jellyfin users | alex + lisa | только alex |
|
||||
| PGS→SRT | pgsrip + cron | TBD |
|
||||
|
||||
## Питфоллы (при деплое)
|
||||
|
||||
- `d---------` в ls — норма для NFSv4 ACL на TrueNAS. Реальные права через `midclt call filesystem.getacl`
|
||||
- После alpine `chown` NFSv4 ACE слетают → повторно применять через `midclt filesystem.setacl`
|
||||
- `indexers.prowlarr.com` отдаёт 403 с IP Тайги → Prowlarr не может скачать Cardigann definitions. Решение: скопировать `/config/Definitions/` с Кракена (549 yml-файлов)
|
||||
- POST /indexer зависает при добавлении Cardigann через API → import через SQLite напрямую с Кракена
|
||||
- Jellyfin 10.11: `name` в POST `/Library/VirtualFolders` — в query string (`?name=Movies`), не в body
|
||||
- Transmission whitelist через env var `WHITELIST` в compose (settings.json перезаписывается при старте)
|
||||
- На Тайге нет `curl` и `python3` в PATH хоста — только внутри контейнеров. Скрипты через `docker exec` или scp
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[tech/arr-stack-kraken]] — *arr stack на Кракене (для сравнения)
|
||||
- [[concepts/kraken-media-stack]] — полная архитектура медиастека
|
||||
- [[tech/kraken-network]] — сетевая топология
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
title: Hermes Docker на Кракене — Правила запуска
|
||||
type: reference
|
||||
namespace: work
|
||||
tags:
|
||||
- hermes
|
||||
- docker
|
||||
- kraken
|
||||
- pitfalls
|
||||
created: '2026-05-18'
|
||||
updated: '2026-05-18'
|
||||
---
|
||||
# Hermes Docker на Кракене — Правила запуска
|
||||
|
||||
## Почему не compose
|
||||
|
||||
`docker compose` ломается из-за long-lived process detection — Hermes gateway — постоянный процесс, что compose интерпретирует как зависание.
|
||||
|
||||
**Решение:** запускать через `docker run` напрямую.
|
||||
|
||||
## Правильная команда
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name hermes-kraken \
|
||||
--restart unless-stopped \
|
||||
--network host \
|
||||
-v /home/kraken/hermes/config:/opt/data \
|
||||
-v /home/kraken/obsidian:/vault:rw \
|
||||
-e HERMES_ALLOW_ROOT_GATEWAY=1 \
|
||||
-e HERMES_SKIP_CHOWN=1 \
|
||||
--env-file /home/kraken/hermes/.env \
|
||||
-t -i \
|
||||
hermes-kraken:latest gateway
|
||||
```
|
||||
|
||||
## Pitfall: HERMES_UID/GID
|
||||
|
||||
**НЕ** задавать `HERMES_UID` / `HERMES_GID` — иначе при каждом старте выполняется `chown -R` на `.venv`, что вешает контейнер на несколько минут.
|
||||
|
||||
## Итог
|
||||
|
||||
| Переменная | Значение |
|
||||
|------------|---------|
|
||||
| `HERMES_ALLOW_ROOT_GATEWAY` | `1` |
|
||||
| `HERMES_SKIP_CHOWN` | `1` |
|
||||
| `HERMES_UID/GID` | ❌ не задавать |
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[tech/kraken-network]] — сетевая топология и инфра Кракена
|
||||
- [[concepts/kraken-media-stack]] — полный медиастек на Кракене
|
||||
@@ -1,228 +0,0 @@
|
||||
---
|
||||
title: Hermes на Eagle (Mac M4 Max) — Настройка и подводные камни
|
||||
type: reference
|
||||
namespace: work
|
||||
tags:
|
||||
- hermes
|
||||
- mac
|
||||
- eagle
|
||||
- claude-proxy
|
||||
- zulip
|
||||
- pitfalls
|
||||
created: '2026-05-21'
|
||||
updated: '2026-05-22'
|
||||
last_synced: '2026-05-22'
|
||||
confidence: 0.9
|
||||
---
|
||||
# Hermes на Eagle (Mac M4 Max) — Настройка и подводные камни
|
||||
|
||||
Hermes работает нативно (не в Docker) на Mac через `hermes gateway`.
|
||||
Транспорт — Zulip (запущен в Docker). Провайдер модели — openclaw-claude-proxy
|
||||
(см. ниже).
|
||||
|
||||
## Компоненты
|
||||
|
||||
| Компонент | Расположение | Запуск |
|
||||
|-----------|-------------|--------|
|
||||
| Hermes config | `~/.hermes/config.yaml` | — |
|
||||
| claude-proxy (Claude proxy) | `/opt/homebrew/bin/claude-proxy` | launchd `ai.claude-proxy` |
|
||||
| Zulip stack | `~/Developer/zulip/docker-compose.yml` | `docker compose up -d` |
|
||||
| Obsidian MCP | mcpvault | встроен в Hermes toolset |
|
||||
|
||||
---
|
||||
|
||||
## openclaw-claude-proxy — обход rate limit Claude API
|
||||
|
||||
### Проблема
|
||||
|
||||
`provider: claude-code` в Hermes использует OAuth-токен напрямую через
|
||||
API Anthropic — и упирается в rate limit подписки. Лимиты сбрасываются
|
||||
раз в час. API-ключа нет (политика организации).
|
||||
|
||||
### Почему не cmappy
|
||||
|
||||
cmappy (`claude-max-proxy-py`) молча выбрасывает поле `tools` из запроса —
|
||||
передаёт только текст в `claude --print`. Результат: Hermes не может
|
||||
использовать **ни один инструмент** (скиллы, MCP, терминал). Только голый
|
||||
чат.
|
||||
|
||||
### Решение: openclaw-claude-proxy
|
||||
|
||||
[mehdic/claude-proxy](https://github.com/mehdic/claude-proxy) (npm:
|
||||
`openclaw-claude-proxy`) — Node.js сервер, запускает `claude --print` как
|
||||
subprocess и предоставляет OpenAI-совместимый `/v1/chat/completions` на
|
||||
порту 3456. **Поддерживает tool_use** — инжектирует схемы инструментов в
|
||||
системный промпт, парсит JSON tool_call из ответа, возвращает стандартный
|
||||
OpenAI `tool_calls`. Caller (Hermes) сам выполняет инструменты.
|
||||
|
||||
**Важно:** `CLAUDE_PROXY_TOOLS_TRANSLATION=1` НЕ включать — этот режим
|
||||
выполняет MCP инструменты внутри CLI и Hermes ничего не получает.
|
||||
|
||||
### Установка
|
||||
|
||||
```bash
|
||||
npm install -g openclaw-claude-proxy
|
||||
```
|
||||
|
||||
### Wrapper-скрипт (обязателен для launchd)
|
||||
|
||||
`~/.local/bin/claude-proxy-start.sh`:
|
||||
```bash
|
||||
#!/bin/zsh
|
||||
# launchd не наследует среду login-сессии — токен нужно загружать явно
|
||||
set -a
|
||||
source /Users/admin/.hermes/.env 2>/dev/null
|
||||
set +a
|
||||
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
|
||||
exec /opt/homebrew/bin/claude-proxy 3456
|
||||
```
|
||||
|
||||
**Pitfall:** без явного `source ~/.hermes/.env` claude-proxy не видит
|
||||
`CLAUDE_CODE_OAUTH_TOKEN` и прогревочные процессы падают с "Not logged in".
|
||||
|
||||
**Pitfall:** без явного PATH Claude CLI не найден (`/opt/homebrew/bin/claude`
|
||||
не в launchd PATH).
|
||||
|
||||
### launchd сервис
|
||||
|
||||
`~/Library/LaunchAgents/ai.claude-proxy.plist`:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key><string>ai.claude-proxy</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/admin/.local/bin/claude-proxy-start.sh</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>HOME</key><string>/Users/admin</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/admin/.hermes/logs/claude-proxy.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/admin/.hermes/logs/claude-proxy.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
```bash
|
||||
launchctl load ~/Library/LaunchAgents/ai.claude-proxy.plist
|
||||
```
|
||||
|
||||
**Pitfall при перезагрузке:** если старый процесс ещё держит порт 3456:
|
||||
```bash
|
||||
lsof -ti :3456 | xargs kill -9
|
||||
launchctl unload ~/Library/LaunchAgents/ai.claude-proxy.plist
|
||||
launchctl load ~/Library/LaunchAgents/ai.claude-proxy.plist
|
||||
```
|
||||
|
||||
### Конфигурация Hermes
|
||||
|
||||
`~/.hermes/config.yaml` (секция model):
|
||||
```yaml
|
||||
model:
|
||||
default: claude-sonnet-4-6
|
||||
# provider: claude-code # отключён — упирается в rate limit OAuth API
|
||||
provider: custom
|
||||
base_url: 'http://localhost:3456/v1'
|
||||
```
|
||||
|
||||
**Pitfall:** `provider: openai` не существует в Hermes — нужно `custom`.
|
||||
|
||||
**Pitfall:** `base_url` должен включать `/v1` (Hermes дописывает
|
||||
`/chat/completions`). Без `/v1` → 404.
|
||||
|
||||
---
|
||||
|
||||
## Zulip Docker — подводные камни
|
||||
|
||||
### RabbitMQ: пользователи сбрасываются после перезапуска
|
||||
|
||||
**Симптом:** Zulip отдаёт 500 на `/api/v1/register`. В логах RabbitMQ —
|
||||
паника Khepri (Raft WAL). Пользователи в RabbitMQ исчезают.
|
||||
|
||||
**Причина:** RabbitMQ 4.x использует Khepri вместо Mnesia. При переполнении
|
||||
диска WAL не может записаться → Khepri сбрасывает состояние → пользователи
|
||||
исчезают. `RABBITMQ_DEFAULT_USER/PASS` применяются только при **первом
|
||||
старте** с пустым volume — повторный запуск их не восстанавливает.
|
||||
|
||||
**Решение:**
|
||||
|
||||
1. `docker system prune` — освободить место на диске (Docker VM sparse disk
|
||||
не освобождает место автоматически).
|
||||
2. Добавить `RABBITMQ_ERLANG_COOKIE` в env rabbitmq (стабилизирует cookie
|
||||
через перезапуски).
|
||||
3. При повреждённом volume — стереть и пересоздать:
|
||||
```bash
|
||||
docker compose down
|
||||
docker volume rm zulip_zulip-rabbitmq
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Log rotation (обязательно!)
|
||||
|
||||
Без ротации логи заполняют Docker VM (~6 ГБ за несколько месяцев).
|
||||
|
||||
`docker-compose.yml` — добавить к каждому сервису:
|
||||
```yaml
|
||||
# zulip:
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "5"
|
||||
|
||||
# rabbitmq, memcached, redis:
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "20m"
|
||||
max-file: "3"
|
||||
```
|
||||
|
||||
### Docker VM sparse disk
|
||||
|
||||
Mac Docker Desktop использует sparse virtual disk. Место, освобождённое
|
||||
внутри VM, не возвращается хосту автоматически. `docker system prune`
|
||||
запускает compaction.
|
||||
|
||||
---
|
||||
|
||||
## Obsidian MCP
|
||||
|
||||
Везде используется `mcpvault` (не `obsidian-mcp`).
|
||||
|
||||
| Конфиг | Путь |
|
||||
|--------|------|
|
||||
| Claude Code CLI | `~/.claude/.mcp.json` |
|
||||
| Claude Desktop App | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
||||
| Hermes | встроен через toolset |
|
||||
|
||||
Пример конфига (одинаковый для обоих):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"obsidian": {
|
||||
"command": "mcpvault",
|
||||
"args": ["/Users/admin/obsidian"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Pitfall:** `obsidian-mcp` (npm) был удалён — если остался в конфиге,
|
||||
Claude падает с "Failed to spawn process". Проверить логи:
|
||||
`~/Library/Logs/Claude/mcp-server-obsidian.log`.
|
||||
|
||||
---
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[tech/hermes-docker-kraken]] — Hermes на Кракене (Docker)
|
||||
- [[tech/kraken-network]] — сетевая топология
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
title: "HTPC — Kodi NFO, Симлинки, Media Layout"
|
||||
namespace: personal
|
||||
type: reference
|
||||
tags:
|
||||
- htpc
|
||||
- kodi
|
||||
- nfo
|
||||
- symlinks
|
||||
- media
|
||||
- wol
|
||||
created: '2026-05-19'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
confidence: 0.9
|
||||
---
|
||||
# HTPC — Kodi NFO, Симлинки, Media Layout
|
||||
|
||||
## Media Layout на HTPC
|
||||
|
||||
| Папка | Контент |
|
||||
|-------|---------|
|
||||
| `/Data/movies/` | фильмы |
|
||||
| `/Data/мультфильмы/` | мультики (отдельно, **не** `/Data/movies/`) |
|
||||
| `/Data/мультфильмы/арменфильм/` | советские мультики Арменфильм |
|
||||
|
||||
## Kodi структура
|
||||
|
||||
```
|
||||
/Data/kodi/movies/ ← подпапки с NFO + симлинки
|
||||
/Data/kodi/series/ ← сериалы
|
||||
```
|
||||
|
||||
- Симлинки из `kodi/movies/` указывают на `/Data/movies/` и `/Data/мультфильмы/`
|
||||
- Flat файлы тоже могут лежать прямо в корне `kodi/movies/`
|
||||
- Каждый тайтл — подпапка (NFO + симлинк внутри)
|
||||
|
||||
## rsync из kodi
|
||||
|
||||
**Обязательный флаг:** `--copy-links`
|
||||
Без него rsync копирует сами симлинки, а не содержимое.
|
||||
|
||||
## Wake-on-LAN (HTPC)
|
||||
|
||||
| Ситуация | Метод |
|
||||
|----------|-------|
|
||||
| Eagle на VPN (вне LAN) | через Кракен: `ssh kraken` + python3 magic packet |
|
||||
| Eagle дома (192.168.x) | напрямую |
|
||||
|
||||
Поллить ответ HTPC с Кракена.
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[tech/htpc-steam-emulators]] — Steam, эмуляторы, геймпады
|
||||
- [[tech/kraken-network]] — сеть, топология
|
||||
@@ -1,165 +0,0 @@
|
||||
---
|
||||
title: HTPC — Steam, Эмуляторы, Геймпады
|
||||
namespace: personal
|
||||
created: '2026-05-17'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
type: reference
|
||||
tags:
|
||||
- htpc
|
||||
- steam
|
||||
- emulators
|
||||
- gamepads
|
||||
- bazzite
|
||||
confidence: 0.9
|
||||
---
|
||||
# HTPC — Steam, Эмуляторы, Геймпады
|
||||
|
||||
## Critical Rules — Steam
|
||||
|
||||
1. **НИКОГДА не убивать Steam через SSH** — вешает (gamescope = системный процесс)
|
||||
2. **SRM** — только Desktop Mode GUI
|
||||
3. **shortcuts.vdf** писать только когда Steam **закрыт** (иначе перезапишет кэшем)
|
||||
|
||||
## Обязательные exe в shortcuts.vdf
|
||||
|
||||
- RetroArch: `flatpak run org.libretro.RetroArch`
|
||||
- Dolphin: `flatpak run org.DolphinEmu.dolphin-emu`
|
||||
|
||||
## Saves rsync — Kraken ← HTPC
|
||||
|
||||
| Игра | Путь |
|
||||
|------|------|
|
||||
| Dolphin Wii | `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/Wii/` |
|
||||
| Dolphin GC | `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/GC/` |
|
||||
| Steam | `~/.var/app/com.valvesoftware.Steam/data/Steam/userdata/` |
|
||||
|
||||
## Геймпады
|
||||
|
||||
- 2× Xbox 360 (USB)
|
||||
- 2× 8BitDo (Xbox-схема, X-режим)
|
||||
- Dolphin: SDL-маппинг, Classic Controller
|
||||
- DKC Returns: X = Roll+Shake
|
||||
|
||||
## Switch Эмуляция — Ryujinx (Ryubing)
|
||||
|
||||
Оригинальный Ryujinx и Yuzu закрыты (Nintendo судится). Живые форки:
|
||||
|
||||
| Эмулятор | Основа | Статус | Платформа |
|
||||
|----------|--------|--------|-----------|
|
||||
| **Ryujinx (Ryubing/GreemDev)** | Ryujinx | ✅ Активно | Flatpak `io.github.ryubing.Ryujinx` |
|
||||
| Eden | Yuzu | ✅ Активно | Android |
|
||||
| Citron | Yuzu | Активно | Альтернатива |
|
||||
|
||||
**Для HTPC: Ryujinx (Ryubing) v1.3.3 через Flatpak.**
|
||||
|
||||
### Установка (✅ 2026-05-16)
|
||||
|
||||
```bash
|
||||
flatpak install -y --user flathub io.github.ryubing.Ryujinx
|
||||
```
|
||||
|
||||
**Пути (Flatpak):**
|
||||
```
|
||||
# Keys:
|
||||
~/.var/app/io.github.ryubing.Ryujinx/data/Ryujinx/system/prod.keys
|
||||
~/.var/app/io.github.ryubing.Ryujinx/data/Ryujinx/system/title.keys
|
||||
|
||||
# ROMs:
|
||||
~/Emulation/roms/switch/ (Steam ROM Manager подхватит)
|
||||
|
||||
# Saves:
|
||||
~/.var/app/io.github.ryubing.Ryujinx/data/Ryujinx/bis/user/save/
|
||||
```
|
||||
|
||||
### prod.keys — Источники
|
||||
|
||||
- **GitHub THZoria/NX_Firmware** ⭐ — актуальная версия firmware + keys (22.1.0, апр. 2026)
|
||||
- **4PDA** — тема Switch ROM'ов, в шапке ссылки на firmware/keys
|
||||
- **Rutracker** — раздел `/f=1605`, в шапках тем часто есть keys
|
||||
|
||||
**Firmware** устанавливается через GUI: Ryujinx → Tools → Install Firmware → Install from ZIP
|
||||
Keys и firmware должны быть одной версии.
|
||||
|
||||
### ROMs форматы
|
||||
- `.nsp` — предпочтительный (Nintendo Submission Package)
|
||||
- `.xci` — картридж-дамп, тоже работает
|
||||
|
||||
### DKC Tropical Freeze — совместимость
|
||||
Подтверждено: работает на схожем железе (i5-6500 + GTX 1050 Ti). HTPC (i7-6800K + RX 570, Vulkan) — ожидается Playable–Perfect.
|
||||
|
||||
## qBittorrent на HTPC (✅ 2026-05-16)
|
||||
|
||||
```bash
|
||||
flatpak install -y --user flathub org.qbittorrent.qBittorrent
|
||||
# Версия 5.2.0
|
||||
```
|
||||
|
||||
| Настройка | Значение |
|
||||
|-----------|----------|
|
||||
| Web UI | http://192.168.1.86:8080 |
|
||||
| BitTorrent port | 6881 |
|
||||
| Download dir | `/run/media/bazzite/Data/downloads/complete` |
|
||||
| Incomplete dir | `/run/media/bazzite/Data/downloads/incomplete` |
|
||||
|
||||
**Sonarr/Radarr интеграция:** Settings → Download Clients → Add → qBittorrent (host: `192.168.1.86`, port: `8080`).
|
||||
|
||||
### API — добавить торрент
|
||||
|
||||
```bash
|
||||
# Логин
|
||||
SID=$(curl -s -i --header 'Referer: http://192.168.1.86:8080' \
|
||||
--data 'username=admin&password=PASSWORD' \
|
||||
http://192.168.1.86:8080/api/v2/auth/login \
|
||||
| grep -i 'set-cookie' | grep -o 'SID=[^;]*')
|
||||
|
||||
# Добавить магнет
|
||||
curl -s --cookie "$SID" \
|
||||
--data-urlencode "urls=magnet:?xt=urn:btih:HASH..." \
|
||||
--data "savepath=/home/bazzite/Emulation/roms/switch/" \
|
||||
http://192.168.1.86:8080/api/v2/torrents/add
|
||||
```
|
||||
|
||||
## Jackett на Кракене — Поиск ROM/торрентов
|
||||
|
||||
```yaml
|
||||
# /srv/.../docker/jackett/docker-compose.yml
|
||||
services:
|
||||
jackett:
|
||||
image: lscr.io/linuxserver/jackett:latest
|
||||
container_name: jackett
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Asia/Bishkek
|
||||
volumes:
|
||||
- ./config:/config
|
||||
- ./downloads:/downloads
|
||||
ports:
|
||||
- 9117:9117
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
Web UI: `http://kraken:9117`
|
||||
Поддерживает RuTracker (нужна учётка). API: Torznab endpoint.
|
||||
|
||||
```bash
|
||||
# Поиск игры
|
||||
curl "http://192.168.1.14:9117/api/v2.0/indexers/rutracker/results/torznab/?apikey=***&t=search&q=Donkey+Kong+Tropical+Freeze+Switch&cat=8000"
|
||||
```
|
||||
|
||||
## Целевой Flow: Агент ищет и качает ROM
|
||||
|
||||
```
|
||||
Eagle/Кракен → Jackett API (Кракен :9117) → RuTracker
|
||||
→ Выбор лучшего torrent (seeders, формат NSP/XCI)
|
||||
→ qBittorrent API (HTPC :8080) — magnet + savepath=/Emulation/roms/switch/
|
||||
→ Steam ROM Manager → игра в Gaming Mode
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [[tech/htpc-kodi-layout]] — Kodi, NFO, симлинки, медиа-структура
|
||||
- [[tech/kraken-network]] — сеть, WireGuard, топология
|
||||
- [[tech/arr-stack-kraken]] — Prowlarr/Radarr/Sonarr на Кракене
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
title: Jellyfin Транскод на RPi5 — PGS/Subtitle Pitfalls
|
||||
type: reference
|
||||
namespace: work
|
||||
tags:
|
||||
- jellyfin
|
||||
- kraken
|
||||
- transcode
|
||||
- subtitles
|
||||
- pitfalls
|
||||
created: '2026-05-18'
|
||||
updated: '2026-05-18'
|
||||
---
|
||||
# Jellyfin Транскод на RPi5 — PGS/Subtitle Pitfalls
|
||||
|
||||
## Контекст
|
||||
|
||||
Клиент: Konka TV с WebOS. Сервер: Raspberry Pi 5 (Крaken, ARM64).
|
||||
|
||||
## Direct Play условия
|
||||
|
||||
Direct Play работает при выполнении всех условий:
|
||||
- Аудио: AAC
|
||||
- Субтитры: **отсутствуют** (или внешние SRT, без burn-in)
|
||||
|
||||
## Проблема PGS/ASS субтитров
|
||||
|
||||
PGS и ASS (SSA) субтитры вызывают **burn-in** — Jellyfin рендерит субтитры прямо в видеопоток.
|
||||
|
||||
**Результат:** полный транскод на CPU → **275% CPU load** на RPi5 → лаги, перегрев.
|
||||
|
||||
**Экспериментальный PGS rendering** в настройках Jellyfin — **не помогает** на RPi5.
|
||||
|
||||
## Решение: конвертация PGS → SRT
|
||||
|
||||
Установка через uv (arm64/aarch64 совместимо):
|
||||
```bash
|
||||
~/.local/bin/uv tool install pgsrip
|
||||
sudo apt-get install -y libgl1 libglib2.0-0 tesseract-ocr tesseract-ocr-rus tesseract-ocr-eng
|
||||
```
|
||||
|
||||
Скрипт конвертации:
|
||||
```
|
||||
/srv/dev-disk-by-uuid.../docker/media-pipeline/pgs-to-srt.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
# один файл
|
||||
pgs-to-srt.sh /media/movies/Film.mkv
|
||||
|
||||
# вся директория
|
||||
pgs-to-srt.sh /media
|
||||
```
|
||||
|
||||
Логи: `/srv/.../docker/media-pipeline/pgs-to-srt.log`
|
||||
|
||||
Скрипт:
|
||||
- Скипает файлы без PGS-дорожек (S_HDMV)
|
||||
- Скипает если .srt уже есть рядом
|
||||
- Пишет лог с timestamp
|
||||
|
||||
После конвертации Jellyfin читает внешние `.srt` без транскода.
|
||||
|
||||
## Transmission completion hook
|
||||
|
||||
Хук `/config/on-download-complete.sh` (монтируется в контейнер `:ro`) после завершения загрузки:
|
||||
1. Запускает media-pipeline sync
|
||||
2. Запускает pgs-to-srt.sh для скачанного файла/директории
|
||||
|
||||
Лог: `/srv/.../docker/media-pipeline/download-complete.log`
|
||||
|
||||
## Итог по субтитрам
|
||||
|
||||
| Тип | Direct Play | Транскод |
|
||||
|-----|------------|---------|
|
||||
| Нет субтитров | ✅ | — |
|
||||
| Внешний SRT | ✅ | — |
|
||||
| ASS/SSA | ❌ | burn-in, 275% CPU |
|
||||
| PGS (MKS/MKV) | ❌ | burn-in, 275% CPU |
|
||||
|
||||
## NFD/NFC filename encoding pitfall
|
||||
|
||||
**Проблема:** HTPC сохраняет имена файлов в NFD, Kraken — в NFC.
|
||||
→ Jellyfin видит **две** папки: одна с `.avi` файлом (NFD), другая с `.nfo` (NFC).
|
||||
→ NFO не применяется — Jellyfin берёт NFD-папку (с видео) и игнорирует NFC-папку (с NFO).
|
||||
→ Метаданные пустые.
|
||||
|
||||
**Фикс A (быстрый):** скопировать `movie.nfo` + `poster.jpg` в NFD-папку:
|
||||
```bash
|
||||
# python3 — использовать bytes для путей
|
||||
import os, shutil
|
||||
nfc_path = "…/Movie.NFC/movie.nfo"
|
||||
nfd_path = "…/Movie.NFD/movie.nfo"
|
||||
shutil.copy(nfc_path.encode(), nfd_path.encode())
|
||||
```
|
||||
|
||||
**Фикс B (радикальный):** переименовать всё в NFC (нормализовать).
|
||||
|
||||
**Диагностика:**
|
||||
```bash
|
||||
ls -la | cat -v # покажет NFD-escape символы как ^ escape sequences
|
||||
python3 -c "import os; [print(repr(f)) for f in os.listdir('.')]"
|
||||
```
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[concepts/kraken-media-stack]] — полный медиастек: *arr + Jellyfin + media-pipeline
|
||||
- [[tech/kraken-network]] — инфра Кракена, HDD error recovery
|
||||
@@ -1,112 +0,0 @@
|
||||
---
|
||||
title: Kraken Network & Infra
|
||||
namespace: work
|
||||
created: '2026-05-17'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
type: reference
|
||||
tags:
|
||||
- kraken
|
||||
- network
|
||||
- infra
|
||||
- htpc
|
||||
confidence: high
|
||||
---
|
||||
# Kraken Network & Infra
|
||||
|
||||
## Topology
|
||||
|
||||
| Host | IP | Notes |
|
||||
|------|----|-------|
|
||||
| Kraken | 192.168.1.15 | wlan0 (ASUS5), основной. `ssh kraken`. eth0 отключён |
|
||||
| Kraken eth0 | 192.168.1.14 | DHCP static lease, **неактивен** |
|
||||
| HTPC | 192.168.1.86 | Bazzite, LAN |
|
||||
|
||||
## Важные правила
|
||||
|
||||
- HTPC **не достигает** Kraken через WireGuard — только LAN (`192.168.1.14`)
|
||||
- Kraken **достигает** HTPC напрямую по LAN (192.168.1.86)
|
||||
- Для rsync: **всегда тянуть на Kraken** (Kraken→HTPC), никогда push с HTPC
|
||||
|
||||
## WireGuard VPN
|
||||
|
||||
Kraken имеет WireGuard адрес 10.99.1.2 (через VPS 91.207.28.205). Используется только как резервный путь при недоступности LAN.
|
||||
|
||||
### wg-auto.sh (Eagle-side, macOS)
|
||||
|
||||
Авто-управление WireGuard-туннелем на Eagle (ноутбуке):
|
||||
- Polling каждые 30 секунд
|
||||
- `AbandonProcessGroup=true` в plist (корректное завершение)
|
||||
- Проверка туннеля: `ifconfig | grep 10.99.0.2`
|
||||
- Поднятие/опускание через `wg_up()` с очисткой старого интерфейса
|
||||
- `wg0.conf`: **без `DNS=`** — вместо этого PostUp создаёт `/etc/resolver/kraken` (nameserver 10.99.0.1), PostDown удаляет. **Без `killall mDNSResponder`** — не нужно.
|
||||
|
||||
### Сетевые интерфейсы Kraken
|
||||
|
||||
- `wlan0` (192.168.1.15, MAC `2c:cf:67:64:03:f4`, ASUS5) — **основной**, static lease на роутере
|
||||
- `eth0` — отключён
|
||||
- `ssh kraken` резолвится в **192.168.1.15** (wlan0)
|
||||
|
||||
## Kodi на HTPC
|
||||
|
||||
- Library: `/run/media/bazzite/Data/kodi/{movies,series}` — симлинки на реальные файлы
|
||||
|
||||
## Kraken media volume
|
||||
|
||||
- Mount path: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/media` → `/media`
|
||||
- **НЕ** `/mnt/user/media` — пустая!
|
||||
- Configs: `~/docker/media-pipeline/{config.json,cache/,unresolved.json}`
|
||||
- Нет docker-compose — только `docker run` напрямую
|
||||
- Монтировать `unresolved.json` явно: `-v "$(pwd)/unresolved.json:/config/unresolved.json"`
|
||||
|
||||
## *arr стек (добавлен 2026-05-17)
|
||||
|
||||
Prowlarr / Radarr / Sonarr + Transmission + Jellyfin — полностью настроены через API.
|
||||
Скилл: `~/.hermes/skills/arr-media-stack-setup/SKILL.md`
|
||||
|
||||
| Сервис | Порт | Compose dir |
|
||||
|--------|------|-------------|
|
||||
| Transmission | 9091 | `docker/transmission/` |
|
||||
| Radarr | 7878 | `docker/radarr/` |
|
||||
| Sonarr | 8989 | `docker/sonarr/` |
|
||||
| Prowlarr | 9696 | `docker/prowlarr/` |
|
||||
| Jellyfin | 8096 | `docker/jellyfin/` |
|
||||
|
||||
Все контейнеры в `media_net` (external network), кроме Jellyfin (читает диск напрямую).
|
||||
RuTracker индексер подключён через Prowlarr → fullSync в Radarr/Sonarr.
|
||||
|
||||
Скачка медиа-агентом: скилл `download-media` (Radarr/Sonarr API — только `curl + jq`, без python3).
|
||||
|
||||
**⚠️ Pitfall: Pi-hole DNS hijack** — при включённом Pi-hole Radarr/Sonarr могут получать 503 на DNS lookup (Pi-hole блокирует трекеры). Решение: whitelist в Pi-hole или прямые IP в настройках индексера.
|
||||
|
||||
**⚠️ Pitfall: curl отсутствует в Hermes-контейнере** — агент внутри Docker не может исполнять curl-команды из скилла. Skills path: `~/.hermes/skills/` видна только хостовому Hermes; контейнерный Hermes ищет в `/opt/data/skills/`.
|
||||
|
||||
## HDD Hardware Error — поведение при перегрузке
|
||||
|
||||
**Симптом (2026-05-18):** При одновременном rsync + Jellyfin transcode + docker overlay → ext4 сбрасывает ошибку Sense Key 0x4 (Hardware Error) → файловая система ремонтирует в read-only (`remount-ro`).
|
||||
|
||||
**Признаки:** Docker containers fail with `EIO` (I/O error -5), overlayfs недоступен.
|
||||
|
||||
**Восстановление:**
|
||||
1. Reboot Kraken (OMV или физически)
|
||||
2. При монтировании ext4 автоматически запускает fsck
|
||||
3. После ребута: `docker compose up -d` из каждого `~/docker/<service>/`
|
||||
|
||||
**Профилактика:** не запускать rsync и ffmpeg transcode одновременно. Jellyfin transcode: pgsrip (subtitle extraction) особенно нагружает CPU+диск.
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[personal-os-architecture]]
|
||||
- [[tech/media-pipeline-pitfalls]]
|
||||
- [[tech/htpc-steam-emulators]]
|
||||
|
||||
## Инцидент 2026-05-21 — containerd не стартовал после нечистого выключения
|
||||
|
||||
**Симптомы:** Крякен не отвечал по сети утром, потребовалась ручная перезагрузка. После ребута nginx отдавал "502 Bad Gateway" на `/sonarr`, `/radarr`, `/jellyfin` и др.
|
||||
|
||||
**Причина:** Жёсткое выключение → orphan cleanup на ext4 (`/dev/mmcblk0p2`). containerd стартовал пока FS была ещё read-only → erofs snapshotter не смог создать temp-файл → bolt metadata plugin упал → вся цепочка плагинов Docker не инициализировалась → контейнеры не поднялись → nginx bad gateway.
|
||||
|
||||
**Фикс:**
|
||||
1. Вручную: `systemctl restart containerd && systemctl restart docker`
|
||||
2. Добавлен `/etc/systemd/system/containerd.service.d/wait-for-fs.conf` — containerd ждёт `local-fs.target` перед стартом
|
||||
3. Добавлен `/etc/monit/conf.d/docker` — watchdog по `/var/run/docker.sock`, перезапускает containerd+docker если сокет недоступен (каждые ~2 мин)
|
||||
@@ -1,137 +0,0 @@
|
||||
---
|
||||
title: Media Pipeline — Pitfalls & Debug Notes
|
||||
namespace: work
|
||||
created: '2026-05-16'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
type: entity
|
||||
tags:
|
||||
- media-pipeline
|
||||
- swift
|
||||
- pitfalls
|
||||
- debugging
|
||||
confidence: high
|
||||
---
|
||||
# Media Pipeline — Pitfalls & Debug Notes
|
||||
|
||||
Операционные заметки по Swift media-pipeline (media_files_db / media-toolbox) на Кракене.
|
||||
Связано: [[personal-os-architecture]], [[tech/kraken-network]]
|
||||
|
||||
## §9.x Score Engine — Критические питфолы
|
||||
|
||||
**§9.9 Year tiebreak:**
|
||||
- `if count > 1` only — НИКОГДА не штрафовать единственного кандидата
|
||||
- Если кандидат один — year mismatch не является причиной для снижения score
|
||||
|
||||
**§9.6 Subset floor:**
|
||||
- Floor 0.35 когда queryToks ⊆ candidateToks (запрос является подмножеством кандидата)
|
||||
- Это нормально — не считать subset-матч за слабый результат
|
||||
|
||||
**False resolves:**
|
||||
- Проверять поле `title:` — если в title шум из имени файла = `hasBestEffortResult` junk, не настоящий resolve
|
||||
- Пример: `2001 Космическая одиссея.mkv` → title: `2001 Космическая одиссея.mkv` = junk
|
||||
|
||||
## Транслитерация
|
||||
|
||||
- `transliteratedToLatin` для кириллических названий генерирует мусорные запросы — TMDb не находит `Migratsiya`
|
||||
- **Решение:** не эмитить lat-запросы когда источник уже кириллица
|
||||
- `transliteratedToCyrillic` из латинских имён — полезен (`Osnovnoi` → `Основной Инстинкт` → TMDb находит)
|
||||
|
||||
## KP (Кинопоиск) Rate Limit
|
||||
|
||||
- KP — настоящий fallback, дёргается только если TMDb не дал winner
|
||||
- 40 KP-запросов vs 8428 TMDb в типичном прогоне
|
||||
- Лимит исчерпывается только после очистки кеша когда весь TMDb идёт заново
|
||||
- Проблема не в архитектуре — это нормально
|
||||
- **KP API URL смена домена (Баг 8):** `api.kinopoisk.dev` → `api.poiskkino.dev`. Swift URLSession при редиректе теряет `X-API-KEY` → пустые ответы кешируются. Фикс: обновить URL, добавить `shouldCache: ((Data) -> Bool)?` — не кешировать пустой `docs`.
|
||||
|
||||
## Docker Deploy — Kraken (обязательный порядок)
|
||||
|
||||
После каждого деплоя **обязательно** чистить dangling images, иначе диск забивается (~1-2GB за прогон):
|
||||
|
||||
```bash
|
||||
# Mac (после docker build)
|
||||
docker image prune -f
|
||||
|
||||
# Kraken (после docker load)
|
||||
ssh kraken "docker image prune -f"
|
||||
```
|
||||
|
||||
Полная последовательность деплоя:
|
||||
```bash
|
||||
# 1. Собрать
|
||||
docker build -f Dockerfile.kraken -t media-pipeline:kraken .
|
||||
|
||||
# 2. Перенести
|
||||
docker save media-pipeline:kraken -o /tmp/mp.tar
|
||||
scp /tmp/mp.tar kraken:/tmp/
|
||||
ssh kraken "docker load -i /tmp/mp.tar && rm /tmp/mp.tar && docker image prune -f"
|
||||
rm /tmp/mp.tar
|
||||
|
||||
# 3. Почистить локально
|
||||
docker image prune -f
|
||||
```
|
||||
|
||||
## Docker Run — Kraken
|
||||
|
||||
Всегда монтировать `unresolved.json` явно:
|
||||
```bash
|
||||
docker run \
|
||||
-v "$(pwd)/config.json:/config/config.json:ro" \
|
||||
-v "/media:/media" \
|
||||
-v "$(pwd)/cache:/cache" \
|
||||
-v "$(pwd)/unresolved.json:/config/unresolved.json" \
|
||||
media-pipeline
|
||||
```
|
||||
Без явного маунта `unresolved.json` пишется внутри контейнера и теряется.
|
||||
|
||||
## Пофикшенные баги (сессии 2026-05)
|
||||
|
||||
- `Code=516 EEXIST` в ApplyPhase — исправлен
|
||||
- Episode regex `\b` boundary — исправлен
|
||||
- BBC prefix strip + trim — исправлен
|
||||
- Yoficator Linux path — исправлен
|
||||
- Backtick в TitleParser (`/[^'\p{L}\p{N}]+/` → strip apostrophes first) — исправлен
|
||||
- §9.6 subset floor 0.35 — добавлен
|
||||
- §9.9 year tiebreak `count>1` only — исправлен
|
||||
- Year-miss retry в TMDb/KP providers — добавлен
|
||||
- KP API URL (`api.poiskkino.dev`) + пустой-docs no-cache — исправлен
|
||||
- Leet-speak в транслите (`4` = `ч`): `String.decodeLeetSpeak()` — исправлен
|
||||
- Год `2023г` (кириллическое `г`): `(19|20)\d\d)г\b` паттерн — исправлен
|
||||
- `TitleParser _year_` underscore boundary: `\b` → `(?<![0-9])..(?![0-9])` — исправлен (Баг 12)
|
||||
- `OutputConfig` `cartoons`/`documentaries` не optional в JSON: `decodeIfPresent` — исправлен
|
||||
- `xvid`/`divx` не в quality markers list — исправлен
|
||||
- TitleParser: год как название фильма (1984, 2001) → safety guard ≥2 букв перед — исправлен
|
||||
|
||||
## Трекер-парсеры (Steps A-C, 2026-05-17)
|
||||
|
||||
`TrackerPageParserRegistry` — dispatch по `url.host`:
|
||||
- `RutrackerPageParser` — CP1251/iconv, SwiftSoup, жанры из заголовка, KP/IMDb IDs
|
||||
- `RutorPageParser`, `NNMClubPageParser` — структура реализована, требует fixture тестов
|
||||
- `TrackerMediaKind` enum: movie/series/cartoon/documentary/music/audiobook/game/book/unknown
|
||||
- `extractMediaKind` — детект по `BB.catId`/`FORUM_ID` на странице (100+ forum IDs)
|
||||
|
||||
`DirectoryPolicy` / `MatchPolicy` / `MoveStrategy`:
|
||||
- `FileAction.transmissionMove(torrentId:, from:, to:)` — Codable
|
||||
- `buildMovieActions` читает policy, `needsSymlink`, `needsNFO`, `effectiveOutputDir`
|
||||
- `transmissionMove` когда есть `torrentId`, иначе `move`
|
||||
|
||||
**⚠️ `transmissionMove` генерируется только если scanner создал регион** (нужен video файл).
|
||||
Музыка/книги/игры из downloads не перекладываются — нет `videoExtensions` для аудио (Шаг D, pending).
|
||||
|
||||
## Agent/Sync Pitfall — Duplicate unresolved
|
||||
|
||||
**Проблема:** agent пишет canonical dir в `/media/library/`, но sync при следующем запуске снова добавляет файл в unresolved (нет source marker).
|
||||
|
||||
**Фикс:** `updateUnresolvedStore` проверяет `allOutputDirs` на существующий canonical dir → пропускает. Файл: `PipelineRunner.swift`.
|
||||
|
||||
## QuerySnapshotGenerator
|
||||
|
||||
При изменениях в `TitleParser`/`NameTokenization`/`QueryBuilder` снапшоты в тестах устаревают.
|
||||
**Регенерация:** `swift run QuerySnapshotGenerator` из корня репо.
|
||||
НЕ использовать `SNAPSHOT_TESTING_RECORD=all` — крашит при 364 concurrent writes (SIGSEGV).
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[personal-os-architecture]]
|
||||
- [[tech/kraken-network]]
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
title: reflect-skip Skip Fuse — Pitfalls
|
||||
created: '2026-05-20'
|
||||
updated: '2026-05-22'
|
||||
last_synced: '2026-05-22'
|
||||
type: reference
|
||||
namespace: personal
|
||||
tags:
|
||||
- reflect
|
||||
- skip
|
||||
- swiftui
|
||||
- kotlin
|
||||
- pitfall
|
||||
confidence: 0.9
|
||||
---
|
||||
# reflect-skip Skip Fuse — Adding a New SwiftUI View
|
||||
|
||||
## Problem
|
||||
|
||||
При добавлении нового SwiftUI View-файла в `Sources/ReflectApp/Views/` Skip Fuse **не создаёт Kotlin-стаб автоматически**. Приложение крашится с `ClassNotFoundException` при запуске.
|
||||
|
||||
## Fix — создать Kotlin-стаб вручную
|
||||
|
||||
Нужно создать стаб в **обоих** местах:
|
||||
|
||||
1. `DerivedData/.../reflect-skip.output/ReflectApp/skipstone/ReflectApp/src/main/kotlin/reflect/app/`
|
||||
2. `.build/plugins/outputs/reflect-skip/ReflectApp/destination/skipstone/ReflectApp/src/main/kotlin/reflect/app/`
|
||||
|
||||
**Шаблон:** скопировать `OnboardingView.kt`, заменить:
|
||||
- Имя класса
|
||||
- `@State` vars
|
||||
|
||||
Constructor принимает closure-параметры.
|
||||
|
||||
После создания стабов:
|
||||
|
||||
```bash
|
||||
skip gradle assembleDebug
|
||||
```
|
||||
|
||||
## Package.swift — обязательная структура
|
||||
|
||||
Без этих секций Xcode падает с "Missing package product 'ReflectApp'":
|
||||
|
||||
```swift
|
||||
// Package.swift — обязательные поля
|
||||
dependencies: [
|
||||
.package(url: "https://source.skip.tools/skip.git", from: "1.8.9"),
|
||||
.package(url: "https://source.skip.tools/skip-fuse.git", from: "1.0.0"),
|
||||
.package(url: "https://source.skip.tools/skip-fuse-ui.git", from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "ReflectApp",
|
||||
path: "Sources/ReflectApp",
|
||||
dependencies: [
|
||||
.product(name: "SkipFuse", package: "skip-fuse"),
|
||||
.product(name: "SkipFuseUI", package: "skip-fuse-ui"),
|
||||
],
|
||||
plugins: [.plugin(name: "skipstone", package: "skip")]
|
||||
)
|
||||
]
|
||||
```
|
||||
|
||||
**Pitfall:** нужны оба: `skip-fuse` (runtime) + `skip-fuse-ui` (SwiftUI overlay для Android). Ранее была попытка использовать `skip-ui` вместо `skip-fuse-ui` — это неверно, `skip-ui` не предоставляет `SwiftUI` модуль для Android-сборки и ломает full build с `no such module 'SwiftUI'`.
|
||||
|
||||
## Прочие питфоллы
|
||||
|
||||
- `@State private` → менять на `internal` в Kotlin-стабе
|
||||
- `case none` в enum крашит JNI — избегать
|
||||
- `ViewModifier` → инлайнить в тело View
|
||||
- `PRODUCT_NAME=ReflectApp` в Build Settings не менять
|
||||
- `@AppStorage` поля добавлять вручную в Kotlin-стаб
|
||||
|
||||
## Deploy & Signing
|
||||
|
||||
```bash
|
||||
# Build and publish (~15s Gradle):
|
||||
./build-and-publish.sh
|
||||
```
|
||||
|
||||
Android signing keystore: `~/.android/signing/nolvu-release.jks` (alias: nolvu2026)
|
||||
|
||||
## Проект
|
||||
|
||||
`~/Developer/reflect-skip`
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[tech/hermes-eagle-mac]] — Hermes на Eagle, openclaw-claude-proxy
|
||||
- [[tech/hermes-docker-kraken]] — Hermes на Кракене (Docker)
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
title: TrueNAS Inpxer — Книги & Pitfalls
|
||||
type: reference
|
||||
namespace: work
|
||||
tags:
|
||||
- truenas
|
||||
- inpxer
|
||||
- books
|
||||
- pitfalls
|
||||
created: '2026-05-18'
|
||||
updated: '2026-05-18'
|
||||
---
|
||||
# TrueNAS Inpxer — Книги & Pitfalls
|
||||
|
||||
## Пути
|
||||
|
||||
| | |
|
||||
|--|--|
|
||||
| Хранилище книг | `/mnt/RED_2TB/Edu/` (214 GB) |
|
||||
| Загрузка новых | `/mnt/RED_2TB/storage/books/` |
|
||||
| Inpxer UI | `books.mallexxx.duckdns.org` |
|
||||
|
||||
## Pitfall: Badger DB блокировка
|
||||
|
||||
**Проблема:** Badger DB (используется inpxer) блокируется при параллельных загрузках.
|
||||
|
||||
**Симптом:** ошибка блокировки БД при параллельном добавлении книг.
|
||||
|
||||
**Решение:** качать книги по одной, пауза 3 секунды между загрузками.
|
||||
|
||||
```bash
|
||||
# Не делать так (параллельно):
|
||||
for book in *.epub; do upload "$book"; done
|
||||
|
||||
# Правильно (последовательно с паузой):
|
||||
for book in *.epub; do upload "$book"; sleep 3; done
|
||||
```
|
||||
|
||||
## Связанные страницы
|
||||
|
||||
- [[entities/library-app]] — книжная библиотека на TrueNAS (inpxer UI)
|
||||
- [[concepts/kraken-media-stack]] — полный стек на Кракене (медиа + книги)
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
title: Vault Namespace Rules
|
||||
namespace: work
|
||||
created: '2026-05-17'
|
||||
updated: '2026-05-20'
|
||||
last_synced: '2026-05-20'
|
||||
type: reference
|
||||
tags:
|
||||
- vault
|
||||
- namespace
|
||||
- obsidian
|
||||
- infra
|
||||
confidence: high
|
||||
---
|
||||
# Vault Namespace Rules
|
||||
|
||||
Актуально с 2026-05-15.
|
||||
|
||||
## WORK (Eagle + Android, DDG-specific)
|
||||
- `work/briefs/daily|weekly|eod|inbox/`
|
||||
- `work/wiki/`
|
||||
- `work/plans/`
|
||||
- `work/projects/`
|
||||
|
||||
> В work — **только DDG data**.
|
||||
|
||||
## PERSONAL (все устройства)
|
||||
- `personal/projects/personal-os/` — executor, wiki, pipeline, infra
|
||||
- `personal/projects/`
|
||||
- `personal/plans/`
|
||||
- `personal/`
|
||||
- `family/`
|
||||
|
||||
## Правила переноса
|
||||
- Планы personal-os/llm-wiki/infra → `personal/`
|
||||
- Личные проекты не смешивать с work
|
||||
|
||||
## Vault style
|
||||
- Titles — русской кириллицей
|
||||
- Aliases: `[РУ вариант, EN вариант, slug]`
|
||||
Reference in New Issue
Block a user