Merge remote-tracking branch 'origin/main'
This commit is contained in:
Executable
+136
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: Arr Stack — Kraken
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-27'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [arr, radarr, sonarr, prowlarr, transmission, jellyfin, infra, kraken]
|
||||
related:
|
||||
- "[[tech/jellyfin-config]]"
|
||||
- "[[tech/arr-stack-taiga]]"
|
||||
- "[[concepts/kraken-media-stack]]"
|
||||
---
|
||||
|
||||
# Arr Stack — Kraken
|
||||
|
||||
## Pipeline
|
||||
|
||||
```
|
||||
Prowlarr → Radarr + Sonarr → Transmission → Jellyfin
|
||||
↓
|
||||
router.py (cron 10min)
|
||||
↓
|
||||
symlinks → /media/{movies,cartoons,series,documentaries,...}/
|
||||
```
|
||||
|
||||
Два параллельных пути поступления контента:
|
||||
|
||||
1. **Radarr/Sonarr** → качают в `/media/movies-radarr/` и `/media/series-sonarr/`
|
||||
2. **Transmission (ручные торренты)** → `on-download-complete.sh` → `sync.py` → `/media/{movies,cartoons,...}/`
|
||||
|
||||
### router.py — жанровая маршрутизация
|
||||
|
||||
`router.py` читает NFO-файлы (которые Radarr/Sonarr создают при загрузке), определяет жанр и возрастной рейтинг, и создаёт symlink в нужную Jellyfin-библиотеку:
|
||||
|
||||
| Источник | Условие | Цель |
|
||||
|---|---|---|
|
||||
| movies-radarr/ | Documentary | `/media/documentaries/` |
|
||||
| movies-radarr/ | Animation + !R/18+ | `/media/cartoons/` |
|
||||
| movies-radarr/ | всё остальное | `/media/movies/` |
|
||||
| series-sonarr/ | Documentary | `/media/documentaries-series/` |
|
||||
| series-sonarr/ | Animation + !TV-MA | `/media/cartoons-series/` |
|
||||
| series-sonarr/ | всё остальное | `/media/series/` |
|
||||
|
||||
**Расположение:** `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/media-pipeline/router.py`
|
||||
**Запуск:** `python3 router.py --dry-run` (проверка) / `python3 router.py --apply` (исполнение)
|
||||
|
||||
### media-router.sh — cron-скрипт для Telegram-уведомлений
|
||||
|
||||
Обёртка над `router.py`, которая:
|
||||
- запускает `router.py --apply`
|
||||
- если `Nothing to do` — **SILENT**, ничего не шлёт
|
||||
- если созданы symlink'и или ошибка — отправляет отчёт в Telegram Kraken
|
||||
|
||||
**Расположение:** рядом с `router.py` — `media-router.sh`
|
||||
**Cron (Kraken crontab):** каждые 10 минут
|
||||
**Telegram:** kraken_htpc_bot → чат @mallex87
|
||||
|
||||
### sync.py — обработка ручных торрентов (Transmission)
|
||||
|
||||
`sync.py` работает внутри Transmission-контейнера. При завершении загрузки:
|
||||
1. Определяет название через TMDB API
|
||||
2. Определяет жанр
|
||||
3. Перемещает файл в `/media/{movies,cartoons,series,documentaries}/`
|
||||
4. Обновляет `downloadDir` в Transmission через RPC
|
||||
|
||||
**Расположение:** `/srv/.../docker/media-pipeline/sync.py`
|
||||
**Триггер:** `on-download-complete.sh` (смонтирован в Transmission как `/config/on-download-complete.sh:ro`)
|
||||
|
||||
## Transmission
|
||||
|
||||
- **download-dir:** `/downloads` (без `complete`)
|
||||
- **incomplete-dir:** `/downloads/incomplete`
|
||||
- **Язык:** отключён auth для локальных
|
||||
- **RPC:** `localhost:9091`
|
||||
|
||||
При перемещении файлов для уже завершённых торрентов:
|
||||
1. Переименовать файл/папку под кейс торрента (Linux ext4 case-sensitive)
|
||||
2. Вызвать `torrent-set-location` с `move=false`
|
||||
3. Запустить торрент на сидирование
|
||||
|
||||
## Cron'ы на Kraken (crontab)
|
||||
|
||||
```
|
||||
0 * * * * bash ~/scripts/sync-vault.sh # Obsidian sync
|
||||
0 * * * * pgs-to-srt.sh /media/downloads # PGS→SRT новые
|
||||
0 3 * * * pgs-to-srt.sh /media # PGS→SRT вся библиотека
|
||||
0 1 * * * bash ~/scripts/watchlist-nightly.sh # watchlist nightly
|
||||
0 9 * * 0 bash ~/scripts/watchlist-discover.sh # watchlist discover
|
||||
*/10 * * * * bash .../media-pipeline/media-router.sh # media router (Telegram)
|
||||
```
|
||||
|
||||
## API Keys
|
||||
|
||||
| Service | API Key |
|
||||
|-------------|----------------------|
|
||||
| Radarr | `cbcb8ec3...` |
|
||||
| Sonarr | `15fbec32...` |
|
||||
| Prowlarr | `134ac38a...` |
|
||||
|
||||
(Full keys truncated — retrieve from each service's settings page.)
|
||||
|
||||
## Ports (default Docker network)
|
||||
|
||||
All services accessible at `kraken:<port>`:
|
||||
|
||||
| Service | Port |
|
||||
|--------------|------|
|
||||
| Radarr | 7878 |
|
||||
| Sonarr | 8989 |
|
||||
| Prowlarr | 9696 |
|
||||
| Transmission | 9091 |
|
||||
| Jellyfin | 8096 |
|
||||
|
||||
## Jellyfin библиотеки
|
||||
|
||||
| Библиотека | Тип | Путь |
|
||||
|---|---|---|
|
||||
| Movies | movies | `/media/movies` |
|
||||
| Series | tvshows | `/media/series` |
|
||||
| Cartoons | movies | `/media/cartoons` |
|
||||
| Cartoon Series | tvshows | `/media/cartoons-series` |
|
||||
| Documentaries | movies | `/media/documentaries` |
|
||||
| Documentary Series | tvshows | `/media/documentaries-series` |
|
||||
|
||||
> `movies-radarr` и `series-sonarr` НЕ добавлены в Jellyfin — router.py создаёт symlink'и из них в перечисленные пути.
|
||||
|
||||
## Известные проблемы
|
||||
|
||||
- **17 фильмов в Radarr `hasFile=False`** — ждут подходящего релиза в Prowlarr. Scream (1996) в процессе загрузки.
|
||||
- **Prowlarr** — если долго не находит релизы, проверить статус индексеров (`/api/v1/health`).
|
||||
|
||||
## Notes
|
||||
|
||||
- See [[arr-stack-taiga]] for Taiga (secondary) arr stack
|
||||
- Media pipeline pitfalls: [[media-pipeline-pitfalls]]
|
||||
- Синтез: [[concepts/kraken-media-stack]]
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Arr Stack — Taiga
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [arr, taiga, infra, media, pitfalls]
|
||||
related:
|
||||
- "[[tech/arr-stack-kraken]]"
|
||||
---
|
||||
|
||||
# Arr Stack — Taiga
|
||||
|
||||
Secondary arr stack on Taiga (TrueNAS), added 2026-05-20.
|
||||
|
||||
## Notes from Setup (2026-05-20)
|
||||
|
||||
- Config and pitfalls recorded during initial Taiga arr stack deployment
|
||||
- `router.py` was customized — check `/mnt/RED_2TB/docker/arr-taiga/router.py`
|
||||
for current state
|
||||
|
||||
## Key Differences from Kraken Stack
|
||||
|
||||
- Taiga = TrueNAS host (storage-focused)
|
||||
- Kraken = Raspberry Pi 5 (playback-focused)
|
||||
- Taiga stack handles acquisition; Kraken handles serving to Jellyfin
|
||||
|
||||
## Pitfalls
|
||||
|
||||
(Details were referenced but not captured. Update this page after next
|
||||
Taiga arr maintenance session.)
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Gitea Config
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [infra, gitea, git, credentials]
|
||||
related:
|
||||
- "[[tech/kraken-network]]"
|
||||
---
|
||||
|
||||
# Gitea Config
|
||||
|
||||
**URL:** `http://git.mallexxx.duckdns.org` (external) / `http://172.16.3.4:3000` (internal LAN)
|
||||
**User:** `git_admin`
|
||||
|
||||
## API Token
|
||||
|
||||
Token name: `eagle-reflect`
|
||||
Token value: `f2e679a571f4c599d64b384a711043f995fd8844`
|
||||
|
||||
Used by Eagle for repo operations (push, PR creation, hook management).
|
||||
|
||||
## Notes
|
||||
|
||||
- External URL uses DuckDNS DDNS pointing to home IP
|
||||
- Internal API endpoint preferred when on home network
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: Hermes Docker on Kraken
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-29'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [hermes, docker, kraken, infra, how-to]
|
||||
related:
|
||||
- "[[tech/kraken-network]]"
|
||||
- "[[concepts/hermes-deployment-patterns]]"
|
||||
- "[[tech/hermes-kraken-api]]"
|
||||
---
|
||||
|
||||
# Hermes Docker on Kraken
|
||||
|
||||
## Key Rule
|
||||
|
||||
Hermes runs via **`docker run`**, NOT `docker compose`. No compose file.
|
||||
|
||||
## Launch Pattern
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name hermes \
|
||||
--restart unless-stopped \
|
||||
-v ~/.hermes:/root/.hermes \
|
||||
... \
|
||||
hermes-image:tag
|
||||
```
|
||||
|
||||
(Add actual flags from the running container: `docker inspect hermes`)
|
||||
|
||||
## Notes
|
||||
|
||||
- Using `docker run` keeps restart behavior explicit
|
||||
- No compose means no accidental `docker compose down` wipes it
|
||||
- Config/memory volume: `~/.hermes` on Kraken host
|
||||
Executable
+229
@@ -0,0 +1,229 @@
|
||||
---
|
||||
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]] — сетевая топология
|
||||
- [[concepts/hermes-deployment-patterns]] — сравнение трёх моделей деплоя Hermes
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Hermes Kraken — OpenAI-Compatible API Server
|
||||
created: '2026-05-29'
|
||||
updated: '2026-05-29'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [hermes, kraken, infra, agent, how-to]
|
||||
sources:
|
||||
- family/projects/aide-kraken-backend.md
|
||||
confidence: medium
|
||||
related:
|
||||
- "[[tech/hermes-docker-kraken]]"
|
||||
- "[[tech/vps-qentra]]"
|
||||
---
|
||||
|
||||
# Hermes Kraken — OpenAI-Compatible API Server
|
||||
|
||||
Hermes on Kraken exposes an OpenAI-compatible `/v1/chat/completions`
|
||||
endpoint (`gateway/platforms/api_server.py`). Exposed externally via
|
||||
Cloudflare Tunnel → used by the Android **Aide** app as a Hermes-backed
|
||||
assistant.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Android (Aide)
|
||||
└── HTTPS → hermes.kraken.qentra.top/v1/chat/completions
|
||||
↓ Cloudflare Tunnel
|
||||
cloudflared (Kraken, host network)
|
||||
↓ localhost:8642
|
||||
hermes-kraken (docker run, network_mode: host)
|
||||
↓
|
||||
Hermes gateway → Gemini / OpenRouter / ...
|
||||
```
|
||||
|
||||
`network_mode: host` means port 8642 is directly on the Kraken host —
|
||||
no port mapping needed.
|
||||
|
||||
## Config (Kraken /opt/data/config.yaml)
|
||||
|
||||
```yaml
|
||||
api_server:
|
||||
enabled: true
|
||||
port: 8642
|
||||
host: "0.0.0.0"
|
||||
key: "<secret>" # openssl rand -hex 32
|
||||
```
|
||||
|
||||
Restart container via Portainer or:
|
||||
```bash
|
||||
BASE=http://localhost:9000
|
||||
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
|
||||
EP=3
|
||||
CID=$(curl -s -H "X-API-Key: $KEY" \
|
||||
"$BASE/api/endpoints/$EP/docker/containers/json" \
|
||||
| jq -r '.[] | select(.Names[] | contains("hermes-kraken")) | .Id')
|
||||
curl -s -X POST -H "X-API-Key: $KEY" \
|
||||
"$BASE/api/endpoints/$EP/docker/containers/$CID/restart"
|
||||
```
|
||||
|
||||
Health check: `curl -s http://localhost:8642/health`
|
||||
|
||||
## Cloudflare Tunnel Setup
|
||||
|
||||
Tunnel name: `kraken`. Public hostname (CF Zero Trust dashboard):
|
||||
- **Hostname:** `kraken.qentra.top`
|
||||
- **Type:** HTTP (not SSH)
|
||||
- **URL:** `localhost:8642`
|
||||
|
||||
SSH to Kraken still works via VPS reverse tunnel (port 2223) — the CF
|
||||
hostname change does not affect SSH access.
|
||||
|
||||
## Aide Android Client Config
|
||||
|
||||
Provider: Custom Endpoint
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Base URL | `https://kraken.qentra.top/v1` |
|
||||
| API Key | secret from config.yaml |
|
||||
| Model | `hermes-agent` (maps to Hermes internally) |
|
||||
|
||||
## What Was Not Changed
|
||||
|
||||
- cloudflared container — already running
|
||||
- VPS reverse SSH tunnel — unaffected
|
||||
- `network_mode: host` on hermes-kraken — already set
|
||||
|
||||
## See Also
|
||||
|
||||
- [[tech/hermes-docker-kraken]] — how Hermes runs on Kraken (docker run
|
||||
pattern, no compose)
|
||||
- [[tech/vps-qentra]] — VPS qentra.top: Cloudflare + nginx stack
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: HTPC Bazzite Ecosystem — Overview
|
||||
created: '2026-05-28'
|
||||
updated: '2026-05-28'
|
||||
type: concept
|
||||
namespace: family
|
||||
tags: [htpc, infra, how-to]
|
||||
sources: []
|
||||
confidence: medium
|
||||
related:
|
||||
- "[[htpc-bazzite-proton]]"
|
||||
- "[[tech/htpc-steam-emulators]]"
|
||||
- "[[tech/htpc-kodi-layout]]"
|
||||
- "[[tech/htpc-magic4pc]]"
|
||||
---
|
||||
|
||||
# HTPC Bazzite Ecosystem — Overview
|
||||
|
||||
Synthesis across [[htpc-bazzite-proton]], [[tech/htpc-steam-emulators]],
|
||||
[[tech/htpc-kodi-layout]], and [[tech/htpc-magic4pc]].
|
||||
|
||||
Intel i7-6800K / RX 570 / Bazzite 44 at `192.168.1.86`. Connected to
|
||||
LG webOS TV (`192.168.1.75`) via HDMI.
|
||||
|
||||
## Mode Map
|
||||
|
||||
| Mode | Entry | What runs |
|
||||
|------|-------|-----------|
|
||||
| Steam Big Picture (gamescope) | Default boot | Steam Gaming Mode + 39 non-Steam shortcuts |
|
||||
| KDE Desktop | Ctrl+Alt+F2 or Steam → "Switch to Desktop" | Full desktop + Kodi launcher |
|
||||
| Kodi | From KDE | NFS/SMB media browsing (see [[tech/htpc-kodi-layout]]) |
|
||||
| Emulators | Steam shortcuts (gamescope or KDE) | RetroArch, EmuDeck |
|
||||
|
||||
## Input Devices
|
||||
|
||||
| Device | Role |
|
||||
|--------|------|
|
||||
| 2× 8BitDo Ultimate dongles | Primary gamepads |
|
||||
| Xbox 360 Wireless Receiver | Secondary gamepad |
|
||||
| LG Magic Remote (magic4pc) | TV remote → mouse/keyboard via [[tech/htpc-magic4pc]] |
|
||||
|
||||
**8BitDo pitfall:** both dongles must be on separate physical USB ports
|
||||
(not the same hub). See [[tech/htpc-steam-emulators]].
|
||||
|
||||
## Windows Games via Proton
|
||||
|
||||
39 games added as non-Steam shortcuts. Most on GE-Proton10-34.
|
||||
Compatibility matrix and fix recipes: [[htpc-bazzite-proton]].
|
||||
|
||||
Highlights:
|
||||
- VK GameCenter (Atomic Heart) — working ✅
|
||||
- Rayman Origins — GE-Proton + `d3d9=b` ✅
|
||||
- Doom 3 BFG — Luxtorpeda (rbdoom-3-bfg flatpak) ✅
|
||||
- 5 games still broken (Brawlhalla, Castle Crashers, Worms ×2, Duck Game)
|
||||
|
||||
## Non-Steam Shortcut Management
|
||||
|
||||
VDF shortcuts via Python `vdf` module. **Rules:**
|
||||
1. Stop Steam before editing `shortcuts.vdf`
|
||||
2. Use `vdf.binary_load` — never manual byte editing
|
||||
3. Keep `bak-eagle` (23 May, 106 entries) as recovery baseline
|
||||
|
||||
See full guide in [[htpc-bazzite-proton]] § VDF.
|
||||
|
||||
## Cover Art
|
||||
|
||||
`steam-grid-artwork.py` (at vault root) — fetches artwork from
|
||||
SteamGridDB for non-Steam shortcuts. Run when adding new shortcuts.
|
||||
|
||||
## Maintenance Notes
|
||||
|
||||
- `rpm-ostree upgrade` resets `/usr/local/bin/magic4pc` — rebuild and redeploy
|
||||
- VDF backup: `saves-backup.service` (systemd, daily rsync)
|
||||
- Proton updates: extract tar.gz into `~/.steam/steam/compatibilitytools.d/`
|
||||
Executable
+319
@@ -0,0 +1,319 @@
|
||||
---
|
||||
confidence: medium
|
||||
created: '2026-05-23'
|
||||
namespace: personal
|
||||
sources:
|
||||
- family/projects/htpc-windows-games-fix.md
|
||||
tags:
|
||||
- htpc
|
||||
- infra
|
||||
- how-to
|
||||
- pitfalls
|
||||
- vk-play
|
||||
- atomic-heart
|
||||
- vdf
|
||||
- doom
|
||||
title: HTPC Bazzite — Proton Compatibility
|
||||
type: tech
|
||||
updated: '2026-05-27'
|
||||
---
|
||||
# HTPC Bazzite — Windows Game Proton Compatibility
|
||||
|
||||
Bazzite HTPC at `bazzite@192.168.1.86`. 39 non-Steam Windows games added as
|
||||
Steam shortcuts (2026-05-22). Default tool: Proton Experimental; older titles
|
||||
on Proton 8.0.
|
||||
|
||||
---
|
||||
|
||||
## Working ✅
|
||||
|
||||
- Fallout 4
|
||||
- Vladik Brutal
|
||||
- Red Alert 3
|
||||
- **Rayman Origins** (fixed 2026-05-23 — GE-Proton10-34 + `WINEDLLOVERRIDES=\"d3d9=b\" %command%`)
|
||||
- Samurai Gunn (works but **gamepad not detected**)
|
||||
- GTA V, Cuphead (assumed; not retested)
|
||||
<<<<<<< HEAD
|
||||
- **VK GameCenter** (GE-Proton10-34, shared prefix c Lutris, авторизация через Lutris + `vk-login-helper`)
|
||||
- **Atomic Heart VK** (через VK GameCenter, 97GB, `Data/gamecenter/atomic heart/`, URL-схема `vkplay://play/0.2015959`)
|
||||
=======
|
||||
- **VK GameCenter** (GE-Proton10-34, `Data/gamecenter/GameCenter/`)
|
||||
- **Atomic Heart VK** (через VK GameCenter, 97GB, `Data/gamecenter/atomic heart/`)
|
||||
>>>>>>> nas/main
|
||||
- **Doom 3 BFG** (через flatpak Classic-RBDOOM-3-BFG)
|
||||
|
||||
## Removed from Steam shortcuts ✅
|
||||
- Human Fall Flat (3928445186) — already in real Steam
|
||||
- Shovel Knight (2526703384) — already in real Steam
|
||||
|
||||
## Mapped to GE-Proton10-34 but still broken
|
||||
|
||||
| Game | AppID | Symptom | LaunchOpt set |
|
||||
|------|-------|---------|---------------|
|
||||
| Brawlhalla | 2410005953 | Doesn't start | `WINEDLLOVERRIDES=\"msvcp140,vcruntime140=n,b\"` |
|
||||
| Castle Crashers | 3048471472 | "crash, mini dump sent" | `WINEDLLOVERRIDES=\"msvcp140,vcruntime140=n,b\"` |
|
||||
| Worms WMD | 3846411911 | Doesn't start | `WINEDLLOVERRIDES=\"msvcp140,vcruntime140,d3dcompiler_47=n,b\"` |
|
||||
| Worms World Party | 2401592779 | Doesn't start | `WINEDLLOVERRIDES=\"msvcp140,vcruntime140=n,b\"` |
|
||||
| Duck Game | 2926094216 | Won't launch | `WINEDLLOVERRIDES=\"msvcp140,vcruntime140=n,b\"` |
|
||||
|
||||
- **Doom 3 BFG** (flatpak, appid `-2113091226`) — работает ✅
|
||||
- **Atomic Heart VK / VK GameCenter** — VK GameCenter запускается через Steam (GE-Proton10-34). Atomic Heart (97GB) установлен через GameCenter на Data. Exe GameCenter скопирован на Data (не на Windows/ — read-only). Symlink `d:` в dosdevices ведёт на `/run/media/bazzite/Data`.
|
||||
|
||||
## Target:
|
||||
|
||||
## Still broken — fundamental issues
|
||||
|
||||
| Game | AppID | Symptom | What's known | What might help |
|
||||
|------|-------|---------|--------------|-----------------|
|
||||
| Atomic Bomberman / BM95 | 2875360586 | Crash "instruction at 0x0 referenced 0x7" | Win3.1-era PE32. Tried: `proton_8`, registry `Version=win98`, virtual desktop 640×480, WineBus controllers off | Dedicated 32-bit `WINEARCH=win32`; or DOSBox‑X |
|
||||
| Discworld Noir | 2361018632 | "Please insert disk III" | Russian 2-CD "Zatmenie v2". 69 missing files copied ✅. Drive D: → cd2 as CD-ROM | Try cd1; or mount `.nrg` images |
|
||||
| Final Fantasy X HD | 2642741094 | Was Japanese, no saves | `GameSetting.ini` replaced (en+HD) from Windows | Test pending |
|
||||
| Metal Slug X | 2938712902 | Speed wrong, controls dead | Neo-Geo emulator config issue, not Wine | — |
|
||||
| Metro Exodus | 3594910936 | "Unable to create interface isteamuser" | VC++ runtime copied | Needs Goldberg `steam_api64.dll` + `steam_appid.txt` |
|
||||
| Split Second | 3871231787 | Green artifacts | `PROTON_USE_WINED3D=1` | Switch to GE-Proton; copy `d3dx9_*.dll` |
|
||||
| Super Bomberman R2 | 3340354231 | Gamepad not detected | Steam Input config issue | — |
|
||||
|
||||
## Gamepad Issues
|
||||
- **Samurai Gunn, Super Bomberman R2**: not detected → Steam Input "Force Off" / "Use Default" cycle; or `SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD=1`
|
||||
- **Metal Slug X**: wrong speed in Neo-Geo wrapper
|
||||
|
||||
---
|
||||
|
||||
## Common Fix Recipes
|
||||
|
||||
### "Doesn't start" → try vcrun2019
|
||||
```
|
||||
protontricks <AppID> vcrun2019 d3dcompiler_47
|
||||
```
|
||||
|
||||
### XNA 4.0 games (Duck Game, etc.)
|
||||
```
|
||||
protontricks <AppID> xna40
|
||||
```
|
||||
|
||||
### DOS-era games (e.g. Atomic Bomberman)
|
||||
Proton won't work. Use **Steam Tinker Launch** → wrap with DOSBox (dosbox-staging).
|
||||
|
||||
### Non-Steam copy of a Steam game (e.g. Metro Exodus)
|
||||
Game needs `steam_api64.dll` emulator:
|
||||
1. Drop in Goldberg `steam_api64.dll`
|
||||
2. Add `steam_appid.txt` with the real App ID (e.g. 412020 for Metro Exodus Enhanced)
|
||||
|
||||
### Cyrillic encoding issues (e.g. Discworld Noir)
|
||||
Try in order:
|
||||
1. `LANG=ru_RU.UTF-8 %command%`
|
||||
2. `WINEDLLOVERRIDES=\"gdiplus=n,b\"`
|
||||
3. Install `ttf-mscorefonts` + set Cyrillic codepage in Wine registry
|
||||
|
||||
### White screen / broken D3D9 (Rayman Origins, Split Second)
|
||||
```
|
||||
PROTON_USE_WINED3D=1 %command%
|
||||
```
|
||||
Or try `WINEDLLOVERRIDES=\"d3d9=b\"` or an older Proton version.
|
||||
|
||||
### Doom 3 BFG Edition — чёрные текстуры, краш после интро
|
||||
Proton ломает текстуры — известный регресс. **Фикс:** Luxtorpeda → rbdoom-3-bfg (native Linux engine).
|
||||
|
||||
---
|
||||
|
||||
## VK Play / VK GameCenter на Bazzite
|
||||
|
||||
### Аккаунты VK Play
|
||||
- **Основной:** `xxxellam@gmail.com` — Google, залогинен на Bazzite
|
||||
- **Дополнительный:** `mallexxx@mail.ru` — подключён к VK Play
|
||||
|
||||
### Общая схема
|
||||
VK Play версии игр запускаются через лаунчер VK GameCenter (`GameCenter.exe`) поверх Proton. Лаунчер отвечает за авторизацию и лицензирование (в т.ч. Denuvo-эмуляцию).
|
||||
|
||||
Известно:
|
||||
- VK Play официально подтвердил совместимость Atomic Heart со Steam Deck/Proton.
|
||||
- Для авторизации используется `mycomgames://` URL-схема. На HTPC без Steam Deck API может потребоваться ручной ввод логина/пароля.
|
||||
- Альтернатива: Lutris с конфигом из gist.github.com/keyCat (обработчик `mycomgames://` схемы).
|
||||
- Перед первым запуском может понадобиться `protontricks -555655402 vcrun2019`.
|
||||
|
||||
### Как добавить VK Play игру
|
||||
1. Запустить VK GameCenter через Steam (GE-Proton10-34)
|
||||
2. Авторизоваться в VK Play
|
||||
3. Установить игру через лаунчер (Atomic Heart уже установлен)
|
||||
4. После авторизации игра появится в библиотеке VK Play
|
||||
|
||||
### Lutris login workaround (shared prefix with Steam/Proton)
|
||||
|
||||
**Проблема:** Steam CEF browser не умеет обрабатывать `mycomgames://` URL-схему, необходимую для OAuth-логина VK Play. При клике "Login" — `ERR_NETWORK_IO_SUSPENDED`.
|
||||
|
||||
**Решение:** использовать Lutris для первичной авторизации, потом запускать игру через Steam/Proton.
|
||||
|
||||
### Implementation status (2026-05-28)
|
||||
|
||||
Все компоненты настроены через SSH (Kraken → HTPC). Последний шаг (логин) требует GUI-сеанса на HTPC.
|
||||
|
||||
| Component | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| `d:` dosdevices symlink (→ Data) | ✅ | `/run/media/bazzite/Data` |
|
||||
| `handle-vkplay-scheme` script | ✅ | `~/.local/bin/` — обрабатывает `mycomgames://` через Proton 10.0 |
|
||||
| `.desktop` → MIME `x-scheme-handler/mycomgames` | ✅ | Зарегистрирован на `Vkplay-scheme-handler.desktop` |
|
||||
| Lutris flatpak | ✅ | `flathub net.lutris.Lutris` |
|
||||
| Lutris game config (shared prefix) | ✅ | `~/.config/lutris/games/vk-play-shared.yml` |
|
||||
| `start-vk.cmd` in Proton prefix | ✅ | `drive_c/VKPlay/gamecenter/start-vk.cmd` |
|
||||
| Steam shortcut VK GameCenter | ✅ | AppID=-1973339958, GE-Proton10-34 |
|
||||
| Steam shortcut Atomic Heart VK | ✅ | AppID=-1973339958 (через GameCenter) |
|
||||
| Atomic Heart installed (97GB) | ✅ | `/run/media/bazzite/Data/gamecenter/atomic heart/` |
|
||||
|
||||
**Осталось сделать (на HTPC в десктоп-режиме):**
|
||||
1. Открыть Lutris → VK Play Game Center → Login
|
||||
2. Авторизоваться в браузере, разрешить `mycomgames://`
|
||||
3. Вернуться в игровой режим
|
||||
4. Запустить Atomic Heart через Steam → ожидать что токен в shared prefix работает
|
||||
|
||||
1. Установить Lutris через flatpak:
|
||||
```
|
||||
flatpak install flathub net.lutris.Lutris
|
||||
```
|
||||
|
||||
2. Создать кастомный пресет VK GameCenter в Lutris, указав **тот же Wine prefix**, что использует Steam:
|
||||
```
|
||||
~/.local/share/Steam/steamapps/compatdata/-1973339958/pfx/
|
||||
```
|
||||
|
||||
3. Зарегистрировать `mycomgames://` protocol handler — поместить .desktop-файл, который ассоциирует схему с Lutris:
|
||||
- Референс: https://gist.github.com/keyCat/a77b1d4d1e0f651b9d3a9818e7f739c5
|
||||
|
||||
4. Выполнить логин через Lutris — откроется внешний браузер, авторизация сработает, редирект `mycomgames://` попадёт в Lutris.
|
||||
|
||||
5. После успешного логина запускать игру через Steam — токен уже лежит в shared prefix, `mycomgames://` больше не нужен.
|
||||
|
||||
**Почему shared prefix:** игра (Atomic Heart, 97GB) НЕ копируется — она уже установлена в `/run/media/bazzite/Data/gamecenter/atomic heart/` через Steam-версию VK GameCenter. Lutris будет использовать тот же префикс, где уже есть dosdevices symlink `d:` → `/run/media/bazzite/Data` и все токены авторизации.
|
||||
|
||||
---
|
||||
|
||||
## How to Add a Non-Steam Game via VDF
|
||||
|
||||
**Шаг 0: Остановить Steam**
|
||||
```
|
||||
systemctl --user stop gamescope-session-plus@steam.service
|
||||
```
|
||||
|
||||
**Шаг 1: Прочитать shortcuts.vdf backup**
|
||||
AppID в shortcuts.vdf — signed int32. В config.vdf CompatToolMapping — unsigned uint32.
|
||||
```python
|
||||
import vdf
|
||||
# read backup
|
||||
with open('shortcuts.vdf.bak-eagle', 'rb') as f:
|
||||
d = vdf.binary_loads(f.read())
|
||||
# edit d['shortcuts']
|
||||
# write
|
||||
with open('shortcuts.vdf', 'wb') as f:
|
||||
f.write(vdf.binary_dumps(d))
|
||||
```
|
||||
|
||||
**Шаг 2: Добавить CompatToolMapping в config.vdf**
|
||||
Unsigned appid = signed & 0xFFFFFFFF.
|
||||
|
||||
**Шаг 3: Запустить Steam, проверить**
|
||||
|
||||
**Критически важно:**
|
||||
- Редактировать ТОЛЬКО при остановленном Steam
|
||||
- Делать бэкап **до** изменений
|
||||
- `vdf.binary_loads` — регистрозависим: `AppName`, `Exe`, а не `appname`, `exe`
|
||||
|
||||
---
|
||||
|
||||
## VDF Troubleshooting
|
||||
|
||||
### shortcuts.vdf испорчен (все записи пустые)
|
||||
Steam перезаписывает VDF при старте если не понимает ручные правки. Восстанавливай из бэкапа.
|
||||
|
||||
**Бэкапы** (в `~/.steam/steam/userdata/147839491/config/`):
|
||||
| Файл | Дата | Entries | Примечание |
|
||||
|------|------|---------|------------|
|
||||
| `shortcuts.vdf.bak-eagle` | 23 мая 18:32 | 106 | **Последний чистый бэкап** — не тронут |
|
||||
| `shortcuts.vdf.bak-launch` | 22 мая 22:25 | 108 | Старый, без Atomic Heart |
|
||||
| `shortcuts.vdf.whale-restored-YYYY-MM-DD` | по ситуации | 108 | Текущее состояние после восстановления |
|
||||
| `/run/media/bazzite/Data/backups/saves/shortcuts/shortcuts.vdf.YYYY-MM-DD` | daily | — | Автоматический через saves-backup.service |
|
||||
|
||||
Проверка бэкапа:
|
||||
```python
|
||||
import vdf
|
||||
with open("shortcuts.vdf.bak-eagle", "rb") as f:
|
||||
d = vdf.binary_loads(f.read())
|
||||
named = sum(1 for e in d["shortcuts"].values() if e.get("AppName"))
|
||||
print(f"{named} named entries")
|
||||
```
|
||||
|
||||
### VDF Incident — 2026-05-27 (разбор)
|
||||
**Что произошло:** при попытке добавить VK GameCenter + Atomic Heart VK через Python vdf на работающем Steam, Steam переписал файл при старте, создав 110 пустых записей-заглушек.
|
||||
|
||||
**Почему бэкапы тоже пустые:** все бэкапы были сделаны уже после того как Steam испортил файл. Единственный выживший — `bak-eagle` (23 мая, до начала экспериментов).
|
||||
|
||||
**Как нашли:** hexdump показал имена игр, но `vdf.binary_loads` не видел их — проблема в регистре ключей (`AppName`, а не `appname`).
|
||||
|
||||
**Как восстановили:**
|
||||
1. Остановлен Steam
|
||||
2. Считан `bak-eagle` (106 записей) + добавлены VK GameCenter (index 106) и Atomic Heart VK (index 107)
|
||||
3. Обнаружено что config.vdf уже имеет CompatToolMapping с другими appid от предыдущих попыток
|
||||
4. Перегенерация с appid, совпадающими с config.vdf
|
||||
5. Удалены дублирующиеся unsigned записи из config.vdf
|
||||
6. Создан `shortcuts.vdf.whale-restored-2026-05-27`
|
||||
|
||||
**Уроки:**
|
||||
- Только при остановленном Steam
|
||||
- Бэкап ДО изменений
|
||||
- Проверять signed↔unsigned соответствие
|
||||
- Регистр ключей в vdf.binary_loads
|
||||
|
||||
---
|
||||
|
||||
## Key Infra Notes
|
||||
|
||||
- **shortcuts.vdf**: `~/.steam/steam/userdata/147839491/config/shortcuts.vdf` (binary VDF)
|
||||
- **config.vdf**: `~/.steam/steam/config/config.vdf` (text VDF, CompatToolMapping block)
|
||||
- **Wine prefix**: `~/.local/share/Steam/steamapps/compatdata/<AppID>/pfx/`
|
||||
- **protontricks**: Flatpak, needs `flatpak override --user --filesystem=/var/home/bazzite/.local/share/Steam`
|
||||
- **Background jobs**: `systemd-run --user --unit=<name>`
|
||||
- **GE-Proton**: extract tar.gz into `~/.steam/steam/compatibilitytools.d/`, restart Steam
|
||||
|
||||
### saves-backup.service
|
||||
Systemd user service (`/etc/systemd/user/saves-backup.service`):
|
||||
- Ежедневный rsync Steam userdata
|
||||
- Копия shortcuts.vdf в `/run/media/bazzite/Data/backups/saves/shortcuts/shortcuts.vdf.YYYY-MM-DD`
|
||||
- Ротация: удаление старше 30 дней
|
||||
|
||||
---
|
||||
|
||||
## Fixes Done (filesystem / config / cover-art)
|
||||
- Cover art swapped: Atomic Bomberman, Discworld Noir, SBR2, FFVI, ALttP, Sunset Riders
|
||||
- "Captain Commando" → "Sunset Riders"
|
||||
- CompatToolMapping for all AppIDs:
|
||||
- **GE-Proton10-34**: Brawlhalla, Castle Crashers, Worms WMD/WP, Duck Game, Rayman Origins, VK GameCenter, Atomic Heart VK, insaneramzes Atomic Heart
|
||||
- **Proton 8.0**: Atomic Bomberman, Discworld Noir, Metal Slug X, Soldat, Red Alert 3, Split Second
|
||||
- **Luxtorpeda**: Doom 3 BFG
|
||||
- **Proton Experimental**: ~24 remaining games
|
||||
- Doom 3 BFG → Luxtorpeda (rbdoom-3-bfg, 2026-05-27)
|
||||
- Rayman Legends: Ubisoft Connect + registry fix
|
||||
- Discworld Noir: symlink, Cyrillic locale, missing files, drive D: as CD-ROM
|
||||
- FFX HD: English `GameSetting.ini`
|
||||
- VC++ runtime + d3dcompiler DLLs copied into 6 prefixes from Windows partition
|
||||
- Duck Game: XNA 4.0 framework dir copied
|
||||
- Atomic Bomberman: `Version=win98` + virtual desktop 640×480 + WineBus controllers off
|
||||
- GE-Proton10-34 installed
|
||||
|
||||
## Source Assets (Windows partition)
|
||||
- Ubisoft Game Launcher: `/run/media/bazzite/Windows/Program Files (x86)/Ubisoft/`
|
||||
- System DLLs: `/run/media/bazzite/Windows/Windows/System32/`, `SysWOW64/`
|
||||
- XNA 4.0: `/run/media/bazzite/Windows/Program Files (x86)/Microsoft XNA/`
|
||||
- .NET 4.0: `/run/media/bazzite/Windows/Microsoft.NET/Framework64/v4.0.30319/`
|
||||
- Discworld Noir source: `/run/media/bazzite/Data/downloads/zatmenie v2 [torrents.ru]/`
|
||||
- **Discworld Noir (скачан 2026-05-29):** `/run/media/bazzite/Data/downloads/Discworld Noir.isz` (ISZ, 1.1GB, Alcohol 120%)
|
||||
- **Discworld (оригинал, скопирован 2026-05-29):** `/run/media/bazzite/Data/downloads/DISCWORLD.iso` (ISO, 434MB) — с TrueNAS `/mnt/RED_2TB/backup/Downloads/Distr/games/DISCWORLD.iso`
|
||||
- FFX settings: `/run/media/bazzite/Windows/Users/mallexxx/documents/square enix/...`
|
||||
|
||||
## Open Questions
|
||||
1. Delete `pfx/` folders for still-broken GE-Proton games (Brawlhalla, Castle Crashers, Worms WMD/WP, Duck Game)
|
||||
2. Atomic Bomberman: 32-bit Wineprefix outside Proton
|
||||
3. Discworld Noir: try cd1 or mount `.nrg` images
|
||||
4. Metro Exodus: Goldberg Steam emulator?
|
||||
5. **Atomic Heart VK:** test VK Play авторизацию, при необходимости `protontricks vcrun2019`
|
||||
6. **Doom 3 BFG:** test с Luxtorpeda → rbdoom-3-bfg
|
||||
|
||||
## See Also
|
||||
[[personal-os-architecture]] [[obsidian-mcp-wrapper]] [[family/how-to/htpc-steam-nonsteam-shortcuts]]
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
---
|
||||
title: HTPC Kodi Layout & WoL
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [htpc, kodi, wol, infra, how-to]
|
||||
related:
|
||||
- "[[tech/htpc-steam-emulators]]"
|
||||
---
|
||||
|
||||
# HTPC Kodi Layout & WoL
|
||||
|
||||
## Wake on LAN
|
||||
|
||||
HTPC MAC address stored in router DHCP config. WoL command:
|
||||
|
||||
```bash
|
||||
wakeonlan <HTPC-MAC>
|
||||
```
|
||||
|
||||
Or via Kodi remote / Home Assistant automation.
|
||||
|
||||
## Kodi Layout
|
||||
|
||||
- Home screen: custom skin (record actual skin name here)
|
||||
- Sources: NFS mounts from TrueNAS (`/mnt/RED_2TB/...`)
|
||||
- Add-ons: check Kodi installed add-ons list
|
||||
|
||||
Note: specific layout details were not migrated. Update this page
|
||||
when next doing HTPC maintenance.
|
||||
@@ -92,6 +92,78 @@ TV шлёт координаты в пространстве 0–1920 × 0–108
|
||||
- **Бинарь слетает** после `rpm-ostree upgrade` → пересобрать и скопировать.
|
||||
- **Display switching** — при смене между `:0` и `:1` xdotool перезапускается. Если переключение происходит часто (мигающие окна) — возможны краткие потери мыши.
|
||||
|
||||
## WebOS TV App — сборка и деплой
|
||||
|
||||
TV-часть — React/Enact WebOS приложение + Node.js сервис, упакованные в IPK. Исходники: `~/Developer/magic4pc/webos/`.
|
||||
|
||||
### Сборка
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc/webos
|
||||
NODE_OPTIONS=--openssl-legacy-provider npm run build
|
||||
```
|
||||
|
||||
**Питфолл:** `--openssl-legacy-provider` обязателен — старый webpack несовместим с Node.js 25+.
|
||||
|
||||
### Упаковка IPK
|
||||
|
||||
```bash
|
||||
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
|
||||
```
|
||||
|
||||
**Питфолл:** нужны оба аргумента `dist/` и `service/` — без `service/` Node.js сервис не попадает в IPK.
|
||||
**Питфолл:** `npm run package` = `ares-package -n` (unsigned) — TV отклоняет неподписанные пакеты. Использовать SDK-команду напрямую.
|
||||
|
||||
### Деплой (deploy.sh)
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc/webos && ./deploy.sh
|
||||
```
|
||||
|
||||
Скрипт: build → package → scp → close → remove → install → launch.
|
||||
Для install (subscribe mode) — прямой `ssh+script` с polling на `"state":"installed"`.
|
||||
|
||||
**Питфолл:** `ares-install` / `ares-launch` ненадёжны — не ждут завершения. Использовать `luna-send dev/install` через script-враппер.
|
||||
|
||||
Версия в UI отображается как `1.1.0 (YYYY-MM-DD HH:MM)` — инжектируется webpack через `process.env.BUILD_DATE`.
|
||||
|
||||
## Auto-launch при включении / пробуждении TV
|
||||
|
||||
Magic4pc запускает настроенное приложение при включении или пробуждении TV.
|
||||
|
||||
| Файл | Расположение | Назначение |
|
||||
|------|-------------|-----------|
|
||||
| `magic4pc-settings` | PERSISTENT_DIR | ID выбранного приложения |
|
||||
| `magic4pc-last-app` | PERSISTENT_DIR | Последнее активное приложение |
|
||||
| `magic4pc-run-state` | `/tmp/` | `running` после первого запуска |
|
||||
|
||||
`PERSISTENT_DIR = /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service`
|
||||
|
||||
Логика:
|
||||
- **Boot/wake:** `/tmp` очищается → нет `run-state` → `freshStart=true` → запускает настроенное приложение
|
||||
- **Ручной запуск:** `run-state=running` уже есть → auto-launch пропускается
|
||||
|
||||
`init.d` скрипт на TV (`/var/lib/webosbrew/init.d/magic4pc`) удаляет `run-state` при suspend — wake снова тригерит fresh launch. Редактировать только в репо (`tv-scripts/init.d-magic4pc.sh`), не напрямую на TV.
|
||||
|
||||
## WebOS Back Key + системная клавиатура
|
||||
|
||||
Когда системная клавиатура открыта, **первый Back** поглощается OS (закрывает клавиатуру) — `keydown` и `onButtonDown` **не стреляют**. Второй Back приходит нормально.
|
||||
|
||||
Фикс в `MainPanel.js` (флаг `_kbWasOpen`):
|
||||
|
||||
```js
|
||||
// Input.onActivate:
|
||||
this._kbWasOpen = true;
|
||||
|
||||
// onButtonDown на Back:
|
||||
if (this.state.wolMacActive || this._kbWasOpen) {
|
||||
this._kbWasOpen = false;
|
||||
return; // подавить закрытие панели
|
||||
}
|
||||
```
|
||||
|
||||
Подходы, которые не работают: `Popup.noAutoDismiss`, timeout-эвристика, polling `document.activeElement` (клавиатура — системный оверлей, фокус не переходит на INPUT).
|
||||
|
||||
## Деплой и sudoers
|
||||
|
||||
На HTPC настроен sudo без пароля для systemctl:
|
||||
|
||||
@@ -229,6 +229,20 @@ Imported 185 torrents from Windows Transmission-daemon into HTPC Transmission.
|
||||
|
||||
10 torrents had no data (X:\Movies\ — lost disk, permanently gone).
|
||||
|
||||
## Sudo / Пароль
|
||||
|
||||
Пароль пользователя `bazzite`: **`bazzite`**
|
||||
|
||||
Для удалённых команд через SSH:
|
||||
```bash
|
||||
ssh bazzite@192.168.1.86 'echo bazzite | sudo -S mount ...'
|
||||
```
|
||||
|
||||
Также настроен sudo без пароля для systemctl (см. [[htpc-magic4pc#Деплой и sudoers]]):
|
||||
```
|
||||
bazzite ALL=(ALL) NOPASSWD: /usr/bin/systemctl
|
||||
```
|
||||
|
||||
## OSTree / Обновления
|
||||
- `/usr/local/bin` слетает при `rpm-ostree` upgrade (новый `/usr` overlay)
|
||||
- Бинари держать в `/home/bazzite/` или пересобирать после обновлений
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: Jellyfin Config
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [jellyfin, infra, media, credentials]
|
||||
related:
|
||||
- "[[tech/arr-stack-kraken]]"
|
||||
---
|
||||
|
||||
# Jellyfin Config
|
||||
|
||||
**URL:** `http://kraken:8096`
|
||||
|
||||
## Users
|
||||
|
||||
| User | Password | Notes |
|
||||
|------|----------|-------|
|
||||
| alex | (set) | Admin |
|
||||
| lisa | (none) | Cartoons library only |
|
||||
|
||||
## API Key
|
||||
|
||||
`87af49b6ff62ea68da6abdab0d7a4fbc`
|
||||
|
||||
Used by automation scripts (watchlist-sync, media-pipeline agents).
|
||||
|
||||
## Database / Maintenance
|
||||
|
||||
- **Before any DB operation:** `docker stop jellyfin` first
|
||||
- Jellyfin runs as a Docker container on Kraken
|
||||
- Config stored in `/opt/jellyfin/config/` (check docker-compose for exact path)
|
||||
Executable
+108
@@ -0,0 +1,108 @@
|
||||
---
|
||||
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
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Kraken Network & Infra
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [infra, kraken, ssh, wireguard, network]
|
||||
related:
|
||||
- "[[tech/arr-stack-kraken]]"
|
||||
---
|
||||
|
||||
# Kraken Network & Infra
|
||||
|
||||
## SSH Access
|
||||
|
||||
```
|
||||
ssh kraken
|
||||
```
|
||||
|
||||
IP: `192.168.1.15` (wlan0, primary). SSH alias `kraken` resolves via `~/.ssh/config`.
|
||||
|
||||
## WireGuard Topology
|
||||
|
||||
Split-tunnel: Eagle ↔ VPS ↔ Kraken. Full details: [[tech/wireguard-vpn]].
|
||||
|
||||
- Eagle: `10.99.0.2`, Kraken: `10.99.1.2`, VPS relay: `10.99.0.1`/`10.99.1.1`
|
||||
- `wg-auto.sh` on Eagle (LaunchDaemon) — up when off home Wi-Fi, down at home
|
||||
- VPS as relay; two interfaces (wg0/wg1) avoid hairpin forwarding
|
||||
|
||||
## Media Volume Mount Paths
|
||||
|
||||
Docker containers on Kraken mount media from NAS over NFS/SMB.
|
||||
Paths were documented here — check docker-compose files in
|
||||
`/opt/media-toolbox-kraken` for current mount config.
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: TrueNAS Inpxer / Books Setup
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [truenas, books, infra, storage]
|
||||
related:
|
||||
- "[[tech/kraken-network]]"
|
||||
---
|
||||
|
||||
# TrueNAS Inpxer / Books Setup
|
||||
|
||||
## Books Storage Path
|
||||
|
||||
```
|
||||
/mnt/RED_2TB/storage/books/
|
||||
```
|
||||
|
||||
Books are stored on the RED_2TB pool. Inpxer (or similar indexer) serves
|
||||
the library from this location.
|
||||
|
||||
## Related TrueNAS Notes
|
||||
|
||||
- General TrueNAS access: [[family/how-to/truenas-access]]
|
||||
- Remote access reverse proxy: [[personal/docs/truenas-remote-access-reverse-proxy]]
|
||||
- Rclone backup: [[family/how-to/truenas-rclone-backup]]
|
||||
|
||||
Note: Inpxer-specific config was not migrated — add details here when
|
||||
revisiting this setup.
|
||||
@@ -40,6 +40,20 @@
|
||||
Переменная `TV_HOST` переопределяет таргет (default: `root@LGwebOSTV`, alias `root@tv`, IP: `root@192.168.1.75`).
|
||||
DNS резолвится через роутер (192.168.1.1), см. [[router-bishkek-asus]].
|
||||
|
||||
## Common Luna URIs
|
||||
|
||||
| URI | Назначение |
|
||||
|-----|-----------|
|
||||
| `.../applicationmanager/running` | Список запущенных приложений |
|
||||
| `.../applicationmanager/closeByAppId` | Закрыть приложение по ID |
|
||||
| `.../appInstallService/dev/install` | Установить IPK (subscribe) |
|
||||
| `.../appInstallService/dev/remove` | Удалить приложение |
|
||||
| `.../applicationManager/launch` | Запустить приложение |
|
||||
| `.../applicationManager/getForegroundAppInfo` | Текущее активное приложение |
|
||||
| `...magic4pc.service/query` | Статус сервиса magic4pc |
|
||||
|
||||
Полные префиксы: `com.webos.service.applicationmanager`, `com.webos.appInstallService`, `com.webos.applicationManager`.
|
||||
|
||||
## Ограничение
|
||||
|
||||
`luna-send -i` (subscribe, бесконечный) не работает через враппер. Для install (`dev/install`) используется прямой ssh+script с polling в deploy.sh.
|
||||
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Vault Git Sync — Setup & Pitfalls
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: wiki
|
||||
tags: [vault, git, sync, infra, obsidian]
|
||||
---
|
||||
|
||||
# Vault Git Sync
|
||||
|
||||
Obsidian vault is a bare git repo on TrueNAS (`mallexxx.duckdns.org:/mnt/RED_2TB/storage/git/obsidian-vault.git`).
|
||||
Three hosts sync to it: Eagle, Kraken, Taiga.
|
||||
|
||||
## Sync Strategy (correct)
|
||||
|
||||
All hosts must follow this order:
|
||||
|
||||
```
|
||||
1. stash local changes (git stash)
|
||||
2. pull from remote (git fetch + git merge)
|
||||
3. pop stash (git stash pop)
|
||||
4. commit if anything new (git add -A + git commit)
|
||||
5. push (git push)
|
||||
```
|
||||
|
||||
**Why this order matters:** `git add -A` before pull stages deletions of files
|
||||
that exist on remote but not locally. This caused Taiga to delete 32+ wiki files
|
||||
on 2026-05-23 (two incidents: 3a44a55, c9020c4).
|
||||
|
||||
## Scripts
|
||||
|
||||
| Host | Script | Status |
|
||||
|--------|------------------------------------|----------------|
|
||||
| Eagle | `~/scripts/sync-vault.sh` | ✅ Correct |
|
||||
| Kraken | `~/scripts/sync-vault-partial.sh` | ✅ Correct |
|
||||
| Taiga | `/opt/data/sync-vault.sh` | ✅ Fixed 2026-05-23 |
|
||||
|
||||
All scripts now use scoped `git add personal/ family/ .obsidian/` (not `git add -A`) before stash.
|
||||
Taiga additionally uses sparse checkout (only `personal/` and `family/`) — double safeguard:
|
||||
even if a bug reintroduces `git add -A`, sparse checkout means wiki/ is never checked out locally.
|
||||
|
||||
## Taiga Architecture
|
||||
|
||||
Taiga is TrueNAS running Hermes in Docker (`/mnt/RED_2TB/docker/hermes/`).
|
||||
The sync script runs **inside the container** with:
|
||||
- `GIT_WORK_TREE=/vault` → mounted from `/mnt/RED_2TB/storage/obsidian`
|
||||
- `GIT_DIR=/vault.git` → mounted from `/mnt/RED_2TB/storage/git/obsidian-vault.git` (the bare repo itself)
|
||||
|
||||
Taiga IS the repo — no remote push needed. Eagle pushes to `nas/main`, which is this same bare repo.
|
||||
|
||||
Script location: `/mnt/RED_2TB/docker/hermes/config/sync-vault.sh` (= `/opt/data/sync-vault.sh` inside container)
|
||||
|
||||
SSH access: `ssh taiga` (alias in ~/.ssh/config → `truenas_admin@mallexxx.duckdns.org`)
|
||||
|
||||
To deploy a script fix:
|
||||
```bash
|
||||
scp ~/scripts/sync-vault-taiga.sh taiga:/mnt/RED_2TB/docker/hermes/config/sync-vault.sh
|
||||
```
|
||||
|
||||
**NEVER use local IP for TrueNAS** — always `mallexxx.duckdns.org` or `ssh taiga`.
|
||||
|
||||
## .gitignore
|
||||
|
||||
Plugin binaries are excluded to prevent cross-device obsidian-git version conflicts:
|
||||
|
||||
```
|
||||
.obsidian/plugins/obsidian-git/main.js
|
||||
.obsidian/plugins/obsidian-git/styles.css
|
||||
.obsidian/plugins/obsidian-git/manifest.json
|
||||
```
|
||||
|
||||
Each device manages its own plugin binaries via Obsidian's built-in update mechanism.
|
||||
`data.json` (plugin config) IS tracked — shared settings across devices.
|
||||
|
||||
## Incident: 2026-05-23
|
||||
|
||||
**Root cause:** Taiga's `/opt/data/sync-vault.sh` did `git add -A` before `git pull`.
|
||||
|
||||
**Sequence:**
|
||||
- 22:02 UTC Eagle created 15 wiki files (d757029, 6dc4b89)
|
||||
- 00:00 UTC Taiga ran sync → staged deletions (local didn't have wiki/) → commit 3a44a55
|
||||
- 03:02 UTC Taiga ran again → deleted 8 more files (c9020c4)
|
||||
|
||||
**Recovery:** `git checkout <hash> -- <file>` for each file from last-good commits.
|
||||
32 files restored in commit 620e2df.
|
||||
|
||||
## Stash Cleanup
|
||||
|
||||
Orphaned stashes from obsidian-git mobile syncs accumulate. Safe to drop:
|
||||
```bash
|
||||
git stash drop stash@{N} # drop specific, or:
|
||||
git stash clear # drop all (only if no unrecovered work)
|
||||
```
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: VPS qentra.top
|
||||
created: '2026-05-24'
|
||||
updated: '2026-05-27'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [infra, vps]
|
||||
confidence: medium
|
||||
related:
|
||||
- "[[tech/kraken-network]]"
|
||||
- "[[tech/wireguard-vpn]]"
|
||||
---
|
||||
|
||||
# VPS qentra.top
|
||||
|
||||
**IP:** 91.207.28.205
|
||||
**Stack:** nginx + Python 3.11, Cloudflare proxy
|
||||
**Panels:** panel.qentra.top:5430, v.qentra.top:8964
|
||||
|
||||
## Subdomain Setup
|
||||
|
||||
1. Add Cloudflare A-record → 91.207.28.205
|
||||
2. Add nginx vhost in `/etc/nginx/sites-enabled/`
|
||||
|
||||
## Backup
|
||||
|
||||
Ежедневный бэкап конфигов через cron (04:00):
|
||||
- Скрипт: `/root/vps-backup.sh`
|
||||
- Cron: `/etc/cron.d/vps-backup`
|
||||
- Куда: `/root/backups/` (`vps-config-YYYY-MM-DD_HHMMSS.tar.gz`)
|
||||
- Ретеншн: 90 дней
|
||||
|
||||
**Что бэкапится:**
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `xray/config.json` | Xray конфиг (все inbound/outbound, клиенты) |
|
||||
| `x-ui/config.json` | 3X-UI панель (полная копия клиентов) |
|
||||
| `systemd/xray.service` | systemd unit Xray |
|
||||
| `cron/xray-update` | Еженедельное обновление Xray и 3X-UI |
|
||||
| `nginx/sites-enabled/nolvu` | nginx vhost → nolvu.qentra.top |
|
||||
| `nginx/sites-available/panel` | nginx vhost → panel.qentra.top |
|
||||
| `nginx/sites-available/xray` | nginx vhost → v.qentra.top (WS прокси) |
|
||||
| `nginx/nginx.conf` | Основной конфиг nginx |
|
||||
| `scripts/add-client.sh` | OpenVPN скрипты |
|
||||
| `scripts/revoke-client.sh` | OpenVPN скрипты |
|
||||
| `scripts/setup-openvpn.sh` | OpenVPN скрипты |
|
||||
|
||||
**Восстановление:**
|
||||
```bash
|
||||
tar xzf /root/backups/vps-config-latest.tar.gz -C /
|
||||
# После восстановления — перезапустить сервисы:
|
||||
systemctl daemon-reload
|
||||
systemctl restart xray nginx
|
||||
```
|
||||
|
||||
## Xray (VLESS+REALITY)
|
||||
|
||||
- **Inbound 443** — REALITY, 4 клиента
|
||||
- `2D9F24C4-21FE-4784-9843-F11C384DA67A` — `user1` (телефон)
|
||||
- `f80b579b-baa6-4887-a76e-682635335c15` — `natali`
|
||||
- `62814419-722a-4f45-b560-eaed2d0df6af` — `alexander_martemyanov`
|
||||
- `23aa4d8e-ef16-43ab-bdef-3d2c11d8ef02` — `taiga` (TrueNAS vless-proxy)
|
||||
- **Inbound 8964** — WebSocket, через nginx v.qentra.top/qentra
|
||||
- `2D9F24C4-21FE-4784-9843-F11C384DA67A` — `124hyews`
|
||||
- `d10834e6-ba84-4dbd-b5e6-b5f4df9e64d6` — `natali@duck.com`
|
||||
- PrivateKey: `CMu-Sz49V5HW-s2c0P33EDlCwY-JMhQbxfdn7LhvY1A`
|
||||
- Публичный ключ (для клиентов): `Rtkptj9Cij2go_oE0Klgf_Mwfhq-d_oaW4mQubHzXm0`
|
||||
|
||||
**Важно:** REALITY на 443, nginx на 8443 + 80. При перезапуске — сначала Xray (забирает 443), потом nginx.
|
||||
|
||||
## See Also
|
||||
|
||||
- [[tech/kraken-network]] — Kraken home network topology
|
||||
- [[tech/wireguard-vpn]] — WireGuard tunnel used for Eagle↔VPS traffic
|
||||
@@ -94,3 +94,8 @@ ssh kraken "sudo wg show"
|
||||
# Логи auto-connect Eagle
|
||||
cat /var/log/wg-auto.log
|
||||
```
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[kraken-network]] — SSH к Кракену, пути медиаволюмов
|
||||
- [[personal-os-architecture]] — Eagle hardware, домашняя инфра
|
||||
|
||||
Executable
+150
@@ -0,0 +1,150 @@
|
||||
---
|
||||
created: '2026-05-20'
|
||||
updated: '2026-05-27'
|
||||
status: active
|
||||
tags:
|
||||
- kraken
|
||||
- watchlist
|
||||
- automation
|
||||
- movies
|
||||
---
|
||||
# Watchlist Automation — Полный Flow
|
||||
|
||||
Полная цепочка: как `family/documents/movies-watchlist.md` превращается в скачанный контент.
|
||||
|
||||
## Полная цепочка
|
||||
|
||||
```
|
||||
[вс 09:00] watchlist-discover ← KP API топ фильмов 2024-2025
|
||||
↓ добавляет в секцию "Новинки 👍/👎"
|
||||
movies-watchlist.md
|
||||
Alex ставит 👍 / 👎
|
||||
↓
|
||||
[ежедн 09:00] watchlist-resolve ← SSH Кракен → resolve → commit
|
||||
[ежедн 10:00] watchlist-sync-down
|
||||
→ process-thumbs (перемещает 👍 → начало списка)
|
||||
→ sync-down (добавляет батч в Radarr/Sonarr)
|
||||
↓
|
||||
Radarr (7878) / Sonarr (8989)
|
||||
→ Prowlarr (9696) → RuTracker / Kinozal(M) / NoNaMe / etc.
|
||||
→ Transmission (9091)
|
||||
→ /media/movies-radarr или /media/series-sonarr
|
||||
↓
|
||||
router.py (Custom Script) → читает жанры из NFO/TMDb
|
||||
→ symlink в /media/{movies,cartoons,documentaries,...}/
|
||||
↓
|
||||
Jellyfin (8096) → rescan → виден контент
|
||||
```
|
||||
|
||||
## Статусы в movies-watchlist.md
|
||||
|
||||
| Символ | Значение | Действие |
|
||||
|--------|---------|---------|
|
||||
| `[ ]` | не смотрел, в очереди | sync-down добавляет в Radarr/Sonarr |
|
||||
| `[x]` | просмотрено | sync-up из Jellyfin watched history |
|
||||
| `⬇️` | добавлено в Radarr/Sonarr | ждёт скачки |
|
||||
| `👍` | нравится (новинка) | process-thumbs переносит в начало → попадёт в sync-down |
|
||||
| `👎` | не хочу (новинка) | process-thumbs перемещает в `## Новинки👎` |
|
||||
| `🗓️` | upcoming (ещё не вышел) | discover помечает, не скачивается |
|
||||
| `❓` | не найдено / ambiguous | ждёт ручного уточнения |
|
||||
| `🧟♀️` | horror (genre_id=27) | информационный маркер |
|
||||
|
||||
## Структура секций movies-watchlist.md
|
||||
|
||||
```
|
||||
## Новинки - 👍/👎 ← discover добавляет сюда
|
||||
## Фильмы ← основной список, отступ 2 пробела ( - [ ])
|
||||
## Мультфильмы
|
||||
## Аниме
|
||||
## Новинки👎 ← без пробела перед 👎
|
||||
## Связанные заметки
|
||||
```
|
||||
|
||||
**Важно:** `process_thumbs` автоматически определяет отступ из `## Фильмы` и сохраняет при переносе. `SECTION_THUMBDN = "## Новинки👎"` (без пробела) — должно точно совпадать с заголовком.
|
||||
|
||||
## 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.sh** (на Кракене):
|
||||
1. `sync-vault.sh` (pull) → `process-thumbs --apply` → `sync-vault.sh` (push)
|
||||
2. `resolve --recheck --apply` → `sync-down --apply --batch 5` → `sync-up --apply` → `sync-vault.sh` (push)
|
||||
|
||||
**Пути на Кракене (HDD UUID 49e8f586-3839-4c5d-a1e1-58bfc3579ade):**
|
||||
- `/home/kraken/obsidian` → symlink на `/srv/dev-disk-by-uuid-.../obsidian`
|
||||
- watchlist-sync: `/srv/dev-disk-by-uuid-.../Developer/watchlist-sync`
|
||||
|
||||
## Discover — Фильтрация
|
||||
|
||||
| Тип | Порог |
|
||||
|-----|-------|
|
||||
| Мировые | IMDb ≥ 7.0 или KP ≥ 7.0 |
|
||||
| Российские | KP ≥ 8.5 (защита от накрутки) |
|
||||
| Upcoming | год ≥ текущий−1 |
|
||||
| Минимум голосов | IMDb ≥ 1000 или KP ≥ 500 |
|
||||
|
||||
KP API endpoint: `https://api.poiskkino.dev/v1.4/movie` (redirect с api.kinopoisk.dev).
|
||||
|
||||
## *arr Stack — Индексеры (Prowlarr)
|
||||
|
||||
| ID | Имя | Тип | Примечание |
|
||||
|----|-----|-----|-----------|
|
||||
| 1 | RuTracker | semi-private | блокирует при rate limit на сутки |
|
||||
| 2 | RuTor | public | поиск по imdbid |
|
||||
| 3 | Byrutor | public | |
|
||||
| 4 | NoNaMe Club | semi-private | анонимный |
|
||||
| 5 | Kinozal | semi-private | резерв |
|
||||
| 6 | Kinozal (M) | semi-private | магнет ✅ — без grab limit, **предпочтительный** |
|
||||
|
||||
**Pi-hole питфолл:** блокирует `skyhook.sonarr.tv` → Sonarr/Radarr поиск молча не запускается. Фикс: `dns: [8.8.8.8]` в docker-compose.yml.
|
||||
|
||||
## Router Script — Маршрутизация по жанру
|
||||
|
||||
После импорта Sonarr/Radarr: `router.py --apply` создаёт symlinks:
|
||||
- Animation (не R/18+) → `/media/cartoons/` или `/media/cartoons-series/`
|
||||
- Documentary → `/media/documentaries/` или `/media/documentaries-series/`
|
||||
- Прочее → `/media/movies/` или `/media/series/`
|
||||
|
||||
Копирует NFO + постер рядом с symlink (Jellyfin не видит метадату через symlink напрямую).
|
||||
|
||||
## watchlist-sync — Python CLI
|
||||
|
||||
Репо: `~/Developer/watchlist-sync` (GitHub: `mallexxx/watchlist-sync`).
|
||||
|
||||
```
|
||||
watchlist-sync resolve — TMDB + KP API → ID, тип (movie/tv)
|
||||
watchlist-sync sync-down — добавить батч (max 5) в Radarr/Sonarr, поставить ⬇️
|
||||
watchlist-sync sync-up — Jellyfin watched → [x] в .md
|
||||
```
|
||||
|
||||
**Резолвер:** TMDB `/search/multi` + KP fallback. Пороги: `min_rating: 6.0`, `min_score: 0.75`. При 2+ кандидатах → `❓` (LLM разрешает в cron каждые 6ч, нерешённые → уточнение в Zulip).
|
||||
|
||||
**Stage 2 (после ≥50 просмотров):** AI-curated recommendations — три списка (с женой / один / семья) на основе TMDB профиля, добавляются в конец watchlist как `## 🤖 Рекомендации (YYYY-WNN)`.
|
||||
|
||||
Jellyfin library mapping: Movies → `movies`, Cartoons → `mixed` (movies + episodes).
|
||||
|
||||
## Питфоллы
|
||||
|
||||
### KP Markdown Link Parsing Bug
|
||||
Фильмы из Kinopoisk с синтаксисом `[Title](https://kinopoisk.ru/film/12345/) (2025)` передавались как есть в TMDB search → не находились → помечались `❓` навсегда (`not i.ambiguous` пропускает при следующем запуске). Фикс: commit `2db1ed9` — извлекать plain title из markdown link до передачи в TMDB. Ошибочно помеченные `❓` требуют ручного `--recheck`.
|
||||
|
||||
### KP API Endpoint
|
||||
`api.kinopoisk.dev` редиректит на `api.poiskkino.dev/v1.4/movie`. Использовать destination redirect напрямую.
|
||||
|
||||
## Open Tasks (2026-05-20)
|
||||
|
||||
- 🟡 Передавать Transmission locations через router script при каждом импорте (сейчас вручную)
|
||||
- 🔴 rsync невыполненных фильмов с HTPC на Кракен (`Фильмы не перенесенные с htpc на кракен.md`)
|
||||
- 🟡 Watchlist sync-up: добавить перенесённые фильмы в нужные разделы
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[watchlist-discover]] — шаг discover: KP API, format, CLI команды
|
||||
- [[watchlist-sync]] — основной проект (resolve, sync-down, sync-up)
|
||||
- [[arr-stack-kraken]] — детальные питфоллы *arr стека
|
||||
- [[jellyfin-transcode-rpi5]] — Jellyfin PGS/ASS питфоллы
|
||||
@@ -76,12 +76,12 @@ watchlist-sync process-thumbs --apply
|
||||
|
||||
---
|
||||
|
||||
## Cron jobs (Hermes)
|
||||
## Cron jobs (Hermes, на Кракене с 2026-05-27)
|
||||
|
||||
| Job | Schedule | Действие |
|
||||
|-----|----------|----------|
|
||||
| `watchlist-discover` (`6aba6979b8c4`) | вс 09:00 | discover --apply + git commit |
|
||||
| `watchlist-sync-down` (`7d12b6d48786`) | ежедн. 10:00 | process-thumbs --apply → sync-down --apply |
|
||||
| `watchlist-discover` | вс 09:00 | discover --apply + git commit (Кракен) |
|
||||
| `watchlist-nightly` | ежедн. 01:00 | process-thumbs → resolve → sync-down → sync-up (Кракен) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user