- Replace python3/PyYAML Authelia ACL parser with pure PHP (no deps available on Unraid) - Cert tab now pulls live from NPM API instead of cert_monitor.sh — auto-discovers all managed certs sorted by urgency - Watchdog page: add missing GB constant and _fmtBytes/_relTime functions that were causing silent render failure - Rsync settings card: pin to far-right 3 columns (grid-column:6/-1), toggle grid narrowed to 2 columns - Add CLAUDE.md project context file on /boot for session persistence across reboots - claude_startup.sh: symlink CLAUDE.md into /root on array start
152 lines
5.8 KiB
Markdown
152 lines
5.8 KiB
Markdown
# Varaverk — Claude Code Context
|
|
|
|
## Working Rules (read first)
|
|
|
|
- **Workspace is always** `/boot/config/plugins/varaverk` — every edit goes here.
|
|
- **Never touch** `/mnt/user/Important Shit/Git/Development/Varaverk` — stale dev folder, ignore it.
|
|
- **No Co-Authored-By** in commit messages unless explicitly asked.
|
|
- **No comments** unless the WHY is genuinely non-obvious.
|
|
- The `.plg` symlinks the installed plugin location directly to this workspace — one copy, no drift.
|
|
|
|
---
|
|
|
|
## Project: What Varaverk Is
|
|
|
|
Self-healing, self-maintaining, mutually-redundant two-server Unraid home media ecosystem.
|
|
One codebase runs on both servers. No primary/standby — both run independently and cover each other.
|
|
|
|
**HOST1 — unRAID-Gmer4Lfe** (`gmer4lfe@gmail.com`)
|
|
- Hardware: Threadripper 1950X, 128 GB RAM, ZFS cache pools
|
|
- Domain: Gmer4Lfe.com
|
|
- Runs: full arr stack (Sonarr/Radarr/Lidarr), auth stack (source of truth), Emby primary
|
|
|
|
**HOST2 — unRAID-Jayred365**
|
|
- Hardware: Intel i5 10th gen, 64 GB RAM
|
|
- Domain: Gmer4Lfe.us
|
|
- Status: being rebuilt — most host2.conf sections scaffolded, not yet fully online
|
|
|
|
Networking between hosts: Tailscale mesh. No hardcoded IPs — hostnames resolve via Tailscale.
|
|
|
|
---
|
|
|
|
## Configuration System (three-file model)
|
|
|
|
Every script sources all three at startup:
|
|
|
|
```
|
|
master.conf ← shared: thresholds, toggles, profiles, orchestrator job lists
|
|
host1.conf ← HOST1 credentials, shares, container names, keys
|
|
host2.conf ← HOST2 credentials, shares, container names, keys
|
|
```
|
|
|
|
Sparse checkout (git) means each server only pulls its own `host*.conf`.
|
|
HOST1 never sees HOST2 credentials and vice versa.
|
|
|
|
**Rule:** thresholds/toggles → `master.conf`; credentials/paths/container names → `host*.conf`.
|
|
|
|
`detect_hosts()` in `common.sh` matches `$(hostname)` against `HOST1`/`HOST2` in `master.conf`
|
|
and sets `MY_ID` / `REMOTE_ID` for the rest of the script.
|
|
|
|
---
|
|
|
|
## Platform Adapter Layer
|
|
|
|
`Plugin/unraid/adapter.sh` isolates all OS-specific calls.
|
|
Scripts never branch on OS directly — always call adapter functions.
|
|
This is intentional architecture — don't bypass it.
|
|
|
|
---
|
|
|
|
## Key Paths
|
|
|
|
| Path | Purpose |
|
|
|------|---------|
|
|
| `master.conf` | Shared config — all thresholds, toggles, profiles |
|
|
| `host1.conf` / `host2.conf` | Per-host credentials, shares, container lists |
|
|
| `common.sh` | Shared functions — `detect_hosts()`, `log()`, `notify()`, etc. |
|
|
| `load_config.sh` | Sources all three conf files + common.sh |
|
|
| `State_Files/` | Runtime state (watchdogs, fallback, transcode) — survives reboots |
|
|
| `data/` | Historical logs and stats |
|
|
| `Plugin/unraid/` | Unraid WebGUI plugin (PHP pages, API endpoints, adapter) |
|
|
| `Orchestrators/` | Top-level schedulers (array_started, daily, weekly, watchdog) |
|
|
| `Watchdogs/` | docker_watchdog, system_watchdog, resource_watchdog, stability |
|
|
| `Fallback/` | Mutual container failover logic |
|
|
| `Rsync/` | rsync.sh + profile system |
|
|
| `Media/` | Arr cleanup, discovery, permissions, play state sync |
|
|
| `Tools/` | Manual one-off tools including `claude_startup.sh` |
|
|
|
|
---
|
|
|
|
## Orchestrator Schedule
|
|
|
|
| When | What |
|
|
|------|------|
|
|
| Array start | `Orchestrators/array_started.sh` → runs `ARRAY_START_SCRIPTS` |
|
|
| Every minute | `watchdog_orchestrator.sh` → resource → docker → system → stability watchdogs |
|
|
| Every 30 min | `critical_sync_maintenance.sh` → downloaders_reset, play_state_sync, critical rsync |
|
|
| Every 4 hours | `intermediate_sync_maintenance.sh` → arr_sync, arrs_failed_stalled_recovery |
|
|
| Daily 1am | `daily_sync_maintenance.sh` → git pull, permissions, cleaners, arr cleanup, docker updates |
|
|
| Sunday 2:30am | `weekly_sync_maintenance.sh` → full Emby + Critical-Data sync, weekly restarts |
|
|
| Sunday 3am+ | `monthly_maintenance.sh` (self-gated on 30-day uptime) → ZFS scrub, SMART tests |
|
|
| Sunday 7am | `sunday_morning_coffee_report.sh` → ZFS, SMART, certs, backup verify, bandwidth, Emby report |
|
|
|
|
---
|
|
|
|
## Rsync Toggle State (current)
|
|
|
|
```bash
|
|
RSYNC_ENABLED=true
|
|
CRITICAL_RSYNC_ENABLED=true
|
|
INTERMEDIATE_RSYNC_ENABLED=true
|
|
DAILY_RSYNC_ENABLED=false # HOST2 rebuild in progress — re-enable when ready
|
|
WEEKLY_RSYNC_ENABLED=true
|
|
FALLBACK_RSYNC_ENABLED=true
|
|
```
|
|
|
|
---
|
|
|
|
## Fallback System
|
|
|
|
`fallback.sh` runs continuously from array start.
|
|
States: `NORMAL | FALLBACK | NO_INTERNET | DARK`
|
|
|
|
DDNS rules are absolute:
|
|
- Internet loss → stop own DDNS immediately
|
|
- Failover → start remote's DDNS as Tier 1 first
|
|
- Handback → stop remote DDNS → rsync → start containers → start local DDNS last
|
|
|
|
Tier delays before activating higher tiers are in `host*.conf` (`HOST1_TIER*_DELAY`, `HOST2_TIER*_DELAY`).
|
|
|
|
---
|
|
|
|
## Port Notes
|
|
|
|
- **NPM admin API (`HOST1_NPM_URL`)** — port **7818**. Port 81 is the partnership WebUI port (`HOST1_PARTNERSHIP_AUTH_WEBUIS`), not the API. Easy to confuse.
|
|
- **HOST1_NETWORK_WATCHDOG_NPM_URL** — external HTTPS domain, completely separate from the admin API.
|
|
|
|
## Known Gaps / Active Work
|
|
|
|
- HOST2 NPM/lldap credentials (`HOST2_NPM_USER`, `HOST2_NPM_PASS`, `HOST2_LLDAP_PASS`) are empty in `host2.conf` — fill in when HOST2 is back online.
|
|
- `PARTNERSHIP_ENABLED=false` — not yet active.
|
|
- `FALLBACK_ENABLED=true` — fallback is running.
|
|
- `DAILY_RSYNC_ENABLED=false` — paused during HOST2 rebuild.
|
|
|
|
---
|
|
|
|
## Claude Code Persistence on Unraid
|
|
|
|
`/root` is a RAM filesystem — wiped on every reboot.
|
|
`Tools/claude_startup.sh` runs at array start (via `ARRAY_START_SCRIPTS`) and:
|
|
- Symlinks `/root/.claude` → `/mnt/user/appdata/claude-code/.claude`
|
|
- Symlinks `/root/.local/share/claude` → `/mnt/user/appdata/claude-code/local/share/claude`
|
|
- Symlinks `/root/CLAUDE.md` → `/boot/config/plugins/varaverk/CLAUDE.md` (this file)
|
|
|
|
This file lives on `/boot` (USB flash) and is always available regardless of array state.
|
|
|
|
---
|
|
|
|
## Commit Style
|
|
|
|
Plain, concise messages. No Co-Authored-By trailers. No bullet-point summaries in the body.
|
|
One sentence on the why, not the what.
|