[2026-05-23] restore wiki: 32 files lost to Taiga sync bug; gitignore plugin binaries

This commit is contained in:
Alexey Martemyanov
2026-05-23 11:11:45 +06:00
parent eede094931
commit 620e2df572
33 changed files with 2313 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
---
title: Arr Stack — Kraken
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [arr, radarr, sonarr, prowlarr, transmission, jellyfin, infra, kraken]
related: "[[jellyfin-config]]"
---
# Arr Stack — Kraken
## Pipeline
```
Prowlarr → Radarr + Sonarr → Transmission → Jellyfin
```
## 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 |
## Notes
- See [[arr-stack-taiga]] for Taiga (secondary) arr stack
- Media pipeline pitfalls: [[media-pipeline-pitfalls]]
+30
View File
@@ -0,0 +1,30 @@
---
title: Arr Stack — Taiga
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [arr, taiga, infra, media, pitfalls]
related: "[[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.)
+26
View File
@@ -0,0 +1,26 @@
---
title: Gitea Config
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: personal
tags: [infra, gitea, git, credentials]
related: "[[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
+34
View File
@@ -0,0 +1,34 @@
---
title: Hermes Docker on Kraken
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: personal
tags: [hermes, docker, kraken, infra, how-to]
related: "[[kraken-network]]"
---
# 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
+228
View File
@@ -0,0 +1,228 @@
---
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]] — сетевая топология
+30
View File
@@ -0,0 +1,30 @@
---
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: "[[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.
+31
View File
@@ -0,0 +1,31 @@
---
title: HTPC Steam & Emulators
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [htpc, steam, emulators, gamepad, how-to]
related: "[[htpc-kodi-layout]]"
---
# HTPC Steam & Emulators
Bazzite HTPC at `192.168.1.86`. See [[htpc-bazzite-proton]] for Proton
game compatibility details.
## 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
## Save Locations (approximate)
| System | Path |
|--------|------|
| Steam | `~/.steam/steam/userdata/` |
| RetroArch | `~/.var/app/org.libretro.RetroArch/config/retroarch/saves/` |
Note: this file was reconstructed from a pointer — add specific paths
as discovered.
+32
View File
@@ -0,0 +1,32 @@
---
title: Jellyfin Config
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [jellyfin, infra, media, credentials]
related: "[[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)
+108
View File
@@ -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
+33
View File
@@ -0,0 +1,33 @@
---
title: Kraken Network & Infra
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: personal
tags: [infra, kraken, ssh, wireguard, network]
related: "[[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.
+34
View File
@@ -0,0 +1,34 @@
---
title: Media Pipeline Pitfalls
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [media-pipeline, pitfalls, torrents, infra]
related: "[[arr-stack-kraken]]"
---
# 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.
## 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
## 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
+32
View File
@@ -0,0 +1,32 @@
---
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: "[[kraken-network]]"
---
# 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
+29
View File
@@ -0,0 +1,29 @@
---
title: TrueNAS Inpxer / Books Setup
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: family
tags: [truenas, books, infra, storage]
related: "[[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.
+34
View File
@@ -0,0 +1,34 @@
---
title: Vault Namespace Rules
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: personal
tags: [vault, meta, conventions]
related: "[[kraken-network]]"
---
# 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.
+120
View File
@@ -0,0 +1,120 @@
---
title: WireGuard VPN — Eagle to Kraken
created: '2026-05-23'
updated: '2026-05-23'
type: tech
namespace: personal
tags: [infra, kraken]
sources: [family/how-to/wireguard-vpn.md]
confidence: high
---
# WireGuard VPN — Eagle to Kraken
Split-tunnel VPN connecting Eagle (Mac M4, home) to Kraken (RPi5, home) via
a VPS relay. Enables SSH to Kraken from anywhere and routes Time Machine
backups over the tunnel. Two VPS interfaces avoid hairpin forwarding.
## Topology
```
Eagle (10.99.0.2) ←→ wg0 VPS (10.99.0.1) ←→ wg1 VPS (10.99.1.1) ←→ Kraken (10.99.1.2)
:51820 :51821
```
SNAT rewrites source address: Eagle packets arrive at Kraken with src
`10.99.1.1` (VPS wg1), not Eagle's `10.99.0.2`. FORWARD runs wg0→wg1
on the VPS with nftables.
## VPN Addresses
| Node | VPN IP |
|------|--------|
| VPS wg0 | 10.99.0.1 |
| VPS wg1 | 10.99.1.1 |
| Eagle | 10.99.0.2 |
| Kraken | 10.99.1.2 |
`kraken` hostname resolves via dnsmasq on VPS (`DNS = 10.99.0.1` in Eagle's
wg0.conf). DNS is scoped to the `kraken` domain only (see DNS section).
## Persistence
| Component | Node | How it survives reboot |
|-----------|------|------------------------|
| wg-quick@wg0 + wg-quick@wg1 | VPS | systemd enabled |
| PostUp FORWARD + SNAT rules | VPS | embedded in `/etc/wireguard/wg0.conf` |
| nftables (10.99.0.0/16 forward) | VPS | `/etc/nftables.conf`, systemd enabled |
| dnsmasq (`kraken` → 10.99.1.2) | VPS | `/etc/dnsmasq.d/vpn-hosts.conf`, systemd enabled |
| wg-quick@wg0 | Kraken | systemd enabled |
| wg-auto LaunchDaemon | Eagle | `/Library/LaunchDaemons/top.eagle.wg-auto.plist` |
## Auto-Connect on Eagle
`/usr/local/bin/wg-auto.sh` polls every 30 seconds via launchd
(`StartInterval`, **not** WatchPaths):
- At home (router MAC `f0:79:59:77:9b:70` visible on ARP) → `wg-quick down`
- Off home network → `wg-quick up`
**Why StartInterval and not WatchPaths:** WatchPaths triggered a race —
`wg-quick down` changes DNS via `networksetup`, which writes to
`/Library/Preferences/SystemConfiguration/`, which re-fires launchd,
tearing the tunnel down immediately after connecting.
## DNS (Scoped Resolver)
wg0.conf uses **no global `DNS =`**. PostUp/PostDown manage a
macOS scoped resolver for the `kraken` domain only:
```
PostUp = mkdir -p /etc/resolver && \
echo "nameserver 10.99.0.1" > /etc/resolver/kraken && \
killall -HUP mDNSResponder
PostDown = rm -f /etc/resolver/kraken && killall -HUP mDNSResponder
```
Result: only `kraken` resolves via VPS dnsmasq. Global DNS and Wi-Fi IP
are untouched — prevents address-bar breakage during tunnel transitions.
## Time Machine
| Setting | Value |
|---------|-------|
| Old destination (broken) | `smb://timemachine@kraken._smb._tcp.local./TimeMachine` |
| New destination (working) | `smb://timemachine@kraken/TimeMachine` |
mDNS (`_smb._tcp.local`) doesn't work off the local LAN. VPN DNS (`kraken`
→ 10.99.1.2 via dnsmasq) works from anywhere. Container on Kraken:
`mbentley/timemachine:smb`, `restart: unless-stopped`.
## Public Keys
| Node | Public Key |
|------|------------|
| VPS wg0 | `6W6hSw0JFLm0BbyeNp1g7wF7dKKTZmGvPRdir68mz0w=` |
| VPS wg1 | `ssRV2497NQ3Lfzvx/FLO0jDlcCXdK/RReJQ36i0yuR8=` |
| Eagle | `dDgIjBUNguodOHWoz7iFsImvKhteodHcFWM8mMe4UiE=` |
| Kraken | `8kIdCKMIoMsW09/aQX6+pU0SS/rN4PysJL59w17eGRg=` |
## Diagnostics
```bash
# Eagle — check tunnel state
sudo wg show
ping kraken
# VPS
ssh root@91.207.28.205 "wg show all"
# Kraken
ssh kraken "sudo wg show"
# Eagle auto-connect log
cat /var/log/wg-auto.log
```
## Related
- [[tech/kraken-network]] — Kraken SSH access, media volume paths
- [[personal-os-architecture]] — Eagle hardware, home infra overview