# ━━━━━ PLUGIN / UNRAID / SYSTEM ESSENTIALS ━━━━━ Four scripts that touch Unraid subsystems directly. They live here rather than in the top-level `System_Essentials/` because each one manipulates something that only exists on Unraid — the mover, the User Scripts plugin, the PHP-FPM pool serving emhttp, and the unraid-api service registry. There is no platform-agnostic version of any of them. On TrueNAS there is no mover to stop. | Script | Runs | Role | |--------|------|------| | `php_fpm_max_children.sh` | Array **start** | Raise the PHP-FPM worker ceiling so the WebGUI stays responsive | | `unraid_api_key_renew.sh` | Array **start** + every **15 min** | Re-register Varaverk's key in the ephemeral unraid-api registry | | `user_scripts_stop.sh` | Array **stop** | Stop User Scripts processes before the array goes down | | `mover_stop.sh` | Array **stop** | Stop the mover gracefully before rsync or reboot | All four are wired through `ARRAY_START_SCRIPTS` / `ARRAY_STOP_SCRIPTS` in `master.conf`. `unraid_api_key_renew.sh` is additionally listed in `WATCHDOG_ORCHESTRATOR_SCRIPTS`, so it also re-runs every 15 minutes. That is deliberate: the registry it repairs can be cleared by a service restart at any time, not only across a reboot, and the script is idempotent. --- ## ━━━ WHY EACH ONE EXISTS ━━━ ### 🐘 `php_fpm_max_children.sh` — the WebGUI gets slow, not broken Unraid's WebGUI runs through PHP-FPM, and the stock `pm.max_children` is very low (4–8). Under real load — several browser tabs polling, Docker operations running, a dashboard open — every worker saturates and new requests queue. The WebGUI becomes slow or stops answering, while nothing is actually wrong with the server. Runs at array start because the setting **does not survive an Unraid update** — the OS replaces the pool config. Idempotent: already at the target value means no write and no restart, so a clean boot is silent. ### 🔑 `unraid_api_key_renew.sh` — the registry is ephemeral Varaverk's enhanced monitoring authenticates against unraid-api. That registry is cleared by OS updates and service restarts, so a key that worked yesterday can simply be gone. Re-registers unconditionally every array start rather than only when missing, because the failure it repairs is precisely *a key present in the conf but absent from the registry* — checking the conf would not detect it. Writes the resulting key into `HOST*_UNRAID_API_KEY`. ### 🛑 `user_scripts_stop.sh` — stop new work before shutting down The User Scripts plugin spawns background processes that Varaverk does not own. During a shutdown sequence those can still be starting operations while everything else is being torn down. Runs **first** in `ARRAY_STOP_SCRIPTS` for that reason — stop new work before stopping the things it would work on. Reports each process by **script name**, not just PID, because "stopping 4 processes" tells an operator nothing they can act on. Matching is scoped strictly to processes the User Scripts plugin spawned. A broad pattern would catch Varaverk's own scripts — including, during a reboot, the very script doing the stopping. ### 💾 `mover_stop.sh` — mover and rsync must not overlap The mover relocates files between cache and array. rsync reads those same paths. Both running at once can produce a corrupt or half-moved snapshot on the remote. Ordering in the stop sequence is deliberate: `rsync_stop.sh` runs **before** `mover_stop.sh`, because both write to the same paths and stopping the reader first is the safer order. Sends a wall warning first, then SIGTERM with a configurable window, then SIGKILL only if ignored. The mover is mid-file-move by definition — giving it the chance to finish the current file is the difference between a stopped transfer and a half-moved file. An absent mover exits 0. Callers use this as a precondition ("ensure the mover is not running"), so treating "already stopped" as failure would abort every reboot on a quiet system. --- ## ━━━ WHERE THEY SIT IN THE LIFECYCLE ━━━ ``` Array starting │ ├── php_fpm_max_children.sh ──── WebGUI can handle the load that's about to arrive └── unraid_api_key_renew.sh ──── monitoring can authenticate again ... normal operation ... Array stopping │ ├── user_scripts_stop.sh ─────── stop new work first ├── fallback.sh --stop ├── rsync_stop.sh ────────────── stop the reader ├── mover_stop.sh ────────────── then the writer — same paths └── docker_container_stop.sh ─── containers last, verified one at a time ``` `mover_stop.sh` is also called directly by `server_reboot.sh`, and both stop scripts appear in the User Scripts master template for manual use. --- ## ━━━ SAFEGUARDS ━━━ All four enforce root, take a lock, and support `--dry-run`. Specific to this group: **Graceful before forced.** `mover_stop.sh` and `user_scripts_stop.sh` both use SIGTERM with a window before SIGKILL. Neither kills first. **Absent target is success.** No mover running, no User Scripts running — both exit 0. These are preconditions, not commands that must find something to do. **Idempotent where it matters.** `php_fpm_max_children.sh` writes and restarts only when the value is actually wrong, so array start does not restart PHP-FPM every single boot. **Targeted process matching.** `user_scripts_stop.sh` matches only what the User Scripts plugin spawned — see above for why a broad pattern is dangerous here specifically. **Stop only, never start.** Neither stop script has a counterpart that restarts what it stopped. Unraid's own schedule owns when the mover runs; these only remove it from the picture for a window. --- ## ━━━ CONFIGURATION ━━━ | Variable | Used by | Purpose | |----------|---------|---------| | `HOST*_UNRAID_API_KEY` | `unraid_api_key_renew.sh` | Written at array start and every 15 min — output, not input | | `MOVER_STOP_TIMEOUT` | `mover_stop.sh` | SIGTERM grace window before escalating | | `PHP_MAX_CHILDREN` | `php_fpm_max_children.sh` | Target worker ceiling | See each script's `CONFIGURATION` header section for the authoritative list — and `Deployment/master.conf.template`, which is the versioned schema for all of them.