runc v1.3.5 (Docker 29.x / Unraid 7.3+) crashes on bind-propagation=shared with any container — not GPU-specific. Ramdisk tmpfs is already MS_SHARED at kernel level; propagation is automatic and the option is unnecessary. - Remove bind-propagation=shared from all example Extra Parameters - Update "Why shared Is Required" → "Mount Propagation — Unraid 7.3+" - Update GPU troubleshooting section to cover the general runc crash - Verify commands updated (no longer checking for Propagation: shared) - Historical notes preserved explaining why it existed before Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1680 lines
65 KiB
Markdown
1680 lines
65 KiB
Markdown
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
# 📋 USER SCRIPTS PLUGIN — COMPLETE SETUP REFERENCE
|
|
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
**Every script entry for the User Scripts plugin — what it does, when it runs,
|
|
how to set it up, and what to watch for.** No cross-referencing other READMEs to
|
|
understand the basics. The deeper documentation exists — this is your daily reference.
|
|
|
|
---
|
|
|
|
## ━━━ REQUIRED PLUGINS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Install both from Community Applications before creating any entries:
|
|
|
|
```
|
|
User Scripts — Andrew Zawadzki
|
|
Core plugin. Runs scripts via unRAID UI without terminal.
|
|
Required — nothing works without this.
|
|
|
|
User Scripts Enhanced — Kurotaku
|
|
Adds categories, drag-to-reorder, UI improvements.
|
|
Required for the category organisation used here.
|
|
```
|
|
|
|
---
|
|
|
|
## ━━━ GLOBAL RULES — READ BEFORE CREATING ENTRIES ━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
```
|
|
1. Every script entry → Run in Background: YES
|
|
Without background mode the plugin UI freezes waiting for the script to complete.
|
|
Long-running scripts and continuous loops (failover, watchdogs) require background.
|
|
There are no exceptions — set background on everything.
|
|
|
|
2. Run as root: YES
|
|
All scripts require root. Docker operations, rsync, kernel tuning, reboots.
|
|
|
|
3. Category names match repo folder names exactly
|
|
When the plugin category and the git folder are identical, you never wonder
|
|
which folder a script lives in. No mental translation.
|
|
|
|
4. Script name matches the script filename (without .sh)
|
|
daily_sync_maintenance.sh → name: daily_sync_maintenance
|
|
When logs reference a script name, you find the plugin entry immediately.
|
|
|
|
5. --dry-run exists on every script
|
|
Test anything unfamiliar with --dry-run first. Pre-flight checks still run.
|
|
It shows what would happen without making changes.
|
|
|
|
6. Most scripts never need to be run directly
|
|
The orchestrators handle timing and order. Individual script entries exist
|
|
for manual testing and one-off maintenance — not as replacement cron jobs.
|
|
```
|
|
|
|
---
|
|
|
|
## ━━━ CATEGORY STRUCTURE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Create these categories in User Scripts Enhanced before adding any entries:
|
|
|
|
```
|
|
Orchestrators — scheduled maintenance windows and startup launcher
|
|
Failover — mutual failover state machine and test tools
|
|
Monitors — weekly reports, health checks, trend tracking
|
|
Rsync — manual per-profile sync triggers
|
|
Docker_Essentials — container management tools (manual use)
|
|
Media — library maintenance tools (manual use)
|
|
Transcodes — ramdisk and transcode tools (manual use)
|
|
unRAID_Essentials — server management tools (manual use)
|
|
Partnership — two-server relationship tools (manual use)
|
|
Tools — repair, recovery, and one-time utilities
|
|
Git — script deployment
|
|
```
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🎯 ORCHESTRATORS
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Orchestrators are the only scripts that run on a schedule. They coordinate multiple
|
|
child scripts in the correct order. Adding or removing a job means editing master.conf
|
|
— never the orchestrator script itself.
|
|
|
|
---
|
|
|
|
### ── array_start ─────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: array_start
|
|
Schedule: At Startup of Array
|
|
Background: YES — required (starts continuous background processes)
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/array_started.sh
|
|
```
|
|
|
|
**What it does:**
|
|
The single "At Startup of Array" entry for the entire ecosystem. Launches every
|
|
startup script in the order defined by ARRAY_START_SCRIPTS in master.conf. You
|
|
never add other startup scripts directly to User Scripts — add them to master.conf.
|
|
|
|
**What it starts (in order):**
|
|
```
|
|
inotify_tuning.sh — raises kernel inotify limits before containers start
|
|
containers inherit limits at startup — must be first
|
|
docker_syslog_filter.sh — suppresses Docker veth noise before containers create interfaces
|
|
php_fpm_max_children.sh — sets PHP-FPM workers to 250 before WebGUI serves requests
|
|
ramdisk_setup.sh — creates /mnt/ramdisk_transcodes and symlink before Emby starts
|
|
docker_network_connect.sh— ensures custom networks exist + containers connected
|
|
stability_watchdog.sh ← last-resort — three-tier server stability watchdog
|
|
docker_watchdog.sh ← continuous — two-tier container healing watchdog
|
|
fallback.sh ← continuous — mutual failover state machine
|
|
```
|
|
|
|
**After running:**
|
|
One-shot scripts exit cleanly. Three continuous processes run in the background until
|
|
the array stops. Check with: `pgrep -f "stability_watchdog\|docker_watchdog\|failover"`
|
|
|
|
---
|
|
|
|
### ── transcode_management ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: transcode_management
|
|
Schedule: */7 * * * * (every 7 minutes)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/transcode_management.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Runs transcode_cleanup.sh then transcode_manager.sh — in that exact order every
|
|
7 minutes. Order is non-negotiable: cleanup removes stale files first so the manager
|
|
sees real active session usage, not inflated numbers from ended sessions.
|
|
|
|
**transcode_cleanup.sh:**
|
|
Removes HLS segment files older than TRANSCODE_MAX_AGE minutes that are not currently
|
|
open by any process. Uses one lsof call per location — not one per file. Covers both
|
|
ramdisk and SSD fallback. Never touches the transcoding-temp directory.
|
|
|
|
**transcode_manager.sh:**
|
|
Checks ramdisk usage against RAMDISK_WARN_GB. Flips the /mnt/ram-transcode symlink
|
|
between ramdisk and SSD fallback based on current usage. Shows active Emby sessions
|
|
with their play method. Writes one daily stats entry to TRANSCODE_DAILY_LOG.
|
|
Runs safety checks every cycle: missing symlink → recreate, ramdisk disappeared →
|
|
auto-flip to SSD, missing transcoding-temp → recreate immediately.
|
|
|
|
**Output when healthy:** session list only — no flip messages = ramdisk managing fine
|
|
|
|
> ⚠️ The Emby/Jellyfin Docker container must have
|
|
> `--mount type=bind,source=/mnt/ram-transcode,target=/ext-ram-transcode`
|
|
> in Extra Parameters. Do **not** add `bind-propagation=shared` — runc v1.3.5+
|
|
> (Docker 29.x, Unraid 7.3+) rejects it with a mountinfo error. The ramdisk tmpfs
|
|
> is already MS\_SHARED at the kernel level — propagation is inherited automatically.
|
|
|
|
---
|
|
|
|
### ── critical_sync_maintenance ───────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: critical_sync_maintenance
|
|
Schedule: */30 * * * * (every 30 minutes)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/critical_sync_maintenance.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Keeps the auth stack and Emby watch state current on HOST2 — 30 minutes is the
|
|
maximum staleness for fallback-critical data.
|
|
|
|
**Jobs in order:**
|
|
```
|
|
rsync Critical-Data — pushes auth stack to HOST2 (NPM rules, certs, LLDAP users,
|
|
Authelia config). HOST2's auth is always within 30min of HOST1.
|
|
rsync Emby dirty sync — pushes watch states, user activity, library delta to HOST2
|
|
with Emby running. WAL files excluded — safe mid-write.
|
|
HOST2 Emby restarts after sync to pick up config changes.
|
|
partnership --check — reads remote state file, increments offline counter if HOST2
|
|
unreachable, triggers auto-offboard at PARTNERSHIP_OFFLINE_THRESHOLD
|
|
```
|
|
|
|
**Silent when healthy:** no output on clean cycles — runs 48 times per day.
|
|
|
|
---
|
|
|
|
### ── arrs_failed_stalled_recovery ───────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: arrs_failed_stalled_recovery
|
|
Schedule: 0 */6 * * * (every 6 hours)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/arrs_failed_stalled_recovery.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Automatically recovers failed imports and stalled downloads across Sonarr, Radarr,
|
|
and Lidarr. A release that downloaded but failed to import sits in the queue
|
|
permanently without this — no arr retries importFailed items on its own.
|
|
|
|
**What it finds and acts on:**
|
|
```
|
|
importFailed — downloaded but couldn't import → blocklist + remove + new search
|
|
importPending — stuck in import queue → blocklist + remove + new search
|
|
error — serious failure state → blocklist + remove + new search
|
|
stalled — no seeders or no progress → blocklist + remove + new search
|
|
```
|
|
|
|
**What it never touches:** items with status "downloading" or "imported".
|
|
Age gate: items newer than ARR_IMPORT_RECOVERY_AGE (default: 6 hours) are skipped —
|
|
the arr may still retry on its own.
|
|
|
|
**Result:** failed imports are automatically replaced while you sleep.
|
|
|
|
---
|
|
|
|
### ── daily_sync_maintenance ──────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: daily_sync_maintenance
|
|
Schedule: 0 1 * * * (1am daily)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/daily_sync_maintenance.sh
|
|
```
|
|
|
|
**What it does:**
|
|
The full 1am daily maintenance window — everything that needs to happen overnight
|
|
in one orchestrated sequence.
|
|
|
|
**Execution order:**
|
|
```
|
|
1. git_pull_execute.sh — pull latest scripts FIRST, everything below runs on
|
|
current code
|
|
|
|
2. rsync DAILY_SYNC_SHARES — push this server's truth shares to the other server
|
|
HOST1 pushes: Movies, Tv_Shows, Music, Kids content, Sports...
|
|
HOST2 pushes: Anime_Shows, Anime_Movies
|
|
Personal encrypted shares appended after — encrypted blocks, remote can't read
|
|
|
|
Drive temp exit codes:
|
|
exit 1 (WARN) → skip this share, continue to next
|
|
exit 2 (CRIT) → abort ALL remaining syncs, notify immediately
|
|
|
|
3. media_shares_permissions.sh — apply nobody:users 755/664 to all media shares
|
|
arr cleanup depends on correct ownership
|
|
|
|
4. media_cleaner.sh anime — remove .sfv .nfo .rar .sample and other scene junk
|
|
media_cleaner.sh media from anime and media share folders
|
|
junk removal BEFORE orphan detection — cleaner results
|
|
|
|
5. lidarr_cleanup.sh — identify and delete orphaned music files not tracked
|
|
sonarr_cleanup.sh by the arr API. 7 safety checks must all pass before
|
|
radarr_cleanup.sh a single file is deleted. notify_emby_scan() called
|
|
after any deletion — Emby library cleaned immediately
|
|
|
|
6. docker_daily_restart.sh — restart connection-heavy containers that degrade over time
|
|
NginxProxyManager, Authelia, Dispatcharr, ErsatzTV-Emby
|
|
Running → docker restart. Stopped → left stopped.
|
|
```
|
|
|
|
**Notify:** silent on success. One notification on failure with count of failed jobs.
|
|
**Both servers run this independently at 1am** — same script, correct direction via detect_hosts().
|
|
|
|
---
|
|
|
|
### ── rsync_emby_failover ─────────────────────────────────────────────────────
|
|
|
|
> **Superseded by `critical_sync_maintenance`.** Delete this User Script from the
|
|
> plugin. The emby-fallback dirty sync now runs as step 2 inside
|
|
> `critical_sync_maintenance.sh` every 30 minutes alongside the auth stack sync
|
|
> and partnership check. Running both produces duplicate syncs.
|
|
|
|
The Emby dirty sync (`/mnt/user/Media_Server/Emby --profile=emby-fallback`) is
|
|
configured in `HOST1_CRITICAL_SYNC_SHARES` in host1.conf. It runs automatically
|
|
when critical_sync_maintenance.sh runs.
|
|
|
|
---
|
|
|
|
### ── weekly_sync_maintenance ─────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: weekly_sync_maintenance
|
|
Schedule: 30 2 * * 0 (Sunday 2:30am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/weekly_sync_maintenance.sh
|
|
```
|
|
|
|
**What it does:**
|
|
The full Sunday maintenance window — clean sync with containers stopped, image
|
|
updates at zero extra downtime, weekly container restarts.
|
|
|
|
**Execution order:**
|
|
```
|
|
1. Pre-flight — connectivity, remote Docker daemon, remote rootfs
|
|
2. Stop local containers — Emby + auth stack stopped on this server
|
|
3. Stop remote containers— Emby + auth stack stopped on remote via SSH
|
|
4. Pull images locally — if WEEKLY_SYNC_UPDATES=true (containers already stopped,
|
|
free downtime, both servers start on identical image versions)
|
|
5. Pull images remotely — if WEEKLY_SYNC_UPDATES_REMOTE=true (SSH to remote)
|
|
6. rsync WEEKLY_SYNC_SHARES:
|
|
/mnt/user/Media_Server/Emby — full clean mirror, databases checkpointed
|
|
/mnt/user/appdata-Fallback/Critical-Data — auth stack clean state
|
|
7. Start remote containers— dependency order, new image, settle + verify each
|
|
8. Start local containers — same
|
|
9. docker_weekly_restart.sh — restarts less-critical services that benefit from
|
|
weekly clean start: NextCloud, AdGuard, Immich
|
|
```
|
|
|
|
**Why containers stop for Emby sync:**
|
|
Weekly sync is a full clean mirror including databases. Emby must be stopped to
|
|
checkpoint WAL — ensures a consistent database copy, not a snapshot mid-write.
|
|
~30 seconds of downtime. The 30-minute dirty sync covers users until this clean sync.
|
|
|
|
**Why weekly and not nightly:**
|
|
Emby builds a warm image thumbnail cache on HOST2 throughout the week. Nightly sync
|
|
resets this cache — cold loads every morning. Weekly sync: cache stays warm 6 days,
|
|
resets Sunday night while users sleep.
|
|
|
|
---
|
|
|
|
### ── sunday_morning_coffee_report ────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Orchestrators
|
|
Name: sunday_morning_coffee_report
|
|
Schedule: 0 7 * * 0 (Sunday 7am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Orchestrators/sunday_morning_coffee_report.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Full weekly system overview — everything that happened this week in one clean read.
|
|
Designed to be read over coffee after the 2:30am maintenance window has completed
|
|
and run all the Sunday morning monitor scripts.
|
|
|
|
**Sections:**
|
|
```
|
|
🖥️ System — uptime, memory, boot drive, cache usage, reboots this week
|
|
📀 Array — disk count, parity status, ZFS health, drive temperatures
|
|
🎬 Transcodes — weekly ramdisk peak, flip count, session split (ramdisk vs SSD)
|
|
🎵 Media Activity — arr cleanup stats (orphans removed, space freed), queue depth
|
|
🌐 Rsync — weekly transfer totals, per-share breakdown, failures
|
|
🛡️ Watchdog — system + docker watchdog state, active strikes, skip list
|
|
🔐 Security — SSL cert expiry days remaining per domain (live TLS check)
|
|
📊 Emby — version, active streams now, weekly play count, top users
|
|
⚙️ System Health — inotify peak/avg/warnings, php-fpm peak/avg, SMART, git sync
|
|
⚠️ Issues — anything requiring attention from any section above
|
|
```
|
|
|
|
**Delivery:** unRAID notification + Discord webhook (if configured).
|
|
**Silent when healthy:** footer shows ✅ if no issues, ⚠️ with count if something needs attention.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 📊 MONITORS
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Monitor scripts observe and report — they never act. Read-only except for two bounded
|
|
log writers. All are safe to run manually at any time.
|
|
|
|
---
|
|
|
|
### ── weekly_health_digest ────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: weekly_health_digest
|
|
Schedule: 0 8 * * * (8am daily — DIGEST_PROFILE in master.conf controls notify behaviour)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/weekly_health_digest.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Reads state files from across the ecosystem — watchdog strikes, failover state, skip
|
|
list, bandwidth history, transcode stats, cert expiry — and compiles them into a
|
|
digest notification. Reads only, writes nothing.
|
|
|
|
**DIGEST_PROFILE controls when it notifies (set in master.conf):**
|
|
```
|
|
always — sends every run regardless of content (daily digest, even when healthy)
|
|
smart — sends only when something worth reporting is found
|
|
triggers: watchdog strikes, non-NORMAL failover, cert warnings, bandwidth spikes
|
|
weekly — sends once per week on DIGEST_DAY (Sunday), silent all other days
|
|
```
|
|
|
|
Schedule never changes (8am daily). Switching between profiles requires only one
|
|
line change in master.conf — no cron edit needed.
|
|
|
|
---
|
|
|
|
### ── system_tuning_monitor ───────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: system_tuning_monitor
|
|
Schedule: 0 */6 * * * (every 6 hours)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/system_tuning_monitor.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Snapshots inotify and PHP-FPM utilisation every 6 hours. Writes one bounded log
|
|
entry. The sunday_morning_coffee_report reads this log for peak, average, and
|
|
warning counts over the week.
|
|
|
|
**inotify monitoring:**
|
|
Current instances in use vs kernel limit. Warns above INOTIFY_WARN_PCT (80%).
|
|
Shows top 5 consumers. inotify exhaustion = downloads complete but arrs don't detect
|
|
them, Live TV stutters, library updates stop — no obvious error anywhere.
|
|
|
|
**PHP-FPM monitoring:**
|
|
Active workers vs PHP_MAX_CHILDREN. Warns above PHP_FPM_WARN_PCT (80%).
|
|
Saturation = WebGUI slows, settings saves hang, container starts from UI timeout.
|
|
|
|
**Log:** TUNING_MONITOR_LOG — bounded, trimmed to TUNING_LOG_RETENTION days on write.
|
|
|
|
---
|
|
|
|
### ── zfs_memory_snapshot ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: zfs_memory_snapshot
|
|
Schedule: 0 6 * * 0 (Sunday 6am — first Sunday script, before everything else)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/zfs_memory_snapshot.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Weekly ZFS pool health and memory diagnostic. Runs before other Sunday monitors so
|
|
pool state is captured while the system is post-maintenance and settled.
|
|
|
|
**Reports:**
|
|
ZFS pool status (ONLINE/DEGRADED/FAULTED) per pool. ARC size vs max, hit rate, metadata
|
|
ratio. Total and available RAM. Top 10 Docker containers by memory. Kernel pressure
|
|
via vmstat. Warns if ARC > ZFS_REPORT_ARC_WARN_PCT or RAM < ZFS_REPORT_FREE_WARN_GB.
|
|
Output goes to both console and /var/log/zfs-weekly-health.log for week-over-week comparison.
|
|
|
|
---
|
|
|
|
### ── smart_health ────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: smart_health
|
|
Schedule: 0 7 * * 0 (Sunday 7am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/smart_health.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Queries SMART attributes for every /dev/sd* and /dev/nvme* drive weekly. Drives
|
|
in HOST*_SMART_IGNORE_DRIVES (typically sda — the boot USB) are skipped.
|
|
|
|
**What triggers a notification:**
|
|
```
|
|
Reallocated_Sector_Ct > 0 — drive found and swapped a bad sector — warning sign
|
|
Current_Pending_Sector > 0 — drive suspects sectors bad, not yet confirmed
|
|
Offline_Uncorrectable > 0 — sectors that couldn't be corrected — data loss risk
|
|
Temperature > thresholds — reads from dynamix.cfg (same thresholds as unRAID UI)
|
|
SMART overall-health FAILED — get data off this drive immediately
|
|
```
|
|
|
|
**Silent when healthy:** no notification if all drives pass all checks.
|
|
|
|
---
|
|
|
|
### ── cert_monitor ─────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: cert_monitor
|
|
Schedule: 0 9 * * 0 (Sunday 9am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/cert_monitor.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Connects to each domain via live `openssl s_client` TLS connection and reads the
|
|
certificate actually being served — not NPM's API, not the certificate file.
|
|
|
|
**Why live TLS and not an API check:**
|
|
NPM can report a cert as renewed while the web server is still serving the old
|
|
expired cert (nginx not reloaded after renewal). A live TLS check catches this.
|
|
If a user would see a certificate error, this script catches it first.
|
|
|
|
**Thresholds (master.conf):**
|
|
```
|
|
> CERT_WARN_DAYS (30) → silent ✅
|
|
≤ CERT_WARN_DAYS (30) → notification — renew soon
|
|
≤ CERT_CRIT_DAYS (7) → urgent notification — renew now
|
|
connection failed → notification — cert unreachable
|
|
```
|
|
|
|
---
|
|
|
|
### ── backup_verify ───────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: backup_verify
|
|
Schedule: 0 10 * * 0 (Sunday 10am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/backup_verify.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Randomly samples BACKUP_VERIFY_SAMPLE (default: 10) files per share, computes MD5
|
|
checksums on both sides via SSH, and compares. Does not trust rsync's exit code —
|
|
verifies actual content matches.
|
|
|
|
**Why verify independently:**
|
|
rsync exit 0 does not mean the copy is correct. Silent data corruption from faulty
|
|
hardware produces a file that exists on both sides with matching size and mtime but
|
|
different content. rsync never detects this. MD5 does.
|
|
|
|
**Pre-flight guards:**
|
|
```
|
|
check_connectivity() — aborts if remote Tailscale IP unreachable
|
|
prevents all files showing as MISSING from network failure
|
|
check_remote_array() — aborts if /mnt/user not mounted on remote
|
|
prevents all files showing as MISSING from array not started
|
|
```
|
|
|
|
---
|
|
|
|
### ── emby_session_report ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: emby_session_report
|
|
Schedule: 0 11 * * 0 (Sunday 11am)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/emby_session_report.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Queries the Emby API for the past EMBY_REPORT_DAYS (7) days and reports streaming
|
|
activity. Each server reports on its own Emby instance via HOST*_EMBY_URL.
|
|
|
|
**Reports:**
|
|
Server info + version. Active streams now with direct play vs transcode breakdown.
|
|
Library counts (movies, episodes, songs). Weekly play count. Top EMBY_REPORT_TOP_N
|
|
most-played items. Most active users. Transcode ratio — notifies if > 80% transcoding
|
|
(usually means a client/format compatibility issue worth fixing).
|
|
|
|
---
|
|
|
|
### ── bandwidth_monitor_report ────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Monitors
|
|
Name: bandwidth_monitor_report
|
|
Schedule: 0 11 * * 0 (Sunday 11am — runs alongside emby_session_report)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Monitors/bandwidth_monitor.sh --report
|
|
```
|
|
|
|
**What it does:**
|
|
Reads the accumulated BANDWIDTH_LOG (written by rsync.sh after each sync) and
|
|
generates a weekly transfer summary.
|
|
|
|
**The log is written automatically by rsync.sh** — you never call
|
|
`--log-transfer` manually. This `--report` entry reads what rsync already logged.
|
|
|
|
**Reports:**
|
|
Per-profile run count, total transferred, average duration, failures.
|
|
Last 7 days timeline. Large transfer flags (> BANDWIDTH_WARN_GB).
|
|
Log format: DATE|TIME|profile|duration|status|bytes — version-stable field names
|
|
that survive rsync updates without parser changes.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🔄 FAILOVER
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
> **fallback.sh is started by array_started.sh — not scheduled separately.**
|
|
> These entries exist for manual control and testing only.
|
|
|
|
---
|
|
|
|
### ── failover_status ─────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Failover
|
|
Name: failover_status
|
|
Schedule: None — run manually
|
|
Background: NO (runs and exits — status check)
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Fallback/fallback.sh --status
|
|
```
|
|
|
|
**What it does:**
|
|
Shows current failover state at a glance without affecting the running loop.
|
|
State (NORMAL/FAILOVER/NO_INTERNET/DARK). Which tier containers are active.
|
|
Outage duration if in FAILOVER. Handback strike count if remote has returned.
|
|
DDNS containers currently running. Remote server Tailscale visibility.
|
|
|
|
**Use before any manual failover intervention.** Understanding the current state
|
|
before acting prevents making things worse.
|
|
|
|
---
|
|
|
|
### ── failover_test ────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Failover
|
|
Name: failover_test
|
|
Schedule: None — run manually (during a planned maintenance window)
|
|
Background: YES — test takes several minutes
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Fallback/fallback_test.sh --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Validates the full failover lifecycle — detection, Tier 1 container start, handback,
|
|
container stop, DNS return — using an iptables rule to simulate remote unreachability.
|
|
No real outage. Safety trap removes the iptables rule on any exit condition including
|
|
ctrl-c and crashes — remote is always reachable after the test.
|
|
|
|
> ⚠️ **Always run with --dry-run first.** Dry run walks all 8 phases with full
|
|
> output but no iptables changes and no container starts/stops. Review timing and
|
|
> configuration before committing to a live test.
|
|
|
|
**For a live test** (real container lifecycle, brief service interruption):
|
|
Change `--dry-run` to nothing and run during a maintenance window.
|
|
|
|
**8 phases:** pre-flight → block remote → detect FAILOVER → verify Tier 1 started
|
|
→ restore remote → wait for handback → verify NORMAL restored → report pass/fail.
|
|
|
|
---
|
|
|
|
### ── fallback_state_reset ────────────────────────────────────────────────────
|
|
|
|
> **Not yet built.** `fallback_state_reset.sh` is a planned utility — not in `Fallback/` yet.
|
|
>
|
|
> **Manual workaround** when state file is stuck in FAILOVER after a failed test or
|
|
> forced kill of fallback.sh:
|
|
> ```bash
|
|
> # Verify first — right containers on right server, DDNS correct, fallback.sh not running
|
|
> cat /boot/config/fallback_state.db
|
|
> echo "state=NORMAL" > /boot/config/fallback_state.db
|
|
> ```
|
|
> Resets state only — does NOT start or stop any containers.
|
|
|
|
**When you need this:**
|
|
State file stuck in FAILOVER after a test that didn't complete cleanly. After killing
|
|
fallback.sh directly (not via plugin Abort button). After a failed handback.
|
|
|
|
**Verify before resetting:**
|
|
Right containers on right server. DDNS correct (`nslookup Gmer4Lfe.com`).
|
|
Both servers Tailscale connected. fallback.sh not currently running.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🔄 RSYNC
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Manual trigger entries for individual rsync profiles. Used when you need to sync
|
|
one specific share outside the normal nightly window — after a bulk import, before a
|
|
planned migration, or to verify connectivity.
|
|
|
|
> **These are NOT scheduled.** Daily and weekly orchestrators handle all scheduled syncs.
|
|
> These exist purely for on-demand manual triggers.
|
|
|
|
**Every rsync run includes:**
|
|
Pre-flight checks (connectivity, version parity, remote daemon, remote rootfs, share exists).
|
|
Profile-matched container stop/start (if profile requires it). Bandwidth logging.
|
|
Drive temperature check — exit 1 on WARN, exit 2 on CRITICAL.
|
|
|
|
---
|
|
|
|
### ── rsync_critical_data ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Rsync
|
|
Name: rsync_critical_data
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Rsync/rsync.sh \
|
|
/mnt/user/appdata-Fallback/Critical-Data
|
|
```
|
|
|
|
**What syncs:** auth stack — NPM proxy rules, TLS certificates, LLDAP user data,
|
|
Authelia policies and config, MariaDB database. Profile: critical-data. Stops auth
|
|
containers on both sides, syncs, restarts with dependency ordering (databases before auth).
|
|
|
|
---
|
|
|
|
### ── rsync_emby_clean ─────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Rsync
|
|
Name: rsync_emby_clean
|
|
Schedule: None — run manually (also runs via weekly_sync_maintenance.sh)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Rsync/rsync.sh \
|
|
/mnt/user/Media_Server/Emby --profile=emby
|
|
```
|
|
|
|
**What syncs:** full clean Emby mirror — all databases checkpointed, metadata, plugins,
|
|
config. Both Emby instances stopped during sync. Excludes transcodes, logs, cache, crash
|
|
files. This is the full-fidelity sync (vs emby-fallback which is the dirty 30-minute sync).
|
|
|
|
---
|
|
|
|
### ── rsync_arrs_stack ─────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Rsync
|
|
Name: rsync_arrs_stack
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Rsync/rsync.sh \
|
|
/mnt/user/appdata-Fallback/Arrs_Stack
|
|
```
|
|
|
|
**What syncs:** all arr appdata — Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, Pinchflat
|
|
databases and config. Profile: arrs_stack. Arr containers stopped on both sides during
|
|
sync to ensure clean SQLite snapshot (no mid-write database corruption).
|
|
|
|
---
|
|
|
|
### ── rsync_important_data ────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Rsync
|
|
Name: rsync_important_data
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Rsync/rsync.sh \
|
|
/mnt/user/appdata-Fallback/Important-Data
|
|
```
|
|
|
|
**What syncs:** NextCloud, Postgres-NextCloud, Immich, PostgreSQL-Immich appdata.
|
|
Profile: important-data. Postgres containers stop first, then NextCloud after delay.
|
|
|
|
---
|
|
|
|
### ── rsync_gmer4lfe ───────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Rsync
|
|
Name: rsync_gmer4lfe
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Rsync/rsync.sh \
|
|
/mnt/user/appdata-Fallback/Gmer4Lfe
|
|
```
|
|
|
|
**What syncs:** HOST1 server appdata backup — everything in the Gmer4Lfe appdata share.
|
|
No profile container stop required. Incremental — safe to run at any time.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🐳 DOCKER_ESSENTIALS
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
> **docker_watchdog.sh is called every minute by watchdog_orchestrator.sh — not scheduled separately.**
|
|
> docker_daily_restart.sh is called by daily_sync_maintenance.sh.
|
|
> docker_weekly_restart.sh is called by weekly_sync_maintenance.sh.
|
|
> docker_network_connect.sh is called by array_started.sh.
|
|
> These entries exist for manual control only.
|
|
|
|
---
|
|
|
|
### ── docker_watchdog_status ──────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Docker_Essentials
|
|
Name: docker_watchdog_status
|
|
Schedule: None — run manually
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Watchdogs/docker_watchdog.sh --status
|
|
```
|
|
|
|
**What it shows:**
|
|
Strike counts for all monitored containers. Current skip list with running/stopped state.
|
|
Whether startup grace period is active and how long remains. Whether RAM emergency
|
|
deferral is active (mem_shutdown_active from resource_watchdog). Last cycle timing.
|
|
|
|
---
|
|
|
|
### ── watchdog_skip_list_manager ──────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Docker_Essentials
|
|
Name: watchdog_skip_list_manager
|
|
Schedule: None — run manually (after fixing a skip-listed container)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Docker_Essentials/watchdog_skip_list_manager.sh --status
|
|
```
|
|
|
|
**What it does:**
|
|
Views and manages the persistent container skip list. When docker_watchdog.sh restarts
|
|
the same container 3 times in 1 hour it adds it to the skip list and stops trying.
|
|
A critical notification is sent. This tool clears the list after you've fixed the cause.
|
|
|
|
**Recovery workflow:**
|
|
```
|
|
1. Run --status to see what's skip-listed and its restart history
|
|
2. Fix the underlying problem (check docker logs, disk space, database)
|
|
3. --clear ContainerName to remove from skip list + clear restart history
|
|
4. docker start ContainerName to confirm your fix works
|
|
5. Watchdog resumes monitoring on next cycle automatically
|
|
```
|
|
|
|
**Actions:**
|
|
```
|
|
--status — show skip list, running/stopped state, restart counts
|
|
--clear ContainerName — clear specific container (prompts YES)
|
|
--clear ContainerName --force — no prompt
|
|
--clear-all — clear everything
|
|
--dry-run — preview any clear action
|
|
```
|
|
|
|
---
|
|
|
|
### ── docker_daily_restart_manual ─────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Docker_Essentials
|
|
Name: docker_daily_restart_manual
|
|
Schedule: None — run manually (called automatically by daily_sync_maintenance.sh)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Docker_Essentials/docker_daily_restart.sh --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Restarts containers in HOST*_DAILY_RESTART_CONTAINERS. Running → docker restart
|
|
(graceful stop + start). Stopped → left stopped (state respected). Missing → skip.
|
|
Dependency ordering: databases restart before applications. CONTAINER_DELAY wait
|
|
between dependency and dependent restarts.
|
|
|
|
**Default configured containers:** NginxProxyManager, Authelia, Dispatcharr,
|
|
Dispatcharr-Basic, ErsatzTV-Emby — services that degrade with uptime.
|
|
|
|
> Remove `--dry-run` to run live. Default is dry-run for safety when run manually.
|
|
|
|
---
|
|
|
|
### ── docker_network_connect_manual ───────────────────────────────────────────
|
|
|
|
```
|
|
Category: Docker_Essentials
|
|
Name: docker_network_connect_manual
|
|
Schedule: None — run manually (runs automatically via array_started.sh)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Docker_Essentials/docker_network_connect.sh --status
|
|
```
|
|
|
|
**What it does:**
|
|
Ensures custom Docker networks exist and containers are connected to them. Idempotent
|
|
— safe to run any time. If a network is missing (typically wiped by a unRAID update),
|
|
it creates it and notifies.
|
|
|
|
**Use after unRAID updates** if containers can't reach each other — the update may have
|
|
wiped custom networks. Run this to recreate them without restarting the array.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🎬 MEDIA
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
> **All media scripts are called by daily_sync_maintenance.sh via media_management.sh.**
|
|
> These entries exist for manual testing and targeted one-off runs.
|
|
> Run --dry-run --log for any new system or after configuration changes.
|
|
|
|
---
|
|
|
|
### ── media_shares_permissions_manual ────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: media_shares_permissions_manual
|
|
Schedule: None — run manually (runs automatically via daily_sync_maintenance.sh)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/media_shares_permissions.sh --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Applies `nobody:users` ownership and 755 (dirs) / 664 (files) permissions to every
|
|
file in HOST*_MEDIA_PERMISSION_SHARES. Two separate passes — directories and files
|
|
get different modes. Idempotent — only changes what's wrong.
|
|
|
|
**When ownership drifts:** scp/cp from another machine leaves root:root. New container
|
|
before PUID/PGID is set. rsync without --chown. This fixes it all in one pass.
|
|
|
|
> Remove `--dry-run` to run live. Dry run shows count of files that would be corrected.
|
|
|
|
---
|
|
|
|
### ── media_cleaner_anime_manual ──────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: media_cleaner_anime_manual
|
|
Schedule: None — run manually (runs automatically via daily_sync_maintenance.sh)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/media_cleaner.sh anime --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Removes junk files from anime share folders using ANIME_FILE_PATTERNS. Patterns
|
|
include: *.sfv *.nfo *.rar *.sample* *.torrent *.url *.log and other scene release
|
|
debris. Runs before arr cleanup so orphan detection only sees actual media files.
|
|
|
|
---
|
|
|
|
### ── media_cleaner_media_manual ──────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: media_cleaner_media_manual
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/media_cleaner.sh media --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Same as above but for media share folders using MEDIA_FILE_PATTERNS — all anime
|
|
patterns plus *.iso and *.lrc.
|
|
|
|
---
|
|
|
|
### ── lidarr_cleanup_manual ───────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: lidarr_cleanup_manual
|
|
Schedule: None — run manually (runs automatically via daily_sync_maintenance.sh)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/lidarr_cleanup.sh --dry-run --log
|
|
```
|
|
|
|
**What it does:**
|
|
Queries Lidarr API for all tracked file paths. Walks /mnt/user/Music. Files on disk
|
|
not in the API response that are older than LIDARR_ORPHAN_AGE (7 days) and not
|
|
currently open by any process = orphans = deleted.
|
|
|
|
**7 safety checks must ALL pass before any deletion:**
|
|
Lidarr running + healthy. API reachable. API version matches. Artist count > 0.
|
|
Tracked file count > 0. Count >= 80% of last known (detects database issues).
|
|
Total deletion size < LIDARR_MAX_DELETE_GB (50GB) — stops catastrophic path mismatches.
|
|
|
|
**Protected always:** *.jpg *.png (cover art), *.nfo (metadata), *.lrc (lyrics)
|
|
**After deletion:** notify_emby_scan() triggers "Clean Missing Files" in Emby immediately.
|
|
|
|
> Remove `--dry-run` only after reviewing the full log output. See README-Media.md
|
|
> for the complete safe testing procedure.
|
|
|
|
---
|
|
|
|
### ── sonarr_cleanup_manual ───────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: sonarr_cleanup_manual
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/sonarr_cleanup.sh --dry-run --log
|
|
```
|
|
|
|
**What it does:**
|
|
Same logic as lidarr_cleanup but for TV files. Walks HOST*_SONARR_TV_ROOT.
|
|
Protected: *.jpg *.png (artwork), *.nfo, *.srt *.sub *.ass *.ssa (Bazarr subtitles).
|
|
Host-aware: HOST1 manages Tv_Shows, HOST2 manages Anime_Shows — correct root via detect_hosts().
|
|
|
|
---
|
|
|
|
### ── radarr_cleanup_manual ───────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Media
|
|
Name: radarr_cleanup_manual
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Media/radarr_cleanup.sh --dry-run --log
|
|
```
|
|
|
|
**What it does:**
|
|
Same logic for movie files. Walks HOST*_RADARR_MOVIES_ROOT.
|
|
Protected: *.jpg *.png (movie artwork), *.nfo, subtitles.
|
|
Host-aware: HOST1 manages Movies, HOST2 manages Anime_Movies.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🎬 TRANSCODES
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
> **ramdisk_setup.sh is called by array_started.sh — not scheduled separately.**
|
|
> **transcode_manager.sh and transcode_cleanup.sh are called by transcode_management.sh.**
|
|
> These entries exist for manual status checks and emergency use.
|
|
|
|
---
|
|
|
|
### ── ramdisk_status ────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Transcodes
|
|
Name: ramdisk_status
|
|
Schedule: None — run manually
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Transcodes/ramdisk_setup.sh --status
|
|
```
|
|
|
|
**What it shows:**
|
|
Whether ramdisk is mounted at RAMDISK_PATH. Current symlink target (ramdisk or SSD).
|
|
Whether transcoding-temp exists on ramdisk. SSD fallback directory state.
|
|
Current usage on both ramdisk and SSD.
|
|
|
|
---
|
|
|
|
### ── transcode_manager_manual ────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Transcodes
|
|
Name: transcode_manager_manual
|
|
Schedule: None — run manually (runs via transcode_management.sh every 7 min)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Transcodes/transcode_manager.sh --status
|
|
```
|
|
|
|
**What it shows:**
|
|
Current mode (smart/ramdisk/ssd). Ramdisk usage vs thresholds. Current symlink target.
|
|
Active sessions per configured TRANSCODE_SERVERS. Daily log stats (peak this week,
|
|
flip count, session split ramdisk vs SSD).
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🖥️ UNRAID_ESSENTIALS
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
> **stability_watchdog.sh is called by watchdog_orchestrator.sh — not scheduled separately.**
|
|
> **webgui_watchdog.sh, system_tuning_monitor.sh, clear_logs.sh are scheduled below.**
|
|
> **inotify_tuning.sh, php_fpm_max_children.sh, docker_syslog_filter.sh run via array_started.sh.**
|
|
|
|
---
|
|
|
|
### ── webgui_watchdog ───────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: webgui_watchdog
|
|
Schedule: */10 * * * * (every 10 minutes)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Watchdogs/System/webgui_watchdog.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Checks WebGUI responsiveness and recovers it automatically. Silent when healthy —
|
|
runs 144 times per day with no output when the WebGUI is responding normally.
|
|
|
|
**Escalation path (each step only runs if previous failed):**
|
|
```
|
|
1. curl http://localhost → unresponsive for WEBGUI_TIMEOUT (5s)?
|
|
2. Restart nginx → wait 15s → recheck
|
|
3. Restart php-fpm → wait 10s → recheck (handles worker saturation)
|
|
4. Restart emhttp (core daemon) → wait 30s → recheck (most disruptive, last resort)
|
|
5. All failed → notify warning — manual investigation needed
|
|
```
|
|
|
|
A notification fires on any restart so you know what recovered and when.
|
|
|
|
---
|
|
|
|
### ── clear_logs ───────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: clear_logs
|
|
Schedule: 0 5 * * 0 (Sunday 5am — before Sunday maintenance window)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/clear_logs.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Clears system and Docker container logs using size thresholds — only logs large
|
|
enough to be worth clearing.
|
|
|
|
**System logs** (/var/log/syslog, messages, dmesg): cleared only if > LOG_MIN_SIZE_MB (10MB).
|
|
Smaller logs contain useful recent history — not cleared.
|
|
|
|
**Docker container logs**: cleared per-container only if > LOG_DOCKER_MAX_MB (100MB).
|
|
Active containers like Emby and SABnzbd grow fastest. Truncation not rotation —
|
|
`> file` keeps the file descriptor valid while emptying. Safe for running services.
|
|
|
|
---
|
|
|
|
### ── stability_watchdog_status ──────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: stability_watchdog_status
|
|
Schedule: None — run manually
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Watchdogs/stability_watchdog.sh --status
|
|
```
|
|
|
|
**What it shows:**
|
|
All three tiers with current thresholds. Active strike counts per check. RAM tier
|
|
status. Whether mem_shutdown_active is set (RAM emergency in progress). Recent
|
|
watchdog-triggered reboots. All 18 per-host toggle states.
|
|
|
|
---
|
|
|
|
### ── mover_stop ───────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: mover_stop
|
|
Schedule: None — run manually (before array operations needing mover stopped)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/mover_stop.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Stops the unRAID mover cleanly. Wall message warning to all logged-in users. Waits
|
|
MOVER_STOP_TIMEOUT seconds. SIGTERM (allows mover to finish current file — no partial
|
|
files). Waits + verifies. SIGKILL if still running (warns that partial files are possible).
|
|
|
|
---
|
|
|
|
### ── rsync_stop ────────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: rsync_stop
|
|
Schedule: None — run manually (when rsync needs stopping)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/rsync_stop.sh --status
|
|
```
|
|
|
|
**What it does:**
|
|
Stops rsync intelligently. Auto-detects if an orchestrator is running:
|
|
Smart mode (default): kills rsync subprocess only — orchestrator sees rsync died and
|
|
exits cleanly. No orphaned lock files. Containers recover via docker_watchdog.sh.
|
|
`--full-stop`: kills orchestrator first then rsync — use for emergency stop.
|
|
|
|
---
|
|
|
|
### ── user_scripts_stop ────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: user_scripts_stop
|
|
Schedule: None — run manually (before reboots, or when a script hangs)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/user_scripts_stop.sh --status
|
|
```
|
|
|
|
**What it does:**
|
|
Finds all running User Script processes by /tmp/user.scripts path signature. Shows
|
|
script names (not just PIDs — you know what you're stopping). SIGTERM → verify →
|
|
SIGKILL. Self-exclusion prevents the script from killing itself. Called automatically
|
|
by server_reboot.sh before reboot.
|
|
|
|
---
|
|
|
|
### ── server_reboot ────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: unRAID_Essentials
|
|
Name: server_reboot
|
|
Schedule: None — run manually (planned maintenance reboots)
|
|
Background: YES — sequence takes 1-2 minutes
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/server_reboot.sh --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Graceful reboot with full pre-flight and clean shutdown. Wall message + unRAID
|
|
notification with MY_ID. Waits REBOOT_SLEEP (30s). virsh shutdown each running VM
|
|
then waits REBOOT_VM_WAIT for graceful exit. Stops Docker. Stops libvirt. sync.
|
|
/sbin/reboot.
|
|
|
|
Pre-flight warnings (not blocks): rsync running, mover running, active Emby sessions.
|
|
These show in the summary — you chose to reboot, these are context.
|
|
|
|
> Remove `--dry-run` to execute. Dry run walks the full sequence without rebooting —
|
|
> use it to verify what processes are active before committing.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🤝 PARTNERSHIP
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Manages the two-server auth-sharing relationship lifecycle. Automated check runs
|
|
inside critical_sync_maintenance.sh. These entries are for manual operations only.
|
|
|
|
---
|
|
|
|
### ── partnership_status ────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Partnership
|
|
Name: partnership_status
|
|
Schedule: None — run manually
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Partnership/partnership_manage.sh --status
|
|
```
|
|
|
|
**What it shows:**
|
|
Both server state files (ACTIVE/INACTIVE). Offline counter (days since last successful
|
|
sync). Which server is the auth stack owner. Current WebUI redirect state on HOST2.
|
|
Whether CRITICAL_RSYNC_ENABLED is true.
|
|
|
|
---
|
|
|
|
### ── partnership_onboard ──────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Partnership
|
|
Name: partnership_onboard
|
|
Schedule: None — run manually (HOST1/owner only, once at relationship start)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Partnership/partnership_manage.sh --onboard --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Establishes the auth-sharing partnership. Reconfigures HOST2 Docker template WebUI
|
|
URLs to redirect to HOST1 via Tailscale. Verifies routing works. Writes ACTIVE state
|
|
on both servers. Enables Critical-Data sync.
|
|
|
|
> Remove `--dry-run` to run live. Dry run shows exactly which templates would be
|
|
> changed and what URLs they'd become — review before committing.
|
|
|
|
---
|
|
|
|
### ── partnership_offboard ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Partnership
|
|
Name: partnership_offboard
|
|
Schedule: None — run manually (either server, when ending the partnership)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Partnership/partnership_manage.sh --offboard --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Clean partnership separation. Stops rsync. Final sync to HOST2. Reconfigures HOST2
|
|
WebUI URLs back to localhost (HOST2 manages its own auth). Disables critical sync.
|
|
Grace period (PARTNERSHIP_GRACE_HOURS). Removes HOST2 from Tailscale tailnet.
|
|
|
|
Both servers can initiate. If HOST1 is unreachable when HOST2 offboards, deferred
|
|
finalisation completes automatically when HOST1 can next reach HOST2.
|
|
|
|
> Remove `--dry-run` to run live. 10-second countdown shown before any changes.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🔧 TOOLS
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Situational utilities — run when something needs fixing, not on a schedule.
|
|
|
|
---
|
|
|
|
### ── bulk_permissions_repair ─────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Tools
|
|
Name: bulk_permissions_repair
|
|
Schedule: None — run manually
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Tools/bulk_permissions_repair.sh /mnt/user/Movies --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Applies nobody:users 755/664 to a specific path immediately — without waiting for
|
|
the nightly media_shares_permissions.sh run. Use when an admin copy, scp, or bad
|
|
container left root-owned files that are blocking arr operations right now.
|
|
Replace /mnt/user/Movies with the actual path that needs fixing.
|
|
|
|
---
|
|
|
|
### ── container_data_export ────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Tools
|
|
Name: container_data_export
|
|
Schedule: None — run manually (before risky updates or migrations)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Tools/container_data_export.sh \
|
|
Emby /mnt/media-servers/Media_Server/Emby /mnt/user/Backups/
|
|
```
|
|
|
|
**What it does:**
|
|
Stops the container cleanly. Archives the entire appdata directory to a timestamped
|
|
.tar.gz. Verifies archive integrity. Restarts the container (always, even if archiving
|
|
failed). Space check before stopping — won't start if output drive is too small.
|
|
|
|
Replace ContainerName, /path/to/appdata, and /output/dir for each use.
|
|
Output filename: ContainerName_YYYY-MM-DD_HH-MM.tar.gz
|
|
|
|
---
|
|
|
|
### ── emby_database_repair ─────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Tools
|
|
Name: emby_database_repair
|
|
Schedule: None — run manually (after power loss or repeated Emby crashes)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Tools/emby_database_repair.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Stops Emby. Runs SQLite `PRAGMA integrity_check` on every Emby database. Restarts
|
|
Emby. Reports per-database with specific recovery guidance.
|
|
|
|
**Per-database recovery guidance:**
|
|
```
|
|
library.db — CORRUPT → safe to delete, Emby fully rebuilds from media files
|
|
users.db — CORRUPT → deleting resets ALL user accounts + watch history
|
|
check for recent backup (weekly_sync_maintenance.sh)
|
|
authentication.db — CORRUPT → safe to delete, API keys regenerated on restart
|
|
activity.db — CORRUPT → safe to delete, it's a log only
|
|
```
|
|
|
|
**This script checks and reports only** — it does not automatically delete anything.
|
|
Recovery is a human decision based on whether you have backups.
|
|
|
|
---
|
|
|
|
### ── zfs_pool_scrub ────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Tools
|
|
Name: zfs_pool_scrub
|
|
Schedule: None — run manually (monthly or after any disk/power event)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Tools/zfs_pool_scrub.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Triggers ZFS scrub on all pools (except ZFS_REPORT_IGNORE_POOLS), waits for completion,
|
|
notifies with results. ZFS checksums every block and verifies — catches silent data
|
|
corruption before you discover it on reads. Safe to run while system is active.
|
|
For a specific pool: add the pool name as argument (bypasses ignore list).
|
|
|
|
---
|
|
|
|
### ── recreate_shares ──────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Tools
|
|
Name: recreate_shares
|
|
Schedule: None — run manually (after fresh install or disk replacement)
|
|
Background: YES
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/Tools/recreate_shares.sh --dry-run
|
|
```
|
|
|
|
**What it does:**
|
|
Reads every .cfg in /boot/config/shares/, parses the shareInclude disk list, and
|
|
creates /mnt/diskN/sharename on each included disk. Run after restoring share .cfg
|
|
files to a fresh install — shares appear in the UI but directories are missing until
|
|
this creates them. chown nobody:users on creation.
|
|
|
|
---
|
|
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
## 🔀 GIT
|
|
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
---
|
|
|
|
### ── git_pull ─────────────────────────────────────────────────────────────────
|
|
|
|
```
|
|
Category: Git
|
|
Name: git_pull
|
|
Schedule: None — run manually (called automatically by daily_sync_maintenance.sh)
|
|
Background: NO
|
|
```
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
/mnt/user/appdata/Varaverk/unRAID_Essentials/git_pull_execute.sh
|
|
```
|
|
|
|
**What it does:**
|
|
Pulls latest commits from Gitea. Sets execute permission on all .sh files. This is
|
|
the deployment mechanism for the ecosystem — push changes from VS Code to Gitea,
|
|
then run this on both servers to deploy. daily_sync_maintenance.sh runs it
|
|
automatically at 1am as the first job in the window.
|
|
|
|
---
|
|
|
|
## ━━━ AT STARTUP OF ARRAY — ORDER ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
**Only one entry needed at startup:** `array_start`. It handles everything.
|
|
|
|
`array_started.sh` is the single "At Startup of Array" entry. It reads ARRAY_START_SCRIPTS
|
|
from master.conf and launches each in order. No other startup entries. No dragging to
|
|
reorder individual scripts. Change the order by editing master.conf.
|
|
|
|
```
|
|
Correct startup setup:
|
|
1 entry: array_start — At Startup of Array, Background: YES
|
|
|
|
Wrong startup setup (old approach):
|
|
ramdisk_setup — At Startup of Array
|
|
docker_syslog_filter — At Startup of Array
|
|
stability_watchdog — Every Minute via watchdog_orchestrator
|
|
docker_watchdog — At Startup of Array
|
|
failover — At Startup of Array
|
|
(unpredictable order, no coordination)
|
|
```
|
|
|
|
---
|
|
|
|
## ━━━ COMPLETE SCHEDULE REFERENCE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
```
|
|
At Startup of Array:
|
|
array_start BG: YES — single entry, handles everything
|
|
|
|
*/7 * * * * (every 7 min):
|
|
transcode_management BG: YES — cleanup then manager
|
|
|
|
*/30 * * * * (every 30 min):
|
|
critical_sync_maintenance BG: YES — auth stack + Emby dirty sync + partnership
|
|
|
|
0 */6 * * * (every 6 hours):
|
|
arrs_failed_stalled_recovery BG: YES — blocklist + re-search failed imports
|
|
system_tuning_monitor BG: YES — inotify + php-fpm snapshot
|
|
|
|
0 1 * * * (1am daily):
|
|
daily_sync_maintenance BG: YES — full nightly window
|
|
|
|
0 5 * * 0 (Sunday 5am):
|
|
clear_logs BG: YES — size-threshold log cleanup
|
|
|
|
0 6 * * 0 (Sunday 6am):
|
|
zfs_memory_snapshot BG: YES — ZFS + memory report
|
|
|
|
0 7 * * 0 (Sunday 7am):
|
|
sunday_morning_coffee_report BG: YES — full weekly digest
|
|
|
|
0 8 * * * (8am daily):
|
|
weekly_health_digest BG: YES — profile-controlled notification
|
|
|
|
0 7 * * 0 (Sunday 7am):
|
|
smart_health BG: YES — SMART attribute check
|
|
|
|
0 9 * * 0 (Sunday 9am):
|
|
cert_monitor BG: YES — live TLS cert expiry check
|
|
|
|
0 10 * * 0 (Sunday 10am):
|
|
backup_verify BG: YES — MD5 checksum mirror verification
|
|
|
|
0 11 * * 0 (Sunday 11am):
|
|
emby_session_report BG: YES — Emby weekly usage stats
|
|
bandwidth_monitor_report BG: YES — rsync transfer summary
|
|
|
|
30 2 * * 0 (Sunday 2:30am):
|
|
weekly_sync_maintenance BG: YES — clean sync + image updates
|
|
```
|
|
|
|
---
|
|
|
|
## ━━━ AFTER CREATING ALL ENTRIES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Run each of these once manually before relying on scheduled runs:
|
|
|
|
```
|
|
array_start --dry-run verify all startup scripts found and sequenced correctly
|
|
transcode_management --status confirm ramdisk mounted and symlink pointing at ramdisk
|
|
critical_sync_maintenance verify Critical-Data sync completes to HOST2
|
|
daily_sync_maintenance --dry-run verify remote connectivity and share list
|
|
failover_status confirm NORMAL state on both servers
|
|
docker_watchdog_status confirm required containers all running
|
|
stability_watchdog_status confirm no threshold alerts on first check
|
|
``` |