[2026-05-29] wiki/ cleanup: move files to vault, drop stale duplicates
- wiki/tech/ → family/how-to/ (15 files, no duplicates existed)
- wiki/{concepts,comparisons,root}/ → personal/projects/personal-os/ (22 files)
- wiki/tech/media-pipeline-pitfalls.md → personal/projects/
- wiki/tech/reflect-skip-fuse.md → personal/projects/
- wiki/ddg-asana-workflow.md → work/
- wiki/user-profile.md → personal/
- Dropped 11 files: vault versions are newer/bigger (xgimi, htpc-steam,
vault-strategy, executor-orchestrator, executor-security-incident,
kraken-media-stack, library-app, psychologist-app, raw/processed/, log, index)
4 files pending review (wiki version larger than vault original):
htpc-magic4pc, tv-luna-send, wireguard-vpn, watchlist-automation
This commit is contained in:
@@ -1,136 +0,0 @@
|
||||
---
|
||||
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]]
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
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.)
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
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
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
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
|
||||
@@ -1,229 +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]] — сетевая топология
|
||||
- [[concepts/hermes-deployment-patterns]] — сравнение трёх моделей деплоя Hermes
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
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
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
title: HTPC Steam & Emulators
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-29'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [htpc, steam, emulators, gamepad, how-to, pitfalls]
|
||||
sources:
|
||||
- family/how-to/htpc-migration-plan.md
|
||||
related:
|
||||
- "[[htpc-kodi-layout]]"
|
||||
- "[[htpc-bazzite-proton]]"
|
||||
- "[[tech/htpc-magic4pc]]"
|
||||
---
|
||||
|
||||
# HTPC Steam & Emulators
|
||||
|
||||
Bazzite HTPC at `192.168.1.86`. See [[htpc-bazzite-proton]] for Proton
|
||||
game compatibility details.
|
||||
|
||||
## Hardware
|
||||
|
||||
- CPU: Intel Core i7-6800K, RAM: 32 GB, GPU: AMD Radeon RX 570
|
||||
- TV: LG webOS at `192.168.1.75` (HDMI)
|
||||
- OS: Bazzite 44 (Fedora-based, immutable OSTree, `bazzite-deck` variant)
|
||||
|
||||
## Gamepads — 8BitDo Ultimate (2 dongles)
|
||||
|
||||
**Critical:** both 8BitDo Ultimate dongles (`2dc8:3106`) must be on
|
||||
**separate physical USB ports**, not sharing a USB hub. If both share
|
||||
the Huasheng USB2.0 HUB on port 006, the second dongle fails to
|
||||
enumerate (`#Ifs=0 Cfg#=0`) and creates no `/dev/input/js`.
|
||||
|
||||
**Working USB layout:**
|
||||
- Port 005 (direct xHCI, no hub) → 8BitDo #1 (`E417D8D87F0C`)
|
||||
- Port 006 → Hub Port 001 → 8BitDo #2 (`E417D8C197E4`)
|
||||
- Port 006 → Hub Port 004 → Xbox 360 Wireless Receiver
|
||||
|
||||
**Symptoms of wrong layout:** lsusb shows both but second has `#Ifs=0`;
|
||||
only one `/dev/input/js`; Steam sees one controller.
|
||||
|
||||
## Rules
|
||||
|
||||
- Game save paths: managed per-emulator; see emulator config in Bazzite
|
||||
- Gamepad config: stored in Steam controller profiles, backed up to
|
||||
`~/controller-profiles/`
|
||||
- Steam shortcuts for non-Steam Windows games: use Proton Experimental
|
||||
|
||||
## EmuDeck Save Paths (Flatpak)
|
||||
|
||||
| Emulator | Save path |
|
||||
|----------|-----------|
|
||||
| RetroArch | `~/.var/app/org.libretro.RetroArch/config/retroarch/saves/` |
|
||||
| Dolphin (GC/Wii) | `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/` |
|
||||
| Citra / Lime3DS | `~/.var/app/org.citra_emu.citra/` |
|
||||
| PCSX2 (PS2) | `~/.var/app/net.pcsx2.PCSX2/config/PCSX2/memcards/` |
|
||||
| RPCS3 (PS3) | `~/.var/app/net.rpcs3.RPCS3/config/rpcs3/dev_hdd0/` |
|
||||
| PPSSPP (PSP) | `~/.var/app/org.ppsspp.PPSSPP/config/ppsspp/PSP/SAVEDATA/` |
|
||||
| melonDS (NDS) | `~/.var/app/net.kuribo64.melonDS/` |
|
||||
| Ryujinx (Switch) | `~/.var/app/org.ryujinx.Ryujinx/config/Ryujinx/bis/user/save/` |
|
||||
| Steam | `~/.steam/steam/userdata/` |
|
||||
|
||||
## ROM Symlinks (Data partition → EmuDeck)
|
||||
|
||||
Emulators expect ROMs at `~/Emulation/roms/<system>/`. Symlinks from
|
||||
the Data partition (`/run/media/bazzite/Data/`):
|
||||
|
||||
```bash
|
||||
ln -s "/run/media/bazzite/Data/n64 roms" ~/Emulation/roms/n64
|
||||
ln -s "/run/media/bazzite/Data/snes roms" ~/Emulation/roms/snes
|
||||
ln -s "/run/media/bazzite/Data/gba roms" ~/Emulation/roms/gba
|
||||
ln -s "/run/media/bazzite/Data/3ds roms" ~/Emulation/roms/3ds
|
||||
ln -s "/run/media/bazzite/Data/ps2 roms" ~/Emulation/roms/ps2
|
||||
ln -s "/run/media/bazzite/Data/dolphin roms" ~/Emulation/roms/wii
|
||||
ln -s "/run/media/bazzite/Data/cemu roms" ~/Emulation/roms/wiiu
|
||||
ln -s "/run/media/bazzite/Data/mame roms" ~/Emulation/roms/mame
|
||||
ln -s "/run/media/bazzite/Data/sega roms" ~/Emulation/roms/genesis
|
||||
ln -s "/run/media/bazzite/Data/nes" ~/Emulation/roms/nes
|
||||
```
|
||||
|
||||
After symlinking, run **Steam ROM Manager** (EmuDeck) from Desktop Mode
|
||||
to import ROMs into Steam with cover art.
|
||||
|
||||
## Non-Steam Windows Games
|
||||
|
||||
`/run/media/bazzite/Data/games/` — 38 pre-installed games (Bayonetta,
|
||||
Cuphead, GTA V, Witcher 3, etc.). Add as Non-Steam games with
|
||||
Proton Experimental.
|
||||
|
||||
`/run/media/bazzite/Data/steam/steamapps/common/` — already-Steam games
|
||||
(Gang Beasts, Shovel Knight, etc.). Add as a second Steam library path.
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
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)
|
||||
@@ -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,34 +0,0 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
title: Media Pipeline Pitfalls
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-27'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [media-pipeline, pitfalls, torrents, infra]
|
||||
related:
|
||||
- "[[tech/arr-stack-kraken]]"
|
||||
- "[[concepts/watchlist-automation]]"
|
||||
---
|
||||
|
||||
# Media Pipeline Pitfalls
|
||||
|
||||
## Torrents — Do Not Rename Files
|
||||
|
||||
Never rename torrent source files or folders while a torrent is active.
|
||||
Transmission tracks files by path. Renaming breaks the association and
|
||||
causes re-download or stalled seeding.
|
||||
|
||||
Правильный порядок (когда файл уже лежит в нужном месте, но с другим кейсом):
|
||||
1. Переименовать файл/папку на диске (Linux ext4 case-sensitive)
|
||||
2. Вызвать `torrent-set-location` с новым путём + `move=false`
|
||||
3. Запустить торрент на сидирование
|
||||
|
||||
## torrent-set-location Updates downloadDir
|
||||
|
||||
`torrent-set-location` in the Transmission RPC updates `downloadDir` in
|
||||
the torrent metadata. Use this when moving completed files, not a manual
|
||||
rename. Sequence:
|
||||
|
||||
1. Move files to new location on disk
|
||||
2. Call `torrent-set-location` with the new path + `move=false`
|
||||
3. Verify torrent goes back to seeding state
|
||||
|
||||
## Router Creates Subdirectories — Transmission downloadDir Stale
|
||||
|
||||
`router.py` creates subdirectory per title under the genre folder
|
||||
(lowercase name, e.g. `/media/cartoons/бобик в гостях у барбоса/`).
|
||||
Transmission still holds the old `downloadDir` pointing to the parent
|
||||
(`/media/cartoons/`). Result: torrents show "No data found" error.
|
||||
|
||||
Fix:
|
||||
1. Find the actual subdirectory on disk
|
||||
2. Call `torrent-set-location` with the subdirectory path + `move=false`
|
||||
3. Transmission verifies and resumes seeding
|
||||
|
||||
## Alpine Container — No Docker-in-Docker
|
||||
|
||||
`on-download-complete.sh` runs inside the Transmission Alpine container.
|
||||
Docker CLI is not available there — using `docker run` inside the container
|
||||
fails silently or errors. Python 3.14 IS available in the Alpine image.
|
||||
|
||||
Solution: `sync.py` (Python3, ~190 lines) in the same container:
|
||||
- Reads `config.json` for sorting rules + credentials (same file as linker container)
|
||||
- Queries TMDB for genre routing
|
||||
- Creates hardlinks + calls Transmission RPC `torrent-set-location`
|
||||
Location: `/srv/.../docker/media-pipeline/sync.py`
|
||||
|
||||
## Transmission download-dir — без /complete
|
||||
|
||||
download-dir: `/downloads` (не `/downloads/complete`).
|
||||
incomplete-dir: `/downloads/incomplete` (enabled).
|
||||
|
||||
Менять через остановку Transmission → правка `settings.json` → запуск.
|
||||
|
||||
## media-router.sh — Telegram-уведомления
|
||||
|
||||
Скрипт-обёртка над `router.py`. Запускается из crontab каждые 10 минут.
|
||||
- При `Nothing to do` — SILENT
|
||||
- При активности — отправляет отчёт в Telegram Kraken (kraken_htpc_bot)
|
||||
- `BOT_TOKEN` и `CHAT_ID` хардкодом в скрипте
|
||||
|
||||
## Удаление дубликатов из downloads/complete
|
||||
|
||||
После перемещения файлов в `/media/{movies,cartoons,series,...}/`:
|
||||
1. Проверить, что файлы в movies — **реальные** (-rwx), не symlink'и
|
||||
2. Проверить что inode разные (это копии, не один файл)
|
||||
3. Удалить из `downloads/complete/`
|
||||
4. Обновить путь в Transmission
|
||||
|
||||
## General Rules
|
||||
|
||||
- Never touch source files/folders (media-pipeline USER.md rule)
|
||||
- `resolve-manual` is emergency-only
|
||||
- NFO files: do not create manually; let the pipeline handle them
|
||||
- Never delete test files from the pipeline project
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
title: Reflect — Skip Fuse (SwiftUI/Kotlin)
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [reflect, swift, kotlin, ios, android, pitfalls]
|
||||
related:
|
||||
- "[[entities/psychologist-app]]"
|
||||
- "[[tech/gitea-config]]"
|
||||
---
|
||||
|
||||
# Reflect — Skip Fuse (SwiftUI/Kotlin)
|
||||
|
||||
## Key Pitfall
|
||||
|
||||
When adding a **new SwiftUI View** to the Reflect iOS codebase, Skip Fuse
|
||||
does **not** auto-generate the Kotlin counterpart. A manual Kotlin stub is
|
||||
required in **2 places**:
|
||||
|
||||
1. The View class file in the Android module
|
||||
2. The registration/factory in the Android navigation/router
|
||||
|
||||
## Why
|
||||
|
||||
Skip Fuse transpiles shared SwiftUI code to Kotlin, but new View types
|
||||
require explicit Kotlin stubs until Skip's transpilation coverage catches up.
|
||||
|
||||
## Checklist for New SwiftUI Views
|
||||
|
||||
- [ ] Add SwiftUI view as normal in iOS target
|
||||
- [ ] Create matching Kotlin stub in `android/src/.../views/`
|
||||
- [ ] Register in Android router/factory
|
||||
- [ ] Run `./gradlew build` to verify no missing class errors
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
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)
|
||||
```
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
title: Vault Namespace Rules
|
||||
created: '2026-05-23'
|
||||
updated: '2026-05-23'
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [vault, meta, conventions]
|
||||
related:
|
||||
- "[[vault-filling-guide]]"
|
||||
---
|
||||
|
||||
# Vault Namespace Rules
|
||||
|
||||
Rules for where notes live in the Obsidian vault. See also [[SCHEMA]] for
|
||||
full frontmatter conventions.
|
||||
|
||||
## Namespace Assignments
|
||||
|
||||
- `personal`: Eagle infra, personal projects, dev tooling
|
||||
- `family`: Kraken media stack, HTPC, Jellyfin, family content
|
||||
- `work`: DuckDuckGo / DDG tasks and tooling
|
||||
|
||||
## Directory Map
|
||||
|
||||
```
|
||||
wiki/concepts/ — how-it-works explanations
|
||||
wiki/tech/ — infra how-tos, tool configs, pitfalls
|
||||
wiki/ideas/ — speculative, not yet decided
|
||||
personal/projects/ — project status & decisions
|
||||
family/projects/ — family-shared project status
|
||||
family/how-to/ — family infra procedures
|
||||
```
|
||||
|
||||
Note: this file was reconstructed from a lost pointer. Extend with actual
|
||||
rules as they emerge.
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
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
|
||||
@@ -1,121 +0,0 @@
|
||||
---
|
||||
title: XGIMI Play 6 — Setup Guide
|
||||
created: '2026-05-25'
|
||||
updated: '2026-05-25'
|
||||
type: tech
|
||||
namespace: family
|
||||
tags: [infra, htpc, how-to]
|
||||
sources:
|
||||
- family/how-to/xgimi-play6-setup.md
|
||||
confidence: medium
|
||||
related:
|
||||
- "[[tech/htpc-kodi-layout]]"
|
||||
- "[[tech/htpc-steam-emulators]]"
|
||||
---
|
||||
|
||||
# XGIMI Play 6 — Setup Guide
|
||||
|
||||
Chinese GMUI 6 version. ADB over network only (USB ADB non-functional).
|
||||
IP on home network: `192.168.1.58`.
|
||||
|
||||
## Key Constraints
|
||||
|
||||
- **Architecture:** arm64-v8a (MT9639 chip) — verify all APKs
|
||||
- **OS:** GMUI 6.0 (Android 11) — Wireless ADB not available (needs Android 12+)
|
||||
- **ADB:** Network-only via port 5555
|
||||
|
||||
## Bootstrap Sequence
|
||||
|
||||
### 1. Install via USB flash (before ADB is up)
|
||||
|
||||
APKs must be renamed: `file.apk` → `file.apk.1` (flash drive workaround).
|
||||
Flash must be FAT32. Install via built-in file manager.
|
||||
|
||||
Install in this order:
|
||||
1. SystemUI Tuner (github.com/zacharee/Tweaker) — enables ADB
|
||||
2. Projectivy Launcher — replaces stock XGIMI launcher
|
||||
|
||||
### 2. Enable ADB
|
||||
|
||||
Settings → find ADB → enable. Connect from Mac:
|
||||
|
||||
```bash
|
||||
brew install android-platform-tools
|
||||
adb connect 192.168.1.58:5555
|
||||
adb devices
|
||||
```
|
||||
|
||||
### 3. Install remaining apps via ADB
|
||||
|
||||
```bash
|
||||
adb -s 192.168.1.58:5555 install /path/to/file.apk
|
||||
```
|
||||
|
||||
Recommended apps: LeanKey Keyboard, VLC, Total Commander,
|
||||
YouTube ReVanced, Кинопоиск TV (4pda.to, regular .apk not .apks).
|
||||
|
||||
### 4. Replace launcher
|
||||
|
||||
```bash
|
||||
# Disable stock launcher
|
||||
adb -s 192.168.1.58:5555 shell pm disable-user --user 0 com.xgimi.home
|
||||
# Set Projectivy as default
|
||||
adb -s 192.168.1.58:5555 shell cmd package set-home-activity \
|
||||
com.spocky.projengmenu/.ui.main.MainActivity
|
||||
```
|
||||
|
||||
### 5. Keyboard
|
||||
|
||||
```bash
|
||||
# Disable Sogou Chinese IME
|
||||
adb -s 192.168.1.58:5555 shell pm disable-user --user 0 \
|
||||
com.sohu.inputmethod.sogou.tv
|
||||
# Enable LeanKey
|
||||
adb -s 192.168.1.58:5555 shell ime enable \
|
||||
org.liskovsoft.androidtv.rukeyboard/com.liskovsoft.leankeyboard.ime.LeanbackImeService
|
||||
adb -s 192.168.1.58:5555 shell ime set \
|
||||
org.liskovsoft.androidtv.rukeyboard/com.liskovsoft.leankeyboard.ime.LeanbackImeService
|
||||
```
|
||||
|
||||
Language switch: long-press **Space** or **Menu** on remote.
|
||||
|
||||
### 6. Russian system language
|
||||
|
||||
```bash
|
||||
adb -s 192.168.1.58:5555 shell setprop persist.sys.locale ru-RU && \
|
||||
adb -s 192.168.1.58:5555 reboot
|
||||
```
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# Check connectivity
|
||||
nc -zv 192.168.1.58 5555
|
||||
|
||||
# List all packages
|
||||
adb -s 192.168.1.58:5555 shell pm list packages
|
||||
|
||||
# Launch app
|
||||
adb -s 192.168.1.58:5555 shell monkey -p com.package.name 1
|
||||
|
||||
# Re-enable a disabled package
|
||||
adb -s 192.168.1.58:5555 shell pm enable com.package.name
|
||||
|
||||
# Find correct launcher activity name
|
||||
adb -s 192.168.1.58:5555 shell cmd package resolve-activity \
|
||||
--brief -c android.intent.category.HOME com.package.name
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
```bash
|
||||
# Restore stock launcher
|
||||
adb -s 192.168.1.58:5555 shell pm enable com.xgimi.home
|
||||
# Restore Chinese keyboard
|
||||
adb -s 192.168.1.58:5555 shell pm enable com.sohu.inputmethod.sogou.tv
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [[tech/htpc-kodi-layout]] — HTPC Kodi layout (related home theater setup)
|
||||
- [[tech/htpc-steam-emulators]] — Bazzite HTPC (different device, same home AV context)
|
||||
Reference in New Issue
Block a user