# ━━━━━ 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 `$VV_CACHE_DIR` (`/tmp/varaverk/api`, 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=1` bypasses 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_.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/varaverk/api/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.