Files
Varaverk/CLAUDE.md
T

6.6 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.

Hard limits — do not cross these

  • Never create or modify .claude/settings.json in this repo. No workspace hooks, ever. The stale hook that existed here previously fired Deployment/deploy.sh (now deleted) on every file edit and caused unintended deploys. If you think a hook would help, ask first.
  • Never change HOST1_STORAGE_MODE_INTERNAL in host1.conf. Claude data belongs in /mnt/user/appdata/claude-code/ — not inside this repo.
  • Never run or reference anything in the stale dev folder (/mnt/user/Important Shit/Git/Development/Varaverk or /mnt/cloud-storage/...). It does not exist for purposes of this project.
  • Never move files between Configurations/ and Deployment/ without explicit instruction. Configurations/ = live runtime confs (gitignored). Deployment/ = templates and setup tooling (tracked).

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=true
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.

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.