rename appdata-Failover→appdata-Fallback in docs; critical sync 15→30min; transcode 3→7min

appdata-Failover → appdata-Fallback:
  All .md files updated — scripts and confs already used appdata-Fallback.
  Share was renamed; docs were the only stale references.

critical_sync_maintenance.sh: */15 → */30, 96/day → 48/day:
  critical_sync_maintenance.sh header, master.conf, host1/2.conf comments,
  Orchestrators README, User Script Plug-in README, Partnership README/manual/script,
  Docker_Essentials README/downloaders_reset.sh, Fallback README,
  weekly_sync_maintenance.sh, user_script_plug-in.sh all updated.

rsync_emby_failover User Script superseded:
  Emby dirty sync was already in HOST1_CRITICAL_SYNC_SHARES — it now runs inside
  critical_sync_maintenance.sh every 30min alongside auth sync and partnership check.
  Section in User Script Plug-in README marked for deletion from plugin.

transcode_management.sh: */3 → */7:
  transcode_management.sh, transcode_manager.sh, transcode_cleanup.sh headers,
  Transcodes README/manual, Orchestrators README, User Script Plug-in README,
  user_script_plug-in.sh all updated.
This commit is contained in:
Gmer4Lfe
2026-05-22 22:22:21 -04:00
parent 2d0c91ea13
commit ee086f309e
22 changed files with 129 additions and 156 deletions
+3 -3
View File
@@ -23,7 +23,7 @@
# ── RSYNC ────────────────────────────────────────────────────────────────────────────────── # ── RSYNC ──────────────────────────────────────────────────────────────────────────────────
# DAILY SYNC SHARES media shares HOST1 owns and pushes to HOST2 # DAILY SYNC SHARES media shares HOST1 owns and pushes to HOST2
# WEEKLY SYNC SHARES appdata shares synced weekly (Sunday 2:30am) # WEEKLY SYNC SHARES appdata shares synced weekly (Sunday 2:30am)
# CRITICAL SYNC SHARES appdata shares synced every 15 minutes # CRITICAL SYNC SHARES appdata shares synced every 30 minutes
# BACKUP VERIFY shares for checksum verification against remote # BACKUP VERIFY shares for checksum verification against remote
# HOST1 RSYNC PROFILE host1-appdata profile for HOST1-specific appdata syncs # HOST1 RSYNC PROFILE host1-appdata profile for HOST1-specific appdata syncs
# #
@@ -221,7 +221,7 @@
) )
# ━━━ Critical Sync Shares ━━━ # ━━━ Critical Sync Shares ━━━
# Appdata shares synced every 15 minutes by critical_sync_maintenance.sh. # Appdata shares synced every 30 minutes by critical_sync_maintenance.sh.
# Format: "/path/to/share" or "/path/to/share|profile-name" # Format: "/path/to/share" or "/path/to/share|profile-name"
# Order matters — Critical-Data first (auth stack), then Emby dirty sync. # Order matters — Critical-Data first (auth stack), then Emby dirty sync.
HOST1_CRITICAL_SYNC_SHARES=( HOST1_CRITICAL_SYNC_SHARES=(
@@ -558,7 +558,7 @@
# Add one entry per root folder in arr Settings → Media Management → Root Folders. # Add one entry per root folder in arr Settings → Media Management → Root Folders.
# ━━━ Downloaders ━━━ # ━━━ Downloaders ━━━
# Used by downloaders_reset.sh — runs every 15min via CRITICAL_MAINTENANCE_SCRIPTS. # Used by downloaders_reset.sh — runs every 30min via CRITICAL_MAINTENANCE_SCRIPTS.
# Clears stuck states, purges old history, prepares each client for a clean cycle. # Clears stuck states, purges old history, prepares each client for a clean cycle.
# slskd — clears stuck searches, dead transfers, purges expired failed imports. # slskd — clears stuck searches, dead transfers, purges expired failed imports.
+2 -2
View File
@@ -27,7 +27,7 @@
# ── RSYNC ────────────────────────────────────────────────────────────────────────────────── # ── RSYNC ──────────────────────────────────────────────────────────────────────────────────
# DAILY SYNC SHARES media shares HOST2 owns and pushes to HOST1 # DAILY SYNC SHARES media shares HOST2 owns and pushes to HOST1
# WEEKLY SYNC SHARES appdata shares synced weekly (Sunday 2:30am) # WEEKLY SYNC SHARES appdata shares synced weekly (Sunday 2:30am)
# CRITICAL SYNC SHARES appdata shares synced every 15 minutes # CRITICAL SYNC SHARES appdata shares synced every 30 minutes
# BACKUP VERIFY shares for checksum verification against remote # BACKUP VERIFY shares for checksum verification against remote
# HOST2 RSYNC PROFILE host2-appdata profile for HOST2-specific appdata syncs # HOST2 RSYNC PROFILE host2-appdata profile for HOST2-specific appdata syncs
# #
@@ -204,7 +204,7 @@
) )
# ━━━ Critical Sync Shares ━━━ # ━━━ Critical Sync Shares ━━━
# Appdata shares synced every 15 minutes by critical_sync_maintenance.sh. # Appdata shares synced every 30 minutes by critical_sync_maintenance.sh.
# Format: "/path/to/share" or "/path/to/share|profile-name" # Format: "/path/to/share" or "/path/to/share|profile-name"
HOST2_CRITICAL_SYNC_SHARES=( HOST2_CRITICAL_SYNC_SHARES=(
# fill in when HOST2 is back online # fill in when HOST2 is back online
+9 -9
View File
@@ -40,7 +40,7 @@
# MONTHLY MAINTENANCE Uptime-triggered heavy tasks — ZFS scrub, SMART tests (monthly_maintenance.sh) # MONTHLY MAINTENANCE Uptime-triggered heavy tasks — ZFS scrub, SMART tests (monthly_maintenance.sh)
# DAILY SYNC MAINTENANCE Job list + media shares (daily_sync_maintenance.sh) # DAILY SYNC MAINTENANCE Job list + media shares (daily_sync_maintenance.sh)
# WEEKLY SYNC MAINTENANCE Job list + sync shares + update toggles (weekly_sync_maintenance.sh) # WEEKLY SYNC MAINTENANCE Job list + sync shares + update toggles (weekly_sync_maintenance.sh)
# CRITICAL SYNC MAINTENANCE 15-minute jobs + sync shares + partnership check (critical_sync_maintenance.sh) # CRITICAL SYNC MAINTENANCE 30-minute jobs + sync shares + partnership check (critical_sync_maintenance.sh)
# #
# ── RSYNC ────────────────────────────────────────────────────────────────────────────────── # ── RSYNC ──────────────────────────────────────────────────────────────────────────────────
# RSYNC ENABLE/DISABLE Two-tier toggle system — global gate + per-orchestrator # RSYNC ENABLE/DISABLE Two-tier toggle system — global gate + per-orchestrator
@@ -154,7 +154,7 @@
# /boot/config/partnership_HOST2.db ← HOST2 writes only # /boot/config/partnership_HOST2.db ← HOST2 writes only
# Propagated via SSH — no rsync needed # Propagated via SSH — no rsync needed
# #
# critical_sync_maintenance.sh runs --check every 15min: # critical_sync_maintenance.sh runs --check every 30min:
# Reads both state files via SSH # Reads both state files via SSH
# Detects offboard requests → finalises from owner side # Detects offboard requests → finalises from owner side
# Increments offline counter → auto-offboards after threshold # Increments offline counter → auto-offboards after threshold
@@ -330,15 +330,15 @@
MONTHLY_LAST_RUN_FILE="/boot/config/monthly_maintenance_last_run.db" MONTHLY_LAST_RUN_FILE="/boot/config/monthly_maintenance_last_run.db"
# ━━━ Critical Sync Maintenance ━━━ # ━━━ Critical Sync Maintenance ━━━
# critical_sync_maintenance.sh runs every 15 minutes. # critical_sync_maintenance.sh runs every 30 minutes.
# Order: CRITICAL_MAINTENANCE_SCRIPTS (jobs) → CRITICAL_SYNC_SHARES (rsync) → partnership --check # Order: CRITICAL_MAINTENANCE_SCRIPTS (jobs) → CRITICAL_SYNC_SHARES (rsync) → partnership --check
# partnership --check always runs last regardless of rsync gate. # partnership --check always runs last regardless of rsync gate.
# Comment out entries to disable without removing. # Comment out entries to disable without removing.
CRITICAL_MAINTENANCE_SCRIPTS=( CRITICAL_MAINTENANCE_SCRIPTS=(
"Docker_Essentials/downloaders_reset.sh" # clear stuck download states every 15min "Docker_Essentials/downloaders_reset.sh" # clear stuck download states every 30min
) )
# Shares synced every 15 minutes — defined per host in host*.conf. # Shares synced every 30 minutes — defined per host in host*.conf.
# HOST1_CRITICAL_SYNC_SHARES / HOST2_CRITICAL_SYNC_SHARES # HOST1_CRITICAL_SYNC_SHARES / HOST2_CRITICAL_SYNC_SHARES
# Format: "/path/to/share" or "/path/to/share|profile-name" # Format: "/path/to/share" or "/path/to/share|profile-name"
# Order matters — Critical-Data first (auth stack), then Emby dirty sync. # Order matters — Critical-Data first (auth stack), then Emby dirty sync.
@@ -442,7 +442,7 @@
# RSYNC_ENABLED=true ← rsync works, individual scripts run fine # RSYNC_ENABLED=true ← rsync works, individual scripts run fine
# DAILY_RSYNC_ENABLED=false ← skip daily HDD syncs during rebuild # DAILY_RSYNC_ENABLED=false ← skip daily HDD syncs during rebuild
# WEEKLY_RSYNC_ENABLED=true ← Emby + Critical-Data still sync (NVMe) # WEEKLY_RSYNC_ENABLED=true ← Emby + Critical-Data still sync (NVMe)
# CRITICAL_RSYNC_ENABLED=true ← 15min auth stack sync still runs # CRITICAL_RSYNC_ENABLED=true ← 30min auth stack sync still runs
# FALLBACK_RSYNC_ENABLED=true ← handback writeback still works # FALLBACK_RSYNC_ENABLED=true ← handback writeback still works
# → Run individual: bash Rsync/rsync.sh /mnt/user/Movies # → Run individual: bash Rsync/rsync.sh /mnt/user/Movies
# → When ready: DAILY_RSYNC_ENABLED=true # → When ready: DAILY_RSYNC_ENABLED=true
@@ -493,14 +493,14 @@
# critical-data — auth stack — full stop both sides, Authelia delayed start # critical-data — auth stack — full stop both sides, Authelia delayed start
# called by weekly_sync_maintenance.sh — full clean sync weekly # called by weekly_sync_maintenance.sh — full clean sync weekly
# critical-fallback — dirty sync — auth stays running both sides, WAL excluded # critical-fallback — dirty sync — auth stays running both sides, WAL excluded
# called by critical_sync_maintenance.sh every 15min # called by critical_sync_maintenance.sh every 30min
# host1-appdata — HOST1 server-specific appdata — defined in host1.conf # host1-appdata — HOST1 server-specific appdata — defined in host1.conf
# host2-appdata — HOST2 server-specific appdata — defined in host2.conf # host2-appdata — HOST2 server-specific appdata — defined in host2.conf
# important-data — NextCloud + Postgres — NextCloud delayed start after Postgres # important-data — NextCloud + Postgres — NextCloud delayed start after Postgres
# emby — weekly clean sync — both Emby stopped, full mirror # emby — weekly clean sync — both Emby stopped, full mirror
# called by weekly_sync_maintenance.sh only — do NOT schedule separately # called by weekly_sync_maintenance.sh only — do NOT schedule separately
# emby-fallback — dirty sync — Emby stays running, WAL excluded # emby-fallback — dirty sync — Emby stays running, WAL excluded
# called by critical_sync_maintenance.sh every 15min # called by critical_sync_maintenance.sh every 30min
declare -A PROFILE_RSYNC_OPTS=( declare -A PROFILE_RSYNC_OPTS=(
[arrs_stack]="-av --info=progress2 --human-readable --bwlimit=$BW_LIMIT --delete --inplace" [arrs_stack]="-av --info=progress2 --human-readable --bwlimit=$BW_LIMIT --delete --inplace"
@@ -632,7 +632,7 @@
# ============================================================================================== # ==============================================================================================
# ━━━ Downloaders Reset ━━━ # ━━━ Downloaders Reset ━━━
# Runs every 15 minutes via CRITICAL_MAINTENANCE_SCRIPTS. # Runs every 30 minutes via CRITICAL_MAINTENANCE_SCRIPTS.
# Clears stuck states, purges old history, prepares each download client for a clean cycle. # Clears stuck states, purges old history, prepares each download client for a clean cycle.
# Per-host URLs and API keys live in host*.conf. # Per-host URLs and API keys live in host*.conf.
DOWNLOADER_RETENTION_DAYS=7 # days — purge history older than this DOWNLOADER_RETENTION_DAYS=7 # days — purge history older than this
@@ -197,7 +197,7 @@ array start. Silent when everything is correct. Notifies when it has to create s
### 🧹 Downloader Hygiene — `downloaders_reset.sh` ### 🧹 Downloader Hygiene — `downloaders_reset.sh`
Maintenance reset for all download clients (slskd, SABnzbd, qBittorrent) every 15 Maintenance reset for all download clients (slskd, SABnzbd, qBittorrent) every 30
minutes. Clears stuck searches, dead transfers, failed imports, and stale queue entries minutes. Clears stuck searches, dead transfers, failed imports, and stale queue entries
that download clients accumulate but never clean up themselves. Never touches active that download clients accumulate but never clean up themselves. Never touches active
or in-progress downloads. or in-progress downloads.
@@ -233,7 +233,7 @@ full coordination model between all four watchdogs.
| `docker_update_remaining.sh` | Image update + prune for all containers not in managed lists | End of weekly maintenance window | | `docker_update_remaining.sh` | Image update + prune for all containers not in managed lists | End of weekly maintenance window |
| `docker_network_connect.sh` | Network existence + container connection enforcement | Every array start | | `docker_network_connect.sh` | Network existence + container connection enforcement | Every array start |
| `docker_container_stop.sh` | Ordered container shutdown — graceful then forced | Called by `array_stopping.sh` | | `docker_container_stop.sh` | Ordered container shutdown — graceful then forced | Called by `array_stopping.sh` |
| `downloaders_reset.sh` | Download client hygiene — slskd / SABnzbd / qBittorrent | Every 15min via `critical_sync_maintenance.sh` | | `downloaders_reset.sh` | Download client hygiene — slskd / SABnzbd / qBittorrent | Every 30min via `critical_sync_maintenance.sh` |
> `watchdog_skip_list_manager.sh` — manual recovery tool for the skip list. Lives in `Tools/` because it's an operator utility, not a lifecycle script. > `watchdog_skip_list_manager.sh` — manual recovery tool for the skip list. Lives in `Tools/` because it's an operator utility, not a lifecycle script.
@@ -262,7 +262,7 @@ Weekly maintenance window (2:30am Sunday):
├── docker_update.sh --remainder ─ update containers not in managed lists ├── docker_update.sh --remainder ─ update containers not in managed lists
└── docker_update_remaining.sh ── prune dangling images └── docker_update_remaining.sh ── prune dangling images
Critical maintenance window (every 15min): Critical maintenance window (every 30min):
critical_sync_maintenance.sh critical_sync_maintenance.sh
└── downloaders_reset.sh ──────── clear stuck downloads / stale queue entries └── downloaders_reset.sh ──────── clear stuck downloads / stale queue entries
+2 -2
View File
@@ -9,7 +9,7 @@
# state that download clients generate but never clean up themselves — stuck # state that download clients generate but never clean up themselves — stuck
# searches, dead transfers, failed imports, stale queue entries, completed history. # searches, dead transfers, failed imports, stale queue entries, completed history.
# #
# Called every 15 minutes by critical_sync_maintenance.sh via # Called every 30 minutes by critical_sync_maintenance.sh via
# CRITICAL_MAINTENANCE_SCRIPTS. Can also be run manually for ad hoc cleanup. # CRITICAL_MAINTENANCE_SCRIPTS. Can also be run manually for ad hoc cleanup.
# If a downloader is not configured for this host, that section skips cleanly. # If a downloader is not configured for this host, that section skips cleanly.
# #
@@ -137,7 +137,7 @@ if [[ "$EUID" -ne 0 ]]; then
exit 1 exit 1
fi fi
# Lock first — wait mode since this runs every 15min and previous may still be finishing # Lock first — wait mode since this runs every 30min and previous may still be finishing
acquire_lock "wait" acquire_lock "wait"
# detect_hosts() sets MY_ID and aliases all HOST*_SLSKD_*, HOST*_SABNZBD_*, HOST*_QBIT_* vars # detect_hosts() sets MY_ID and aliases all HOST*_SLSKD_*, HOST*_SABNZBD_*, HOST*_QBIT_* vars
+7 -7
View File
@@ -242,16 +242,16 @@ HOST1_TIER1_WRITEBACK_DELAY=60
# Writeback paths — synced back to HOST1 on handback # Writeback paths — synced back to HOST1 on handback
FALLBACK_HOST1_WRITEBACK_TIER1=( FALLBACK_HOST1_WRITEBACK_TIER1=(
"/mnt/user/appdata-Failover/Critical-Data" # auth stack — Authelia + NPM + certs "/mnt/user/appdata-Fallback/Critical-Data" # auth stack — Authelia + NPM + certs
"/mnt/user/Media_Server/Emby" # Emby userdata — watch history, playstates "/mnt/user/Media_Server/Emby" # Emby userdata — watch history, playstates
) )
FALLBACK_HOST1_WRITEBACK_TIER2=( FALLBACK_HOST1_WRITEBACK_TIER2=(
"/mnt/user/appdata-Failover/Important-Data" # NextCloud + Postgres + Immich "/mnt/user/appdata-Fallback/Important-Data" # NextCloud + Postgres + Immich
) )
FALLBACK_HOST1_WRITEBACK_TIER3=( FALLBACK_HOST1_WRITEBACK_TIER3=(
"/mnt/user/appdata-Failover/Gmer4Lfe" # secondary appdata accumulated changes "/mnt/user/appdata-Fallback/Gmer4Lfe" # secondary appdata accumulated changes
) )
# Tier 4 writeback uses HOST1_DAILY_SYNC_SHARES automatically — no list needed here. # Tier 4 writeback uses HOST1_DAILY_SYNC_SHARES automatically — no list needed here.
@@ -355,15 +355,15 @@ ssh root@[HOST2-tailscale-ip] "docker inspect Emby --format '{{.State.Status}}'"
These shares must exist on HOST2 with current data from HOST1 before failover is needed: These shares must exist on HOST2 with current data from HOST1 before failover is needed:
``` ```
/mnt/user/appdata-Failover/Critical-Data # auth stack — NPM, LLDAP, Authelia, certs /mnt/user/appdata-Fallback/Critical-Data # auth stack — NPM, LLDAP, Authelia, certs
/mnt/user/appdata-Failover/Important-Data # NextCloud + Postgres + Immich /mnt/user/appdata-Fallback/Important-Data # NextCloud + Postgres + Immich
/mnt/user/Media_Server/Emby # Emby userdata — watch history, playstates /mnt/user/Media_Server/Emby # Emby userdata — watch history, playstates
/mnt/user/appdata-Failover/Gmer4Lfe # server appdata /mnt/user/appdata-Fallback/Gmer4Lfe # server appdata
``` ```
```bash ```bash
# Verify data is current — check modification times # Verify data is current — check modification times
ssh root@[HOST2-tailscale-ip] "ls -la /mnt/user/appdata-Failover/Critical-Data/" ssh root@[HOST2-tailscale-ip] "ls -la /mnt/user/appdata-Fallback/Critical-Data/"
``` ```
Sync is maintained continuously by `daily_sync_maintenance.sh` critical-data profile. Sync is maintained continuously by `daily_sync_maintenance.sh` critical-data profile.
+1 -1
View File
@@ -102,7 +102,7 @@ know the full library — arr_sync kept them in union while both servers were on
NPM, LLDAP, and Authelia run actively on both servers at all times. HOST2 needs them running NPM, LLDAP, and Authelia run actively on both servers at all times. HOST2 needs them running
to serve his own users daily — this is not a fallback-only configuration. HOST1 is source of to serve his own users daily — this is not a fallback-only configuration. HOST1 is source of
truth: all changes mirror to HOST2 every 15 minutes via critical sync. truth: all changes mirror to HOST2 every 30 minutes via critical sync.
When DNS cuts over, auth is already running on the covering server. The 30-60 second dead When DNS cuts over, auth is already running on the covering server. The 30-60 second dead
zone where auth is coming up after DNS has already switched does not exist. zone where auth is coming up after DNS has already switched does not exist.
+14 -14
View File
@@ -49,7 +49,7 @@ tells you which job and what happened — no correlation needed.
### 🔴 Transcode Manager Triggering Unnecessary SSD Flips ### 🔴 Transcode Manager Triggering Unnecessary SSD Flips
`transcode_manager.sh` ran every 3 minutes on its own. It checked ramdisk usage — `transcode_manager.sh` ran every 7 minutes on its own. It checked ramdisk usage —
saw 6.8GB used, threshold is 6.5GB, flipped sessions to SSD. One minute later saw 6.8GB used, threshold is 6.5GB, flipped sessions to SSD. One minute later
`transcode_cleanup.sh` ran and removed 4GB of stale segment files from ended sessions. `transcode_cleanup.sh` ran and removed 4GB of stale segment files from ended sessions.
Actual usage was 2.8GB. Sessions were now on SSD for no reason. Users experiencing Actual usage was 2.8GB. Sessions were now on SSD for no reason. Users experiencing
@@ -102,14 +102,14 @@ The User Scripts plugin contains exactly these entries:
array_started.sh array_started.sh
# Cron — one entry per maintenance window: # Cron — one entry per maintenance window:
*/3 * * * * transcode_management.sh */7 * * * * transcode_management.sh
0 */6 * * * arrs_failed_stalled_recovery.sh 0 */6 * * * arrs_failed_stalled_recovery.sh
*/30 * * * * rsync.sh emby-fallback ← not an orchestrator, direct call */30 * * * * critical_sync_maintenance.sh ← auth + Emby dirty sync + partnership
0 1 * * * daily_sync_maintenance.sh 0 1 * * * daily_sync_maintenance.sh
30 2 * * 0 weekly_sync_maintenance.sh 30 2 * * 0 weekly_sync_maintenance.sh
# Manual only (not scheduled): # Manual only (not scheduled):
failover_test.sh, emby_database_repair.sh, repair tools fallback_test.sh, emby_database_repair.sh, repair tools
``` ```
Every job list is configured in the `ORCHESTRATORS` section of `master.conf`. Every job list is configured in the `ORCHESTRATORS` section of `master.conf`.
@@ -168,7 +168,7 @@ without `--log`.
|--------|---------------------|----------| |--------|---------------------|----------|
| `array_started.sh` | All array startup scripts in order | At Startup of Array | | `array_started.sh` | All array startup scripts in order | At Startup of Array |
| `watchdog_orchestrator.sh` | resource → docker → system → stability watchdogs | Every minute | | `watchdog_orchestrator.sh` | resource → docker → system → stability watchdogs | Every minute |
| `transcode_management.sh` | Cleanup then manager — order critical | Every 3 minutes | | `transcode_management.sh` | Cleanup then manager — order critical | Every 7 minutes |
| `arrs_failed_stalled_recovery.sh` | Failed import + stalled download recovery | Every 6 hours | | `arrs_failed_stalled_recovery.sh` | Failed import + stalled download recovery | Every 6 hours |
| `daily_sync_maintenance.sh` | git pull → sync → media maintenance → restarts | 1am daily | | `daily_sync_maintenance.sh` | git pull → sync → media maintenance → restarts | 1am daily |
| `weekly_sync_maintenance.sh` | Stop → update → clean sync → start → weekly restarts | 2:30am Sunday | | `weekly_sync_maintenance.sh` | Stop → update → clean sync → start → weekly restarts | 2:30am Sunday |
@@ -292,11 +292,11 @@ array_started.sh --status
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Runs `transcode_cleanup.sh` then `transcode_manager.sh` in the correct order every Runs `transcode_cleanup.sh` then `transcode_manager.sh` in the correct order every
3 minutes. Exists because the order is not optional — the manager must always see 7 minutes. Exists because the order is not optional — the manager must always see
post-cleanup usage to make accurate flip decisions. post-cleanup usage to make accurate flip decisions.
```bash ```bash
# Scheduled: */3 * * * * (every 3 minutes) # Scheduled: */7 * * * * (every 7 minutes)
``` ```
--- ---
@@ -371,7 +371,7 @@ post-cleanup usage to make accurate flip decisions.
### ── Usage ─────────────────────────────────────────────────────────────────── ### ── Usage ───────────────────────────────────────────────────────────────────
```bash ```bash
transcode_management.sh # normal run (every 3 min via cron) transcode_management.sh # normal run (every 7 min via cron)
transcode_management.sh --dry-run # passes --dry-run to both child scripts transcode_management.sh --dry-run # passes --dry-run to both child scripts
transcode_management.sh --status # show config, current state, daily log stats transcode_management.sh --status # show config, current state, daily log stats
transcode_management.sh --log # verbose output from both child scripts transcode_management.sh --log # verbose output from both child scripts
@@ -730,7 +730,7 @@ maintenance block before the 7am coffee report.
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Two Emby syncs run in parallel — dirty and clean: # Two Emby syncs run in parallel — dirty and clean:
# #
# emby-fallback dirty sync (every 30 minutes, Emby running): # emby-fallback dirty sync (every 30 minutes via critical_sync_maintenance.sh, Emby running):
# watch states, library deltas, user activity — continuous coverage # watch states, library deltas, user activity — continuous coverage
# WAL files excluded — safe to copy while Emby writes # WAL files excluded — safe to copy while Emby writes
# HOST2 always within 30 minutes of HOST1 on playback state # HOST2 always within 30 minutes of HOST1 on playback state
@@ -814,7 +814,7 @@ maintenance block before the 7am coffee report.
# master.conf # master.conf
WEEKLY_SYNC_SHARES=( WEEKLY_SYNC_SHARES=(
"/mnt/user/Media_Server/Emby" # emby profile — full clean mirror "/mnt/user/Media_Server/Emby" # emby profile — full clean mirror
"/mnt/user/appdata-Failover/Critical-Data" # critical-data — auth stack clean state "/mnt/user/appdata-Fallback/Critical-Data" # critical-data — auth stack clean state
) )
WEEKLY_MAINTENANCE_SCRIPTS=( WEEKLY_MAINTENANCE_SCRIPTS=(
@@ -943,14 +943,14 @@ media_management.sh --status # show configured job list and exit
array_started.sh array_started.sh
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Frequent — every 3 minutes: # Frequent — every 7 minutes:
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
*/3 * * * * transcode_management.sh */7 * * * * transcode_management.sh
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Periodic — not an orchestrator, direct rsync call: # Every 30 minutes — auth stack + Emby dirty sync + partnership check:
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
*/30 * * * * rsync.sh /mnt/user/Media_Server/Emby --profile=emby-fallback */30 * * * * critical_sync_maintenance.sh
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Every 6 hours: # Every 6 hours:
+8 -8
View File
@@ -2,9 +2,9 @@
# ============================================================================================== # ==============================================================================================
# ============================= Critical Sync Maintenance ====================================== # ============================= Critical Sync Maintenance ======================================
# ============================================================================================== # ==============================================================================================
# Orchestrator for time-sensitive syncs that run every 15 minutes. # Orchestrator for time-sensitive syncs that run every 30 minutes.
# Keeps the mirror current between the less frequent daily and weekly windows. # Keeps the mirror current between the less frequent daily and weekly windows.
# Schedule: */15 * * * * (every 15 minutes via User Scripts plugin) # Schedule: */30 * * * * (every 30 minutes via User Scripts plugin)
# #
# ── EXECUTION ORDER ─────────────────────────────────────────────────────────────────────────── # ── EXECUTION ORDER ───────────────────────────────────────────────────────────────────────────
# 1. Critical-Data rsync — auth stack, NPM config, certs (containers stopped both sides) # 1. Critical-Data rsync — auth stack, NPM config, certs (containers stopped both sides)
@@ -12,8 +12,8 @@
# 3. CRITICAL_MAINTENANCE_SCRIPTS — any scripts configured for critical window # 3. CRITICAL_MAINTENANCE_SCRIPTS — any scripts configured for critical window
# 4. partnership --check — read both state files, detect changes, act accordingly # 4. partnership --check — read both state files, detect changes, act accordingly
# #
# ── WHY EVERY 15 MINUTES ────────────────────────────────────────────────────────────────────── # ── WHY EVERY 30 MINUTES ──────────────────────────────────────────────────────────────────────
# Auth stack changes (new users, proxy rules, certs) propagate within 15min ✅ # Auth stack changes (new users, proxy rules, certs) propagate within 30min ✅
# Emby watch states stay in sync — mirror users see correct playback position ✅ # Emby watch states stay in sync — mirror users see correct playback position ✅
# Partnership state changes detected and acted on quickly ✅ # Partnership state changes detected and acted on quickly ✅
# Lock prevents: daily rsync doing Critical-Data mid-critical window ✅ # Lock prevents: daily rsync doing Critical-Data mid-critical window ✅
@@ -24,17 +24,17 @@
# partnership --check always runs regardless — state check doesn't need rsync # partnership --check always runs regardless — state check doesn't need rsync
# #
# ── LOCK BEHAVIOUR ──────────────────────────────────────────────────────────────────────────── # ── LOCK BEHAVIOUR ────────────────────────────────────────────────────────────────────────────
# acquire_lock "strict" — if previous 15min run still going, skip this cycle entirely # acquire_lock "strict" — if previous 30min run still going, skip this cycle entirely
# Critical-Data taking > 15min is a problem worth knowing about # Critical-Data taking > 30min is a problem worth knowing about
# Strict mode prevents pile-up without waiting — log and move on ✅ # Strict mode prevents pile-up without waiting — log and move on ✅
# #
# ── SILENT WHEN HEALTHY ─────────────────────────────────────────────────────────────────────── # ── SILENT WHEN HEALTHY ───────────────────────────────────────────────────────────────────────
# Runs 96 times per day — clean runs must produce zero output ✅ # Runs 48 times per day — clean runs must produce zero output ✅
# Only failures and notable events produce visible output # Only failures and notable events produce visible output
# #
# ── CONFIGURATION (master.conf) ─────────────────────────────────────────────────────────────── # ── CONFIGURATION (master.conf) ───────────────────────────────────────────────────────────────
# CRITICAL_RSYNC_ENABLED — enable/disable rsync section # CRITICAL_RSYNC_ENABLED — enable/disable rsync section
# CRITICAL_SYNC_SHARES — shares synced every 15min (HOST*_CRITICAL_SYNC_SHARES) # CRITICAL_SYNC_SHARES — shares synced every 30min (HOST*_CRITICAL_SYNC_SHARES)
# CRITICAL_MAINTENANCE_SCRIPTS — scripts run in critical window (optional) # CRITICAL_MAINTENANCE_SCRIPTS — scripts run in critical window (optional)
# PARTNERSHIP_ENABLED — enable/disable partnership check # PARTNERSHIP_ENABLED — enable/disable partnership check
# #
+3 -3
View File
@@ -4,7 +4,7 @@
# ============================================================================================== # ==============================================================================================
# Orchestrator — runs transcode_cleanup.sh then transcode_manager.sh in the correct order. # Orchestrator — runs transcode_cleanup.sh then transcode_manager.sh in the correct order.
# Replace individual transcode_manager and transcode_cleanup cron entries with this. # Replace individual transcode_manager and transcode_cleanup cron entries with this.
# Schedule: */3 * * * * (every 3 minutes via User Scripts plugin) # Schedule: */7 * * * * (every 7 minutes via User Scripts plugin)
# #
# ── WHY CLEANUP BEFORE MANAGER ──────────────────────────────────────────────────────────────── # ── WHY CLEANUP BEFORE MANAGER ────────────────────────────────────────────────────────────────
# Cleanup runs first — removes stale segment files from ended sessions. # Cleanup runs first — removes stale segment files from ended sessions.
@@ -47,7 +47,7 @@
# All TRANSCODE_* threshold vars — see master.conf Transcode Manager section # All TRANSCODE_* threshold vars — see master.conf Transcode Manager section
# #
# ── USAGE ───────────────────────────────────────────────────────────────────────────────────── # ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
# transcode_management.sh — normal run (every 3 minutes via cron) # transcode_management.sh — normal run (every 7 minutes via cron)
# transcode_management.sh --dry-run — preview without changes (passed to children) # transcode_management.sh --dry-run — preview without changes (passed to children)
# transcode_management.sh --status — show configuration and current state # transcode_management.sh --status — show configuration and current state
# transcode_management.sh --log — verbose output from both child scripts # transcode_management.sh --log — verbose output from both child scripts
@@ -92,7 +92,7 @@ if [[ "$SHOW_STATUS" == true ]]; then
echo "$ICON_RAM Ramdisk: $RAMDISK_PATH ($RAMDISK_SIZE)" echo "$ICON_RAM Ramdisk: $RAMDISK_PATH ($RAMDISK_SIZE)"
echo "$ICON_DISK SSD fallback: $TRANSCODE_SSD" echo "$ICON_DISK SSD fallback: $TRANSCODE_SSD"
echo "$ICON_LINK Symlink: $TRANSCODE_LINK" echo "$ICON_LINK Symlink: $TRANSCODE_LINK"
echo "$ICON_TIME Schedule: every 3 minutes" echo "$ICON_TIME Schedule: every 7 minutes"
echo "" echo ""
echo "━━━ Child Scripts ━━━" echo "━━━ Child Scripts ━━━"
[[ -f "$CLEANUP_SCRIPT" ]] && \ [[ -f "$CLEANUP_SCRIPT" ]] && \
+1 -1
View File
@@ -20,7 +20,7 @@
# Emby builds a warm image cache on HOST2 throughout the week. # Emby builds a warm image cache on HOST2 throughout the week.
# Syncing nightly resets cache — cold loads every morning for users. # Syncing nightly resets cache — cold loads every morning for users.
# Weekly sync: cache stays warm 6 days, resets Sunday night while users sleep. # Weekly sync: cache stays warm 6 days, resets Sunday night while users sleep.
# emby-fallback dirty sync covers watch states + library every 15min between weekly syncs. # emby-fallback dirty sync covers watch states + library every 30min between weekly syncs.
# #
# ── CONTAINER UPDATES ───────────────────────────────────────────────────────────────────────── # ── CONTAINER UPDATES ─────────────────────────────────────────────────────────────────────────
# Containers already stopped for sync — updates pull at zero extra downtime. # Containers already stopped for sync — updates pull at zero extra downtime.
+4 -4
View File
@@ -18,20 +18,20 @@ NPM proxy rules NPM serving mirror's domain
LLDAP users LLDAP — same users LLDAP users LLDAP — same users
Authelia policies Authelia — same policies Authelia policies Authelia — same policies
Certs Certs — mirrored, valid Certs Certs — mirrored, valid
Emby Emby — dirty-synced every 15min Emby Emby — dirty-synced every 30min
Changes made here ──→ Propagated every 15 minutes Changes made here ──→ Propagated every 30 minutes
WebUI management ──→ Redirected to HOST1 via Tailscale WebUI management ──→ Redirected to HOST1 via Tailscale
Config → git push ──→ Received via git pull on next cycle Config → git push ──→ Received via git pull on next cycle
``` ```
**Mirror's daily experience:** open unRAID Docker UI, click NginxProxyManager, **Mirror's daily experience:** open unRAID Docker UI, click NginxProxyManager,
browser opens HOST1's NPM WebUI automatically via Tailscale. Make a proxy rule browser opens HOST1's NPM WebUI automatically via Tailscale. Make a proxy rule
change. 15 minutes later it's live on HOST2. The mirror operator never manages change. 30 minutes later it's live on HOST2. The mirror operator never manages
auth directly — every WebUI redirect is transparent and automatic. auth directly — every WebUI redirect is transparent and automatic.
**Owner's daily experience:** manage auth as normal. Opens NPM → adds a proxy **Owner's daily experience:** manage auth as normal. Opens NPM → adds a proxy
rule → 15min later live on both servers. Never needs to SSH to HOST2 or think rule → 30min later live on both servers. Never needs to SSH to HOST2 or think
about HOST2 during normal operation. about HOST2 during normal operation.
--- ---
+5 -5
View File
@@ -34,7 +34,7 @@ in one place and forgotten in the other.
**The fix:** one auth stack with a managed mirror. HOST1 owns the configuration. **The fix:** one auth stack with a managed mirror. HOST1 owns the configuration.
HOST2 runs a warm copy that stays current via 15-minute sync. HOST2's operator makes HOST2 runs a warm copy that stays current via 15-minute sync. HOST2's operator makes
zero auth management decisions — clicking an auth container opens HOST1's WebUI via zero auth management decisions — clicking an auth container opens HOST1's WebUI via
Tailscale. Changes happen there, propagate to HOST2 in 15 minutes. One place to Tailscale. Changes happen there, propagate to HOST2 in 30 minutes. One place to
manage everything for both households. manage everything for both households.
--- ---
@@ -107,7 +107,7 @@ Called by `partnership_manager.sh --offboard` but runnable directly.
**Lifecycle management** (`partnership_manager.sh`) — dispatcher and monitor. **Lifecycle management** (`partnership_manager.sh`) — dispatcher and monitor.
- Manually: `--onboard`, `--offboard` (delegates to offboard script), `--transfer`, `--status`, `--unblock` - Manually: `--onboard`, `--offboard` (delegates to offboard script), `--transfer`, `--status`, `--unblock`
- Automatically: `--check` called every 15 minutes by `critical_sync_maintenance.sh` - Automatically: `--check` called every 30 minutes by `critical_sync_maintenance.sh`
**SSH management** (`ssh_setup.sh`) — generates the keypair for rsync automation, **SSH management** (`ssh_setup.sh`) — generates the keypair for rsync automation,
installs it on the remote, and tracks auth failures with a configurable strike system. installs it on the remote, and tracks auth failures with a configurable strike system.
@@ -119,7 +119,7 @@ re-keying.
## ━━━ RELATIONSHIP TO OTHER FOLDERS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ## ━━━ RELATIONSHIP TO OTHER FOLDERS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Orchestrators/**`critical_sync_maintenance.sh` calls `partnership_manager.sh --check` **Orchestrators/**`critical_sync_maintenance.sh` calls `partnership_manager.sh --check`
every 15 minutes, passing `--remote-seen` or `--remote-unseen` based on whether the every 30 minutes, passing `--remote-seen` or `--remote-unseen` based on whether the
rsync to the partner succeeded. The rsync outcome is the connectivity signal — no rsync to the partner succeeded. The rsync outcome is the connectivity signal — no
separate ping needed. separate ping needed.
@@ -140,7 +140,7 @@ independently at 4-hour cadence.
|--------|------|--------------| |--------|------|--------------|
| `partnership_onboard.sh` | One-time setup — SSH keys, stack deploy, arr bootstrap | Manually, once per server per partnership | | `partnership_onboard.sh` | One-time setup — SSH keys, stack deploy, arr bootstrap | Manually, once per server per partnership |
| `partnership_offboard.sh` | Clean separation — both paths, both roles | Via `partnership_manager.sh --offboard`; or directly | | `partnership_offboard.sh` | Clean separation — both paths, both roles | Via `partnership_manager.sh --offboard`; or directly |
| `partnership_manager.sh` | Dispatcher + monitor — onboard WebUIs, health check, transfer, status | `--check` every 15min; all other modes manually | | `partnership_manager.sh` | Dispatcher + monitor — onboard WebUIs, health check, transfer, status | `--check` every 30min; all other modes manually |
| `ssh_setup.sh` | SSH key generation, remote install, auth validation | Called by onboard; manually for re-keying or validation | | `ssh_setup.sh` | SSH key generation, remote install, auth validation | Called by onboard; manually for re-keying or validation |
--- ---
@@ -166,7 +166,7 @@ HOST1 (owner) runs:
├─ partnership_manager.sh --onboard reconfigures WebUIs, writes ACTIVE state ├─ partnership_manager.sh --onboard reconfigures WebUIs, writes ACTIVE state
└─ arr_sync.sh bootstraps full library on both servers └─ arr_sync.sh bootstraps full library on both servers
ONGOING OPERATION (every 15min) ONGOING OPERATION (every 30min)
───────────────────────────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────────────────────────
critical_sync_maintenance.sh critical_sync_maintenance.sh
├─ Critical-Data rsync keeps auth appdata current on mirror ├─ Critical-Data rsync keeps auth appdata current on mirror
+5 -5
View File
@@ -7,7 +7,7 @@
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Manages the full lifecycle of a two-server partnership — onboard, daily health # Manages the full lifecycle of a two-server partnership — onboard, daily health
# monitoring, offboard, and ownership transfer. Called by partnership_onboard.sh # monitoring, offboard, and ownership transfer. Called by partnership_onboard.sh
# during initial setup, and by critical_sync_maintenance.sh every 15 minutes for # during initial setup, and by critical_sync_maintenance.sh every 30 minutes for
# the --check mode. All other modes are run manually. # the --check mode. All other modes are run manually.
# #
# PARTNERSHIP_OWNER_HOST flips to "HOST2" after a successful --transfer. # PARTNERSHIP_OWNER_HOST flips to "HOST2" after a successful --transfer.
@@ -34,7 +34,7 @@
# Reconfigures both servers, flips PARTNERSHIP_OWNER_HOST in master.conf # Reconfigures both servers, flips PARTNERSHIP_OWNER_HOST in master.conf
# Requires confirmation string + consecutive health check passes # Requires confirmation string + consecutive health check passes
# #
# --check (called every 15min by critical_sync_maintenance.sh) # --check (called every 30min by critical_sync_maintenance.sh)
# --remote-seen: rsync succeeded → reset offline counter, read remote state # --remote-seen: rsync succeeded → reset offline counter, read remote state
# --remote-unseen: rsync failed → increment offline counter → auto-offboard at threshold # --remote-unseen: rsync failed → increment offline counter → auto-offboard at threshold
# Silent when healthy — never noisy on clean runs # Silent when healthy — never noisy on clean runs
@@ -172,7 +172,7 @@
# Flip ownership — owner only. Requires exact confirmation string. # Flip ownership — owner only. Requires exact confirmation string.
# #
# partnership_manager.sh --check --remote-seen|--remote-unseen # partnership_manager.sh --check --remote-seen|--remote-unseen
# Called by critical_sync_maintenance.sh every 15min — do not run manually # Called by critical_sync_maintenance.sh every 30min — do not run manually
# #
# partnership_manager.sh --status # partnership_manager.sh --status
# Show state files, blocklist, SSH key status from both servers # Show state files, blocklist, SSH key status from both servers
@@ -1300,7 +1300,7 @@ fi
# ============================================================================================== # ==============================================================================================
# ━━━ Check ━━━ # ━━━ Check ━━━
# Called every 15min by critical_sync_maintenance.sh — must be silent when healthy # Called every 30min by critical_sync_maintenance.sh — must be silent when healthy
# ============================================================================================== # ==============================================================================================
if [[ "$MODE" == "check" ]]; then if [[ "$MODE" == "check" ]]; then
@@ -1316,7 +1316,7 @@ if [[ "$MODE" == "check" ]]; then
OFFLINE_COUNT=$(( OFFLINE_COUNT + 1 )) OFFLINE_COUNT=$(( OFFLINE_COUNT + 1 ))
echo "$OFFLINE_COUNT" > "$OFFLINE_COUNTER" echo "$OFFLINE_COUNT" > "$OFFLINE_COUNTER"
# Auto-offboard threshold: threshold_days × 96 intervals/day (every 15min) # Auto-offboard threshold: threshold_days × 48 intervals/day (every 30min)
THRESHOLD_INTERVALS=$(( ${PARTNERSHIP_OFFLINE_THRESHOLD:-30} * 96 )) THRESHOLD_INTERVALS=$(( ${PARTNERSHIP_OFFLINE_THRESHOLD:-30} * 96 ))
if [[ "$OFFLINE_COUNT" -ge "$THRESHOLD_INTERVALS" ]]; then if [[ "$OFFLINE_COUNT" -ge "$THRESHOLD_INTERVALS" ]]; then
warn "Remote offline for ${PARTNERSHIP_OFFLINE_THRESHOLD} days — triggering auto-offboard" warn "Remote offline for ${PARTNERSHIP_OFFLINE_THRESHOLD} days — triggering auto-offboard"
+22 -49
View File
@@ -127,7 +127,7 @@ the array stops. Check with: `pgrep -f "stability_watchdog\|docker_watchdog\|fai
``` ```
Category: Orchestrators Category: Orchestrators
Name: transcode_management Name: transcode_management
Schedule: */3 * * * * (every 3 minutes) Schedule: */7 * * * * (every 7 minutes)
Background: YES Background: YES
``` ```
@@ -138,7 +138,7 @@ Background: YES
**What it does:** **What it does:**
Runs transcode_cleanup.sh then transcode_manager.sh — in that exact order every Runs transcode_cleanup.sh then transcode_manager.sh — in that exact order every
3 minutes. Order is non-negotiable: cleanup removes stale files first so the manager 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. sees real active session usage, not inflated numbers from ended sessions.
**transcode_cleanup.sh:** **transcode_cleanup.sh:**
@@ -167,7 +167,7 @@ auto-flip to SSD, missing transcoding-temp → recreate immediately.
``` ```
Category: Orchestrators Category: Orchestrators
Name: critical_sync_maintenance Name: critical_sync_maintenance
Schedule: */15 * * * * (every 15 minutes) Schedule: */30 * * * * (every 30 minutes)
Background: YES Background: YES
``` ```
@@ -177,13 +177,13 @@ Background: YES
``` ```
**What it does:** **What it does:**
Keeps the auth stack and Emby watch state current on HOST2 — 15 minutes is the Keeps the auth stack and Emby watch state current on HOST2 — 30 minutes is the
maximum staleness for failover-critical data. maximum staleness for fallback-critical data.
**Jobs in order:** **Jobs in order:**
``` ```
rsync Critical-Data — pushes auth stack to HOST2 (NPM rules, certs, LLDAP users, rsync Critical-Data — pushes auth stack to HOST2 (NPM rules, certs, LLDAP users,
Authelia config). HOST2's auth is always within 15min of HOST1. Authelia config). HOST2's auth is always within 30min of HOST1.
rsync Emby dirty sync — pushes watch states, user activity, library delta to HOST2 rsync Emby dirty sync — pushes watch states, user activity, library delta to HOST2
with Emby running. WAL files excluded — safe mid-write. with Emby running. WAL files excluded — safe mid-write.
HOST2 Emby restarts after sync to pick up config changes. HOST2 Emby restarts after sync to pick up config changes.
@@ -191,7 +191,7 @@ partnership --check — reads remote state file, increments offline counter
unreachable, triggers auto-offboard at PARTNERSHIP_OFFLINE_THRESHOLD unreachable, triggers auto-offboard at PARTNERSHIP_OFFLINE_THRESHOLD
``` ```
**Silent when healthy:** no output on clean cycles — runs 96 times per day. **Silent when healthy:** no output on clean cycles — runs 48 times per day.
--- ---
@@ -286,35 +286,14 @@ in one orchestrated sequence.
### ── rsync_emby_failover ───────────────────────────────────────────────────── ### ── rsync_emby_failover ─────────────────────────────────────────────────────
``` > **Superseded by `critical_sync_maintenance`.** Delete this User Script from the
Category: Orchestrators > plugin. The emby-fallback dirty sync now runs as step 2 inside
Name: rsync_emby_failover > `critical_sync_maintenance.sh` every 30 minutes alongside the auth stack sync
Schedule: */30 * * * * (every 30 minutes) > and partnership check. Running both produces duplicate syncs.
Background: YES
```
```bash The Emby dirty sync (`/mnt/user/Media_Server/Emby --profile=emby-fallback`) is
#!/bin/bash configured in `HOST1_CRITICAL_SYNC_SHARES` in host1.conf. It runs automatically
/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ when critical_sync_maintenance.sh runs.
/mnt/user/Media_Server/Emby --profile=emby-fallback
```
**What it does:**
Keeps HOST2's Emby within 30 minutes of HOST1 on watch states, play positions, and
library changes — with Emby running on both sides. Not a full sync (that's weekly) —
this is continuous coverage of what matters for failover.
**What syncs (emby-fallback profile):**
```
Syncs: users.db, library.db, authentication.db, config/
Skips: *.wal *.shm — WAL files being written by Emby, unsafe to copy mid-write
transcodes/ — volatile, never needed on HOST2
logs/ — local diagnostics only
cache/ — rebuilt automatically
```
**HOST2 Emby restarts after each sync** to pick up config changes.
**Result:** if HOST1 goes down, users resume from a position at most 30min stale.
--- ---
@@ -346,7 +325,7 @@ updates at zero extra downtime, weekly container restarts.
5. Pull images remotely — if WEEKLY_SYNC_UPDATES_REMOTE=true (SSH to remote) 5. Pull images remotely — if WEEKLY_SYNC_UPDATES_REMOTE=true (SSH to remote)
6. rsync WEEKLY_SYNC_SHARES: 6. rsync WEEKLY_SYNC_SHARES:
/mnt/user/Media_Server/Emby — full clean mirror, databases checkpointed /mnt/user/Media_Server/Emby — full clean mirror, databases checkpointed
/mnt/user/appdata-Failover/Critical-Data — auth stack clean state /mnt/user/appdata-Fallback/Critical-Data — auth stack clean state
7. Start remote containers— dependency order, new image, settle + verify each 7. Start remote containers— dependency order, new image, settle + verify each
8. Start local containers — same 8. Start local containers — same
9. docker_weekly_restart.sh — restarts less-critical services that benefit from 9. docker_weekly_restart.sh — restarts less-critical services that benefit from
@@ -774,7 +753,7 @@ Background: YES
```bash ```bash
#!/bin/bash #!/bin/bash
/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Critical-Data /mnt/user/appdata-Fallback/Critical-Data
``` ```
**What syncs:** auth stack — NPM proxy rules, TLS certificates, LLDAP user data, **What syncs:** auth stack — NPM proxy rules, TLS certificates, LLDAP user data,
@@ -816,7 +795,7 @@ Background: YES
```bash ```bash
#!/bin/bash #!/bin/bash
/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Arrs_Stack /mnt/user/appdata-Fallback/Arrs_Stack
``` ```
**What syncs:** all arr appdata — Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, Pinchflat **What syncs:** all arr appdata — Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, Pinchflat
@@ -837,7 +816,7 @@ Background: YES
```bash ```bash
#!/bin/bash #!/bin/bash
/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Important-Data /mnt/user/appdata-Fallback/Important-Data
``` ```
**What syncs:** NextCloud, Postgres-NextCloud, Immich, PostgreSQL-Immich appdata. **What syncs:** NextCloud, Postgres-NextCloud, Immich, PostgreSQL-Immich appdata.
@@ -857,7 +836,7 @@ Background: YES
```bash ```bash
#!/bin/bash #!/bin/bash
/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Gmer4Lfe /mnt/user/appdata-Fallback/Gmer4Lfe
``` ```
**What syncs:** HOST1 server appdata backup — everything in the Gmer4Lfe appdata share. **What syncs:** HOST1 server appdata backup — everything in the Gmer4Lfe appdata share.
@@ -1175,7 +1154,7 @@ Current usage on both ramdisk and SSD.
``` ```
Category: Transcodes Category: Transcodes
Name: transcode_manager_manual Name: transcode_manager_manual
Schedule: None — run manually (runs via transcode_management.sh every 3 min) Schedule: None — run manually (runs via transcode_management.sh every 7 min)
Background: NO Background: NO
``` ```
@@ -1641,17 +1620,11 @@ Wrong startup setup (old approach):
At Startup of Array: At Startup of Array:
array_start BG: YES — single entry, handles everything array_start BG: YES — single entry, handles everything
*/3 * * * * (every 3 min): */7 * * * * (every 7 min):
transcode_management BG: YES — cleanup then manager transcode_management BG: YES — cleanup then manager
*/10 * * * * (every 10 min):
webgui_watchdog BG: YES — silent when healthy
*/15 * * * * (every 15 min):
critical_sync_maintenance BG: YES — auth stack + Emby dirty + partnership check
*/30 * * * * (every 30 min): */30 * * * * (every 30 min):
rsync_emby_failover BG: YES — Emby watch state sync critical_sync_maintenance BG: YES — auth stack + Emby dirty sync + partnership
0 */6 * * * (every 6 hours): 0 */6 * * * (every 6 hours):
arrs_failed_stalled_recovery BG: YES — blocklist + re-search failed imports arrs_failed_stalled_recovery BG: YES — blocklist + re-search failed imports
+9 -9
View File
@@ -243,14 +243,14 @@ where determines whether you need encryption and whether sync failure matters.
# services to work correctly when they start on HOST2. # services to work correctly when they start on HOST2.
# #
/mnt/user/Media_Server/Emby # Emby userdata — watch history, playstates /mnt/user/Media_Server/Emby # Emby userdata — watch history, playstates
/mnt/user/appdata-Failover/Critical-Data # auth stack — NPM rules, certs, user accounts /mnt/user/appdata-Fallback/Critical-Data # auth stack — NPM rules, certs, user accounts
/mnt/user/Movies # media library content /mnt/user/Movies # media library content
/mnt/user/Tv_Shows # media library content /mnt/user/Tv_Shows # media library content
/mnt/user/Music # media library content /mnt/user/Music # media library content
# #
# Sync failure here = failover runs but with stale data (acceptable) or missing # Sync failure here = failover runs but with stale data (acceptable) or missing
# data (problematic). These sync every night via daily_sync_maintenance.sh. # data (problematic). These sync every night via daily_sync_maintenance.sh.
# Critical-Data and Emby also sync every 15 minutes via critical_sync_maintenance.sh. # Critical-Data and Emby also sync every 30 minutes via critical_sync_maintenance.sh.
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
``` ```
@@ -266,8 +266,8 @@ where determines whether you need encryption and whether sync failure matters.
# Content is not sensitive — anyone with access to HOST2 could read it. # Content is not sensitive — anyone with access to HOST2 could read it.
# #
# Examples: # Examples:
/mnt/user/appdata-Failover/Gmer4Lfe # Gmer4Lfe server appdata backup /mnt/user/appdata-Fallback/Gmer4Lfe # Gmer4Lfe server appdata backup
/mnt/user/appdata-Failover/Important-Data # NextCloud, Immich appdata /mnt/user/appdata-Fallback/Important-Data # NextCloud, Immich appdata
/mnt/user/Kids_Movies # kids content — not sensitive /mnt/user/Kids_Movies # kids content — not sensitive
/mnt/user/Sports # sports content — not sensitive /mnt/user/Sports # sports content — not sensitive
# #
@@ -345,7 +345,7 @@ This is not standby. This is mutual coverage between peers.
# #
# "Minimal disruption" does NOT mean: # "Minimal disruption" does NOT mean:
# Zero downtime (DDNS TTL = 1 minute, brief gap expected) # Zero downtime (DDNS TTL = 1 minute, brief gap expected)
# Perfect consistency (Emby userdata is 15min stale at most) # Perfect consistency (Emby userdata is 30min stale at most)
# All services covered immediately (tiered start over 24 hours) # All services covered immediately (tiered start over 24 hours)
# #
# The system is designed around the real experience of a household: # The system is designed around the real experience of a household:
@@ -363,7 +363,7 @@ This is not standby. This is mutual coverage between peers.
```bash ```bash
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Things conventional failover provides that this does NOT: # Things conventional failover provides that this does NOT:
# Zero RPO (recovery point objective) — there is ~15min of potential staleness # Zero RPO (recovery point objective) — there is ~30min of potential staleness
# Synchronous state replication — changes don't reach HOST2 instantly # Synchronous state replication — changes don't reach HOST2 instantly
# Automatic failure detection in seconds — fallback.sh checks every 2 minutes # Automatic failure detection in seconds — fallback.sh checks every 2 minutes
# Transparent IP migration — DNS TTL means up to 1 minute of routing to old IP # Transparent IP migration — DNS TTL means up to 1 minute of routing to old IP
@@ -426,7 +426,7 @@ server's own domain.
# #
# HOST1 is source of truth for the auth configuration. All changes to NPM proxy # HOST1 is source of truth for the auth configuration. All changes to NPM proxy
# rules, LLDAP users, Authelia policies, and certs happen on HOST1 and propagate # rules, LLDAP users, Authelia policies, and certs happen on HOST1 and propagate
# to HOST2 via Critical-Data sync every 15 minutes. # to HOST2 via Critical-Data sync every 30 minutes.
# #
# HOST2 operator's experience: click NginxProxyManager in Docker UI → # HOST2 operator's experience: click NginxProxyManager in Docker UI →
# browser opens HOST1's NPM via Tailscale redirect → make changes there → # browser opens HOST1's NPM via Tailscale redirect → make changes there →
@@ -451,7 +451,7 @@ Always running:
Source of truth: Source of truth:
Media Movies, Tv_Shows, Music ←── Anime_Movies, Anime_Shows Media Movies, Tv_Shows, Music ←── Anime_Movies, Anime_Shows
───────────────────────→ (bidirectional daily push) ───────────────────────→ (bidirectional daily push)
Config auth stack config ──→ mirrored every 15 min Config auth stack config ──→ mirrored every 30 min
Emby state watch history, playstates──→ dirty sync every 30 min Emby state watch history, playstates──→ dirty sync every 30 min
Failover coverage: Failover coverage:
@@ -621,7 +621,7 @@ Throughout the day (every minute via watchdog_orchestrator.sh):
Throughout the day: Throughout the day:
fallback.sh watching: remote server, internet connectivity fallback.sh watching: remote server, internet connectivity
transcode_management.sh managing: ramdisk ↔ SSD, session cleanup (every 3min) transcode_management.sh managing: ramdisk ↔ SSD, session cleanup (every 3min)
critical_sync_maintenance.sh keeping: auth stack + Emby current (every 15min) critical_sync_maintenance.sh keeping: auth stack + Emby current (every 30min)
1am: 1am:
git pull (latest scripts first) git pull (latest scripts first)
+11 -11
View File
@@ -261,7 +261,7 @@ HOST2_DAILY_SYNC_SHARES=(
# Synced during the Sunday 2:30am window — containers stopped both sides. # Synced during the Sunday 2:30am window — containers stopped both sides.
WEEKLY_SYNC_SHARES=( WEEKLY_SYNC_SHARES=(
"/mnt/user/Media_Server/Emby" "/mnt/user/Media_Server/Emby"
"/mnt/user/appdata-Failover/Critical-Data" "/mnt/user/appdata-Fallback/Critical-Data"
) )
``` ```
@@ -296,13 +296,13 @@ Override with `--profile=name`.
### Profile Matching ### Profile Matching
```bash ```bash
# rsync.sh /mnt/user/appdata-Failover/Arrs_Stack # rsync.sh /mnt/user/appdata-Fallback/Arrs_Stack
# basename: Arrs_Stack → lowercased: arrs_stack → matches [arrs_stack] profile # basename: Arrs_Stack → lowercased: arrs_stack → matches [arrs_stack] profile
# #
# rsync.sh /mnt/user/Movies # rsync.sh /mnt/user/Movies
# basename: Movies → no profile match → global defaults (no containers stopped) # basename: Movies → no profile match → global defaults (no containers stopped)
# #
# rsync.sh /mnt/user/appdata-Failover/Critical-Data --profile=critical-data # rsync.sh /mnt/user/appdata-Fallback/Critical-Data --profile=critical-data
# explicit override # explicit override
``` ```
@@ -492,7 +492,7 @@ Test with `--dry-run` first — all pre-flight checks run, no changes made.
```bash ```bash
bash /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ bash /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Arrs_Stack --dry-run --log /mnt/user/appdata-Fallback/Arrs_Stack --dry-run --log
``` ```
Expected output (healthy): Expected output (healthy):
@@ -521,7 +521,7 @@ bash /mnt/user/appdata/unraid_scripts/Orchestrators/daily_sync_maintenance.sh --
```bash ```bash
bash /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \ bash /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh \
/mnt/user/appdata-Failover/Arrs_Stack --status /mnt/user/appdata-Fallback/Arrs_Stack --status
``` ```
--- ---
@@ -619,13 +619,13 @@ ssh -i /root/.ssh/Gmer4Lfe-rsync-key root@[HOST2-ip] "docker ps --format '{{.Nam
```bash ```bash
# Profile key = directory basename lowercased # Profile key = directory basename lowercased
# /mnt/user/appdata-Failover/Arrs_Stack → key: arrs_stack # /mnt/user/appdata-Fallback/Arrs_Stack → key: arrs_stack
# Override explicitly: # Override explicitly:
bash rsync.sh /mnt/user/appdata-Failover/My_Stuff --profile=arrs_stack bash rsync.sh /mnt/user/appdata-Fallback/My_Stuff --profile=arrs_stack
# Verify what profile resolved: # Verify what profile resolved:
bash rsync.sh /mnt/user/appdata-Failover/Arrs_Stack --status bash rsync.sh /mnt/user/appdata-Fallback/Arrs_Stack --status
``` ```
--- ---
@@ -705,7 +705,7 @@ stops, no bandwidth log entry. Safe to run at any time.
```bash ```bash
rsync.sh /mnt/user/Movies --dry-run rsync.sh /mnt/user/Movies --dry-run
rsync.sh /mnt/user/appdata-Failover/Arrs_Stack --dry-run --log rsync.sh /mnt/user/appdata-Fallback/Arrs_Stack --dry-run --log
daily_sync_maintenance.sh --dry-run daily_sync_maintenance.sh --dry-run
``` ```
@@ -716,7 +716,7 @@ used — then exits. No pre-flight checks, no rsync. Use to verify configuration
loaded correctly. loaded correctly.
```bash ```bash
rsync.sh /mnt/user/appdata-Failover/Arrs_Stack --status rsync.sh /mnt/user/appdata-Fallback/Arrs_Stack --status
``` ```
### --log ### --log
@@ -730,6 +730,6 @@ Override profile selection. Bypasses basename inference. Use when the directory
name doesn't match any profile key, or when testing a specific profile. name doesn't match any profile key, or when testing a specific profile.
```bash ```bash
rsync.sh /mnt/user/appdata-Failover/Critical-Data --profile=critical-data rsync.sh /mnt/user/appdata-Fallback/Critical-Data --profile=critical-data
rsync.sh /mnt/user/Media_Server/Emby --profile=emby-fallback rsync.sh /mnt/user/Media_Server/Emby --profile=emby-fallback
``` ```
+3 -3
View File
@@ -26,11 +26,11 @@ All three scripts follow a two-tier output model: `echo` lines are always visibl
**ramdisk_setup.sh** — one-shot at array start. Without `--log`, section headers **ramdisk_setup.sh** — one-shot at array start. Without `--log`, section headers
and the final summary are visible. Per-step creation detail suppressed. and the final summary are visible. Per-step creation detail suppressed.
**transcode_manager.sh** — runs every 3 minutes. Without `--log`, only state **transcode_manager.sh** — runs every 7 minutes. Without `--log`, only state
transitions (flips, warnings, errors) and active session display are shown. When transitions (flips, warnings, errors) and active session display are shown. When
nothing changes, a single one-line confirmation is printed. Per-check detail suppressed. nothing changes, a single one-line confirmation is printed. Per-check detail suppressed.
**transcode_cleanup.sh** — runs every 3 minutes. Without `--log`, the cleanup **transcode_cleanup.sh** — runs every 7 minutes. Without `--log`, the cleanup
summary (files removed, space freed) is always visible. Per-file deletion detail summary (files removed, space freed) is always visible. Per-file deletion detail
suppressed. suppressed.
@@ -376,7 +376,7 @@ At Startup of Array (via array_started.sh in unRAID_Essentials/):
ramdisk_setup.sh — creates ramdisk, symlink, transcoding-temp ramdisk_setup.sh — creates ramdisk, symlink, transcoding-temp
Must run BEFORE Emby starts Must run BEFORE Emby starts
Every 3 minutes (via transcode_management.sh in Orchestrators/): Every 7 minutes (via transcode_management.sh in Orchestrators/):
1. transcode_cleanup.sh — remove stale files, check flip-back 1. transcode_cleanup.sh — remove stale files, check flip-back
2. transcode_manager.sh — check usage, flip if needed, display sessions 2. transcode_manager.sh — check usage, flip if needed, display sessions
+3 -3
View File
@@ -49,7 +49,7 @@ it at mount time. Both protections together prevent this permanently.
**lsof Per File on a Live TV System** **lsof Per File on a Live TV System**
Early cleanup called `lsof filename` per file to check if anything had it open. On a busy Early cleanup called `lsof filename` per file to check if anything had it open. On a busy
Live TV night with 5 simultaneous streams, the ramdisk contains thousands of HLS segment Live TV night with 5 simultaneous streams, the ramdisk contains thousands of HLS segment
files — thousands of subprocess calls every 3 minutes. files — thousands of subprocess calls every 7 minutes.
Fix: lsof called once per location to build a complete open-file map. All subsequent Fix: lsof called once per location to build a complete open-file map. All subsequent
checks are O(1) lookups against that map. checks are O(1) lookups against that map.
@@ -82,7 +82,7 @@ unRAID_Essentials/
Orchestrators/ Orchestrators/
transcode_management.sh ──── cleanup first ──► transcode_cleanup.sh transcode_management.sh ──── cleanup first ──► transcode_cleanup.sh
──── then manager ──► transcode_manager.sh ──── then manager ──► transcode_manager.sh
(every 3 minutes — order non-negotiable) (every 7 minutes — order non-negotiable)
Monitors/ Monitors/
weekly_health_digest.sh ◄─── reads ──────────── TRANSCODE_DAILY_LOG weekly_health_digest.sh ◄─── reads ──────────── TRANSCODE_DAILY_LOG
@@ -121,7 +121,7 @@ Emby starts, reads transcode path from config
All new sessions write to: /mnt/ram-transcode → /mnt/ramdisk_transcodes/ All new sessions write to: /mnt/ram-transcode → /mnt/ramdisk_transcodes/
Every 3 minutes (transcode_management.sh): Every 7 minutes (transcode_management.sh):
├─ transcode_cleanup.sh ├─ transcode_cleanup.sh
│ Remove files older than TRANSCODE_MAX_AGE, not open by any process │ Remove files older than TRANSCODE_MAX_AGE, not open by any process
+2 -2
View File
@@ -20,7 +20,7 @@
# #
# lsof Called Once, Not Per File # lsof Called Once, Not Per File
# On a busy Live TV system the ramdisk contains thousands of HLS segment files. # On a busy Live TV system the ramdisk contains thousands of HLS segment files.
# Calling lsof once per file creates thousands of subprocess calls every 3 minutes. # Calling lsof once per file creates thousands of subprocess calls every 7 minutes.
# lsof is called once per location to build a complete open-file map. All subsequent # lsof is called once per location to build a complete open-file map. All subsequent
# checks are O(1) lookups against that map — thousands of files, one lsof call. # checks are O(1) lookups against that map — thousands of files, one lsof call.
# #
@@ -59,7 +59,7 @@
# `! -name "transcoding-temp"` in the find command — protected unconditionally. # `! -name "transcoding-temp"` in the find command — protected unconditionally.
# #
# Silent by Default # Silent by Default
# Runs every 3 minutes — must not produce noise when healthy. # Runs every 7 minutes — must not produce noise when healthy.
# #
# ============================================================================================== # ==============================================================================================
# CONFIGURATION # CONFIGURATION
+2 -2
View File
@@ -6,7 +6,7 @@
# PURPOSE # PURPOSE
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Monitors ramdisk usage and manages the transcode symlink direction. Called by # Monitors ramdisk usage and manages the transcode symlink direction. Called by
# transcode_management.sh (Orchestrators/) every 3 minutes — always after # transcode_management.sh (Orchestrators/) every 7 minutes — always after
# transcode_cleanup.sh runs first. Must be fast, non-blocking, and silent when # transcode_cleanup.sh runs first. Must be fast, non-blocking, and silent when
# nothing has changed. # nothing has changed.
# #
@@ -59,7 +59,7 @@
# validate_unraid_cmd confirms the notify script is present before use. # validate_unraid_cmd confirms the notify script is present before use.
# #
# Silent by Default # Silent by Default
# Runs every 3 minutes — only speaks when something changes or needs attention. # Runs every 7 minutes — only speaks when something changes or needs attention.
# #
# ============================================================================================== # ==============================================================================================
# CONFIGURATION # CONFIGURATION
+10 -10
View File
@@ -17,8 +17,8 @@
# array_started.sh at array start — launches ALL startup scripts in order # array_started.sh at array start — launches ALL startup scripts in order
# array_stopping.sh at array stop — graceful shutdown sequence # array_stopping.sh at array stop — graceful shutdown sequence
# watchdog_orchestrator.sh every minute — resource + docker + system watchdog # watchdog_orchestrator.sh every minute — resource + docker + system watchdog
# transcode_management.sh every 3 min — cleanup then manager (order critical) # transcode_management.sh every 7 min — cleanup then manager (order critical)
# critical_sync_maintenance.sh every 15 min — auth + Emby dirty sync + partnership # critical_sync_maintenance.sh every 30 min — auth + Emby dirty sync + partnership
# intermediate_sync_maintenance.sh every 4 hours — arr library sync + artwork fetch # intermediate_sync_maintenance.sh every 4 hours — arr library sync + artwork fetch
# daily_sync_maintenance.sh 1am daily — git + rsync + media + restart # daily_sync_maintenance.sh 1am daily — git + rsync + media + restart
# rsync.sh --profile=emby-fallback every 30 min — Emby watch state dirty sync # rsync.sh --profile=emby-fallback every 30 min — Emby watch state dirty sync
@@ -174,7 +174,7 @@
# ── TRANSCODE MANAGEMENT ────────────────────────────────────────────────────────────────────── # ── TRANSCODE MANAGEMENT ──────────────────────────────────────────────────────────────────────
# Schedule: */3 * * * * (every 3 minutes) # Schedule: */7 * * * * (every 7 minutes)
# Background: YES # Background: YES
# #
# Cleanup first, then manager — order is non-negotiable. Stale segment files are removed # Cleanup first, then manager — order is non-negotiable. Stale segment files are removed
@@ -202,15 +202,15 @@
# ── CRITICAL SYNC MAINTENANCE ───────────────────────────────────────────────────────────────── # ── CRITICAL SYNC MAINTENANCE ─────────────────────────────────────────────────────────────────
# Schedule: */15 * * * * (every 15 minutes) # Schedule: */30 * * * * (every 30 minutes)
# Background: YES # Background: YES
# #
# Keeps failover-critical data current on HOST2. 15 minutes is the maximum staleness # Keeps fallback-critical data current on HOST2. 30 minutes is the maximum staleness
# for the auth stack and Emby watch states. Run on HOST1 — bidirectional via detect_hosts(). # for the auth stack and Emby watch states. Run on HOST1 — bidirectional via detect_hosts().
# #
# rsync Critical-Data: # rsync Critical-Data:
# Auth stack to HOST2: NPM proxy rules, TLS certs, LLDAP user accounts, # Auth stack to HOST2: NPM proxy rules, TLS certs, LLDAP user accounts,
# Authelia config and policies. HOST2 auth always within 15min of HOST1. # Authelia config and policies. HOST2 auth always within 30min of HOST1.
# #
# rsync Emby dirty sync: # rsync Emby dirty sync:
# Watch states, user activity, library delta — Emby stays running on both sides. # Watch states, user activity, library delta — Emby stays running on both sides.
@@ -221,7 +221,7 @@
# Reads remote state file. Increments offline counter on failed sync. # Reads remote state file. Increments offline counter on failed sync.
# Triggers auto-offboard at PARTNERSHIP_OFFLINE_THRESHOLD (30 days) unreachable. # Triggers auto-offboard at PARTNERSHIP_OFFLINE_THRESHOLD (30 days) unreachable.
# #
# Silent on clean cycles: runs 96 times per day, no output when healthy. # Silent on clean cycles: runs 48 times per day, no output when healthy.
# #
# bash /mnt/user/appdata/unraid_scripts/Orchestrators/critical_sync_maintenance.sh # bash /mnt/user/appdata/unraid_scripts/Orchestrators/critical_sync_maintenance.sh
@@ -684,7 +684,7 @@
# bash /mnt/user/appdata/unraid_scripts/Docker_Essentials/docker_update_remaining.sh # bash /mnt/user/appdata/unraid_scripts/Docker_Essentials/docker_update_remaining.sh
# downloaders_reset.sh — maintenance reset for all download clients on this server # downloaders_reset.sh — maintenance reset for all download clients on this server
# Called every 15 minutes by critical_sync_maintenance.sh via CRITICAL_MAINTENANCE_SCRIPTS. # Called every 30 minutes by critical_sync_maintenance.sh via CRITICAL_MAINTENANCE_SCRIPTS.
# Host-aware: sections skip gracefully if a downloader URL is empty for this server. # Host-aware: sections skip gracefully if a downloader URL is empty for this server.
# #
# slskd: # slskd:
@@ -1297,13 +1297,13 @@
# * * * * * every minute: # * * * * * every minute:
# Orchestrators/watchdog_orchestrator.sh # Orchestrators/watchdog_orchestrator.sh
# #
# */3 * * * * every 3 minutes: # */7 * * * * every 7 minutes:
# Orchestrators/transcode_management.sh # Orchestrators/transcode_management.sh
# #
# */10 * * * * every 10 minutes: # */10 * * * * every 10 minutes:
# Watchdogs/System/webgui_watchdog.sh # Watchdogs/System/webgui_watchdog.sh
# #
# */15 * * * * every 15 minutes: # */30 * * * * every 30 minutes:
# Orchestrators/critical_sync_maintenance.sh # Orchestrators/critical_sync_maintenance.sh
# #
# */30 * * * * every 30 minutes: # */30 * * * * every 30 minutes: