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.
8.1 KiB
━━━━━ PLUGIN / UNRAID ━━━━━
The Unraid platform layer. Everything in this folder exists to translate one specific operating system into the vocabulary Varaverk speaks — and to put a face on it in the Unraid WebGUI.
Varaverk itself knows nothing about Unraid. No script outside this folder references
/etc/rc.d, /boot/config/plugins/dynamix, emhttp, the mover, or a .page file. They call
platform_*() and read $STATE_DIR; this folder decides what those mean on Unraid.
adapter.sh 24 platform_*() functions — the entire OS contract
Varaverk.page WebGUI menu entry (Tasks:95)
VaraverkSettings.page WebGUI settings entry
event/ Unraid array lifecycle hooks
pages/ api/ include/ the three-layer web UI
System_Essentials/ Unraid-specific system scripts
Tools/ Unraid-specific operator tools
Watchdogs/System/ Unraid-specific watchdog (WebGUI health)
Partnership/ Unraid-specific container deploy/cleanup
Swapping platforms means writing
Plugin/truenas/adapter.shimplementing the same 24 function names.load_config.shsourcesPlugin/$PLATFORM/adapter.sh— nothing else in the codebase changes.
━━━ THE PROBLEM THAT BUILT THIS ━━━
Every NAS OS Answers the Same Questions Differently "Is the array mounted?" "Restart this service." "What are the disk temperature thresholds?" "Send a notification." Every platform has an answer, and every answer is different — a different path, a different init system, a different config format.
Scattering those differences through 115 scripts would mean every script carrying an if unraid ... elif truenas branch, and every new platform touching all of them.
Varaverk Vars Are Not OS Vars
Varaverk works in terms of STATE_DIR, SCRIPTS_DIR, DOCKER_APPDATA_BASE,
WATCHDOG_CONTAINERS. Unraid works in terms of /boot/config/plugins/, emhttp,
/mnt/user, dockerMan XML templates, and dynamix.cfg. Something has to map one onto the
other, in exactly one place, or the two vocabularies leak into each other.
A Headless Ecosystem Is Hard to Trust 115 scripts running unattended produce a lot of state nobody can see. Without a UI the only way to know what the watchdogs did last night is to read logs. The WebGUI exists so the system can be inspected without SSH.
━━━ THE ADAPTER — WHERE OS MEETS VARAVERK ━━━
adapter.sh is the whole contract. 24 functions, sourced by load_config.sh after
common.sh, so every script in the ecosystem has them.
The most-called ones, by usage across the repo:
| Function | Calls | What it hides |
|---|---|---|
platform_require_cmd |
28 | Verifying a platform binary exists and is executable |
platform_restart_service |
13 | /etc/rc.d/rc.<name> init scripts |
platform_is_service_running |
13 | Unraid's service process conventions |
platform_is_mover_running |
10 | The Unraid mover — no other OS has one |
platform_get_os_version |
10 | Where the version string lives |
platform_setup_db_path |
9 | Where wizard/setup state persists |
platform_storage_path |
7 | /mnt/user as the user-share root |
Plus: disk states and temperature thresholds from dynamix.cfg, parity/maintenance detection,
native notifications through the dynamix notify script, container rebuild from dockerMan XML
templates, and the WebGUI install path.
The contract is strict, and it is what makes the layer work:
- Every function returns 0/1 and never calls
exit. A missing capability is information the caller needs, not a decision the adapter makes — a watchdog may want to skip where an installer wants to abort. - Value-producing functions write to stdout, captured with
$(). Status travels in the exit code. Keeping those separate is what lets callers use them in conditionals. - It reports; it does not remediate. No retries, no escalation, no notification policy. Burying those here would make identical calls behave differently per platform.
━━━ THE WEB UI — THREE LAYERS ━━━
pages/*.php what you look at ── requires ──► include/
api/*.php what the page fetches ── requires ──► include/
include/*.php the actual logic — vv_*() functions, shared by both
The split matters: a page and its API endpoint call the same vv_*() builders, so a
cached response and a live one cannot disagree in shape. Adding a metric means adding it in
include/ once, and both the page and the endpoint get it.
| Layer | Files | Role |
|---|---|---|
pages/ |
11 | One per WebGUI tab — monitor, docker, arrs, fallback, watchdog, rsync, partnership, scheduler, auth, settings, setup |
api/ |
50 | JSON endpoints the pages poll, plus action endpoints (run a script, stop a job, toggle a flag) |
include/ |
16 | Shared builders and helpers — vv_monitor_*, vv_arrs_*, vv_docker_*, config read/write, auth |
Caching. Several endpoints serve from /tmp/vv_cache (tmpfs) rather than hitting live
APIs on every page view, refreshed by Tools/api_cache_writer.sh. ?live=1 bypasses the
cache. A missing or unparseable cache always falls back to a live call, so the cache can never
be the reason a page fails to load.
━━━ ARRAY LIFECYCLE HOOKS ━━━
event/ plugs Varaverk into Unraid's own array lifecycle. These are how the ecosystem starts
and stops with the array rather than with the OS.
| Hook | Fires | Runs |
|---|---|---|
disks_mounted/array_start_jobs |
Array started | Orchestrators/array_started.sh → ARRAY_START_SCRIPTS |
disks_mounted/rebuild_cron |
Array started | Regenerates varaverk.cron from the scheduler config |
unmounting_disks/array_stop_jobs |
Array stopping | Orchestrators/array_stopping.sh → ARRAY_STOP_SCRIPTS |
Array-start rather than boot is the correct trigger: in flash storage mode SCRIPTS_DIR lives
in appdata, which does not exist until the array mounts.
━━━ THE PLATFORM-SPECIFIC SCRIPT MIRRORS ━━━
These folders mirror the top-level Varaverk structure, but hold work that cannot be platform-agnostic. A script lives here rather than in the root folder when it manipulates Unraid itself.
| Folder | Contents | Why it is platform-specific |
|---|---|---|
System_Essentials/ |
4 scripts | Mover, User Scripts plugin, PHP-FPM pool, unraid-api registry — all Unraid subsystems |
Tools/ |
5 files | Share .cfg recreation, storage-mode migration, API cache writers |
Watchdogs/System/ |
webgui_watchdog.sh |
emhttp / nginx / php-fpm health — there is no generic "WebGUI" |
Partnership/ |
containers.sh |
Container deploy from dockerMan CA XML templates |
Each has its own README where the group is large enough to need one; single-script folders are documented in the script header.
━━━ HOW THIS FOLDER IS INSTALLED ━━━
Two paths, deliberately different:
Development — Plugin/plugin_setup.sh symlinks this directory into the WebGUI plugin
location. Every edit is live immediately. This is the normal working mode.
Release — Plugin/build.sh packages this directory into a Slackware .txz and rewrites
the version and checksum in varaverk.plg. That is what Unraid reinstalls from flash on every
boot.
In flash storage mode git_pull_execute.sh syncs Plugin/ back to /boot/ after each pull,
so the WebGUI always serves current PHP even though SCRIPTS_DIR points at appdata.
━━━ ADDING A NEW PLATFORM ━━━
- Create
Plugin/<platform>/adapter.shimplementing all 24platform_*()functions. - Set
PLATFORM=<platform>invaraverk.cfg.
That is the whole contract for the script ecosystem. load_config.sh sources
Plugin/$PLATFORM/adapter.sh and every script keeps working unchanged.
The WebGUI is separate and optional — it is Unraid-specific by nature (.page files, emhttp
conventions). A new platform can run the entire ecosystem headless with only the adapter, and
add a UI later in whatever form that platform expects.