Files
Varaverk/CLAUDE.md
T
Gmer4Lfe bac0f7c535 Auth page: pure-PHP Authelia ACL parser, NPM-sourced certs tab, watchdog JS fixes, rsync settings layout
- 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
2026-06-06 15:39:34 -04:00

5.8 KiB

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)

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.