The folder that translates the OS into Varaverk's vocabulary had no docs of its own, so the adapter contract and the three-layer web UI were only discoverable by reading the code.
6.1 KiB
━━━━━ PLUGIN / UNRAID / TOOLS ━━━━━
Platform-specific tooling for the WebGUI and the Unraid installation itself. Two of these keep the UI fast, two are operator tools for specific recovery and migration situations.
They live here rather than in the top-level Tools/ because each one manipulates something
Unraid-specific — share .cfg files, the plugin's own PHP payload builders, or the
installation's storage location.
| File | Type | Runs |
|---|---|---|
api_cache_writer.sh + .php |
UI cache | Every minute via cron |
remote_arr_cache_writer.sh |
UI cache | Every 2 hours via cron |
recreate_shares.sh |
Recovery | Manual — after a rebuild or fresh install |
storage_migrate.sh |
Migration | Manual — switching storage mode |
━━━ THE CACHE WRITERS — WHY PAGES LOAD INSTANTLY ━━━
The monitor and arrs pages present a lot of state: per-core CPU, memory, network, GPUs,
containers, VMs, transcodes, arr library counts. Building that live on every page view means
dozens of API calls and docker inspect runs per refresh, from a WebGUI that is already the
first thing to slow down under load.
Instead, both are written to /tmp/vv_cache (tmpfs — RAM-speed reads, cleared on reboot) and
the pages serve from there.
⚡ api_cache_writer.sh — local payloads, every minute
A deliberate one-line shim: php api_cache_writer.php. All logic is in the PHP because the
payload builders (vv_monitor_*, vv_arrs_*) are the same functions the live API endpoints
call. A bash reimplementation would be a second version of the same payload, free to drift.
Nothing here is allowed to break the UI:
- A failed run simply leaves the cache unrefreshed — pages fall back to live calls. Slower, still correct.
- A missing or unparseable cache is treated as absent, never as empty data.
?live=1bypasses the cache entirely.- Runs unprivileged with no lock — a torn cache file is replaced within 60 seconds, and every reader already has the live fallback.
🌐 remote_arr_cache_writer.sh — partner payloads, every 2 hours
SSHes to each partner and calls vv_arrs_local_node() on their PHP stack, caching the
result locally as arrs_remote_<hostid>.json.
The partner builds its own payload rather than this host querying the partner's arr APIs directly. That matters: the partner already has working local URLs and API keys for its own arrs, so no cross-host credentials and no path mapping are involved. This host never holds keys for a remote's arrs.
A partner whose Tailscale IP will not resolve is skipped, not fatal — the arrs page shows what it has and falls back for the rest.
━━━ THE OPERATOR TOOLS ━━━
🗂️ recreate_shares.sh — after a rebuild
Recreates share directories on the correct disks by reading /boot/config/shares/*.cfg
and honouring each share's shareInclude disk list.
The .cfg files are Unraid's own record of what a share is and which disks it spans — they
are the source of truth, not a list Varaverk maintains. Typically needed on a host after a
full disk replacement or fresh install, where the config survived but the folders did not.
Create only, never delete. A directory that already exists is left alone. This runs at a moment when the operator's picture of what should exist may be out of date, and removing anything on that basis is how a recovery step becomes a data-loss step.
Refuses to run without /mnt/user mounted. Creating share directories against an
unmounted array writes them into the underlying root filesystem, where they then shadow the
real shares once the array does mount.
📦 storage_migrate.sh — moving the whole installation
Relocates Varaverk between the two storage modes:
| Mode | SCRIPTS_DIR |
Trade-off |
|---|---|---|
| Internal | /boot/config/plugins/varaverk |
Direct git pull/push. Available before the array mounts. |
| Flash | /mnt/user/appdata/Varaverk |
Preserves USB flash lifetime. Array must be started for Varaverk to function at all. |
This is the most destructive script in the folder — rsync --delete, cp -a, rm -rf — and
it rewrites the pointers everything else derives from:
varaverk.cfg SCRIPTS_DIR ← the authoritative path
master.conf TARGET_DIR
host*.conf HOST*_STORAGE_MODE_INTERNAL
varaverk.cron regenerated so job paths follow the new SCRIPTS_DIR
STATE_DIR, DATA_DIR, PERSISTENT_CONF_CACHE and every orchestrator job path are built
from SCRIPTS_DIR. Changing storage mode moves all of them at once, which is why the cron is
regenerated rather than edited.
In flash mode, git_pull_execute.sh syncs Plugin/ back to /boot/ after each pull, so the
WebGUI keeps serving current PHP even though the scripts live in appdata.
━━━ SAFEGUARDS ━━━
The cache writers are deliberately unprivileged and lockless. Their output is regenerable within a minute and every consumer has a live fallback. There is no privileged operation to gate and no state worth locking. This is documented in their headers so it is not "corrected" later.
The operator tools are the opposite. Both enforce root, take a lock, and support
--dry-run. storage_migrate.sh additionally exits cleanly if already in the requested mode,
and removes the old location only once the new one is confirmed in place.
recreate_shares.sh will not act on an unmounted array — see above; this is the guard
that prevents shadow directories.
━━━ RELATIONSHIP TO THE WEB UI ━━━
pages/monitor.php ─┐
├─► include/monitor.php (vv_monitor_*)
api/monitor.php ───┘ ▲
│
Tools/api_cache_writer.php ─────┘ same builders → cache can't disagree with live
│
└─► /tmp/vv_cache/monitor.json ──► served by api/monitor.php unless ?live=1
Adding a metric means adding it in include/ once. The page, the live endpoint, and the cache
all pick it up together.