fixed reADME AND USER SCRIPT PLUGIN
This commit is contained in:
@@ -22,83 +22,88 @@ Before this ecosystem existed, the same problems were solved by 60+ standalone s
|
||||
## The Servers
|
||||
|
||||
```
|
||||
HOST1 — unRAID-Gmer4Lfe (Primary)
|
||||
HOST1 — unRAID-Gmer4Lfe
|
||||
Hardware: Threadripper 1950X, 128GB RAM
|
||||
Storage: Multiple ZFS pools + cache
|
||||
Role: Primary services, full media stack, all Docker containers
|
||||
Domain: Gmer4Lfe.com
|
||||
Runs: Full media stack, auth, live TV, arrs, downloaders
|
||||
arr master — source of truth for shared library
|
||||
|
||||
HOST2 — unRAID-Jayred365 (Secondary / Buddy server)
|
||||
HOST2 — unRAID-Jayred365 (Buddy server)
|
||||
Hardware: Intel i5 10th gen — completely different hardware
|
||||
Storage: Different disk count, different pool layout
|
||||
Location: Remote — 50 miles from HOST1
|
||||
Role: Mirror, failover coverage, independent services
|
||||
Domain: Gmer4Lfe.us (his own domain, his own services)
|
||||
Runs: His own independent Emby, his own containers, his own users
|
||||
Access to shared media library via mirrored shares
|
||||
|
||||
Network: Tailscale — encrypted tunnel between both servers
|
||||
Repo: Self-hosted Gitea on HOST1
|
||||
Deployment: git pull on either server → both stay current
|
||||
```
|
||||
|
||||
**The servers do not need to be identical hardware.** This is one of the most important design decisions in the ecosystem. Because everything is accessed through `/mnt/user/` — unRAID's fused share layer — the underlying disk count, pool layout, and hardware generation don't matter. A share called `Movies` on HOST1 is `/mnt/user/Movies`. The same share name on HOST2 is also `/mnt/user/Movies`. rsync syncs between them. Failover containers on HOST2 mount `/mnt/user/Movies` and see the same data. The hardware underneath is completely irrelevant.
|
||||
|
||||
```
|
||||
HOST1: Threadripper, 10 drives across 5 ZFS pools
|
||||
HOST2: i5, 4 drives, completely different layout
|
||||
Both: /mnt/user/Movies — identical path, same data, different everything else
|
||||
```
|
||||
|
||||
**What is actually mirrored:**
|
||||
|
||||
**Share names** — `/mnt/user/Movies` is `/mnt/user/Movies` on both servers. rsync syncs the content nightly. Container volume mounts use the same path. No path translation anywhere.
|
||||
|
||||
**Media shares** — all media is mirrored to HOST2. Since both servers mount the same share names, every container on HOST2 — Emby, the arr stack, everything — has access to the same library HOST1 serves. HOST1 is the source of truth. HOST2 is the mirror. They share the same data pool when failover kicks in — no separate libraries, no separate metadata, no separate databases for media.
|
||||
|
||||
```
|
||||
HOST1 /mnt/user/Movies → rsync nightly → HOST2 /mnt/user/Movies
|
||||
HOST1 /mnt/user/Tv_Shows → rsync nightly → HOST2 /mnt/user/Tv_Shows
|
||||
HOST1 /mnt/user/Music → rsync nightly → HOST2 /mnt/user/Music
|
||||
...all media shares mirrored...
|
||||
```
|
||||
|
||||
**Normal operation — HOST2 piggybacks on HOST1:**
|
||||
|
||||
In day-to-day operation HOST2 is essentially passive from HOST1's perspective. HOST1 handles everything — all arrs, all downloads, all transcoding, all active services. HOST2 keeps its mirror current and waits.
|
||||
**This is a genuine mutual failover agreement between two friends, each running a fully independent server.** Both servers are fully active in normal operation — each with their own service stack, their own domain, their own users. HOST2 is not a standby. He runs his own Emby, his own containers, and his own domain while sharing access to the mirrored media library.
|
||||
|
||||
```
|
||||
Normal operation:
|
||||
HOST1 — source of truth, all active services running
|
||||
HOST2 — mirror current, containers ready but stopped
|
||||
no arrs running (would create conflicts with HOST1)
|
||||
no downloaders running
|
||||
just keeping data fresh and ready to take over
|
||||
HOST1 — Gmer4Lfe.com — full stack, live TV, arrs, everything
|
||||
HOST2 — Gmer4Lfe.us — his Emby, his containers, his domain, his users
|
||||
Both independently serving media from the mirrored shared library
|
||||
```
|
||||
|
||||
**Don't run arrs on both servers simultaneously.** The arr stack manages your library — two instances writing to the same share causes conflicts, duplicate downloads, and database corruption. Either designate one server as the arr master (HOST1 in this setup) or split arrs between servers by type. HOST2's arrs only start during Tier 4 failover — when HOST1 has been down 18+ hours and workflow continuity is genuinely needed.
|
||||
|
||||
**Container names** — failover containers on HOST2 must use the same Docker container name as on HOST1. The failover script starts them by name via SSH. Server-specific containers get server-specific names:
|
||||
|
||||
**When HOST2 goes down:**
|
||||
```
|
||||
Shared containers — same name on both servers:
|
||||
Emby ← starts on HOST2 during HOST1 outage
|
||||
uses HOST2's mirrored media, same library
|
||||
NginxProxyManager ← same name, same config, same network
|
||||
Authelia ← same name
|
||||
|
||||
Server-specific containers — unique names:
|
||||
Emby-Gmer4Lfe ← HOST1's own Emby instance, always on HOST1
|
||||
Emby-Jayred365 ← HOST2's own Emby instance, always on HOST2
|
||||
VaultWarden-Gmer4Lfe ← HOST1's password manager
|
||||
VaultWarden-Jayred365← HOST2's password manager
|
||||
HOST1 detects HOST2 unreachable + internet up
|
||||
→ Starts HOST2's DDNS (Gmer4Lfe.us) on HOST1 — his domain stays live
|
||||
→ Starts HOST2's specific containers — his services keep running on HOST1
|
||||
→ HOST1's own services keep running unaffected — failover is additive
|
||||
→ Waits for HOST2 to come back stable (FAILOVER_HANDBACK_STRIKES checks)
|
||||
→ Hands everything back — his containers, his DDNS — returns to NORMAL
|
||||
```
|
||||
|
||||
**Docker custom networks** — containers communicate by container name within a custom network, not by IP address. When a container restarts and gets a new IP, NginxProxyManager still reaches it by name. Failover containers on HOST2 join the same named custom networks and are immediately reachable by NPM without any IP reconfiguration required.
|
||||
**When HOST1 goes down:**
|
||||
```
|
||||
HOST2 detects HOST1 unreachable + internet up
|
||||
→ Starts HOST1's DDNS (Gmer4Lfe.com) on HOST2 — my domain stays live
|
||||
→ Starts HOST1's Tier 1 containers — Emby, auth, live TV immediately
|
||||
→ Tiers 2/3/4 escalate if outage extends beyond configured delays
|
||||
→ HOST2's own services keep running unaffected — failover is additive
|
||||
→ Waits for HOST1 to come back stable and hands everything back
|
||||
```
|
||||
|
||||
**The hardware doesn't need to match.** `/mnt/user/` abstracts everything. A share called `Movies` is `/mnt/user/Movies` on both servers regardless of what drives or pools back it. rsync syncs the content. Container mounts use the same path. The hardware underneath is irrelevant.
|
||||
|
||||
**The shared media library:**
|
||||
|
||||
All media syncs from HOST1 to HOST2 nightly. HOST1 is the arr master and source of truth — all downloads, all library management happens there. HOST2 accesses the mirrored library with his own Emby instance in normal operation, and serves it via HOST1's failover Emby when HOST1 is down.
|
||||
|
||||
```
|
||||
Custom network: high-availability
|
||||
NginxProxyManager → Authelia (by name — IP changes are invisible)
|
||||
NginxProxyManager → Emby (by name)
|
||||
NginxProxyManager → NextCloud (by name)
|
||||
HOST1 /mnt/user/Movies → rsync nightly → HOST2 /mnt/user/Movies
|
||||
|
||||
HOST1's Emby → /mnt/user/Movies ← always
|
||||
HOST2's Emby → /mnt/user/Movies ← his own instance, same library
|
||||
Failover Emby → /mnt/user/Movies ← HOST1's Emby running on HOST2 during outage
|
||||
```
|
||||
|
||||
Don't run arrs on both simultaneously — two instances writing to the same share causes conflicts. HOST2's arrs only start at Tier 4 (18hr+ outage) when full workflow continuity is genuinely needed.
|
||||
|
||||
**Container naming convention:**
|
||||
|
||||
```
|
||||
Server-specific containers — always on their own server, unique names:
|
||||
Emby-Gmer4Lfe ← HOST1's personal Emby, always on HOST1
|
||||
Emby-Jayred365 ← HOST2's personal Emby, always on HOST2
|
||||
VaultWarden-Gmer4Lfe ← HOST1's password manager
|
||||
VaultWarden-Jayred365 ← HOST2's password manager
|
||||
|
||||
Shared failover containers — same name on both servers:
|
||||
Emby ← HOST1's main Emby, starts on HOST2 during HOST1 outage
|
||||
NginxProxyManager ← same name, same proxy rules, same networks
|
||||
Authelia ← same name
|
||||
```
|
||||
|
||||
**Docker custom networks** — containers communicate by name within custom networks, not by IP. When a container restarts and gets a new IP, NPM still reaches it by name. Failover containers join the same named networks on either server — no proxy rule changes, no IP reconfiguration, no downtime from IP drift.
|
||||
|
||||
**Personal shares — backup without failover:**
|
||||
|
||||
Beyond the shared media library, each user can sync personal shares to the other server purely for offsite backup — no failover container involvement, just data protection.
|
||||
@@ -235,7 +240,8 @@ Unraid_Scripts/
|
||||
├── Orchestrators/ # Sequential job runners
|
||||
│ ├── README-Orchestrators.md
|
||||
│ ├── daily_sync.sh # All media shares synced nightly
|
||||
│ └── media_management.sh # Permissions + cleaners + arr cleanup
|
||||
│ ├── media_management.sh # Permissions + cleaners + arr cleanup
|
||||
│ └── transcode_management.sh # Cleanup then manager every 3min + daily stats
|
||||
│
|
||||
├── Rsync/ # Core sync engine
|
||||
│ ├── README-Rsync.md
|
||||
@@ -274,7 +280,7 @@ Unraid_Scripts/
|
||||
│ └── zfs_pool_scrub.sh # Trigger ZFS scrub with completion report
|
||||
│
|
||||
└── unRAID_Essentials/ # Server-level system management
|
||||
├── README-unRAID_Essentials.md
|
||||
├── README-Unraid_Essentials.md
|
||||
├── system_watchdog.sh # Last line of defense — controlled reboot
|
||||
├── webgui_restart.sh # WebGUI nginx + emhttp auto-restart
|
||||
├── docker_syslog_filter.sh # Suppress Docker veth noise from syslog
|
||||
@@ -283,7 +289,7 @@ Unraid_Scripts/
|
||||
├── mover_stop.sh # Graceful mover termination
|
||||
├── rsync_stop.sh # Stop rsync + recover containers
|
||||
├── server_reboot.sh # Graceful reboot with user warning
|
||||
└── user_script_stop.sh # Stop all running User Scripts jobs
|
||||
└── user_scripts_stop.sh # Stop all running User Scripts jobs
|
||||
```
|
||||
|
||||
---
|
||||
@@ -338,8 +344,7 @@ php_fpm_max_children.sh
|
||||
docker_network_connect.sh
|
||||
|
||||
# ━━━ Frequent ━━━
|
||||
*/3 * * * * transcode_manager.sh
|
||||
*/5 * * * * transcode_cleanup.sh
|
||||
*/3 * * * * transcode_management.sh # replaces separate manager + cleanup entries
|
||||
*/10 * * * * webgui_restart.sh
|
||||
*/15 * * * * docker_watchdog.sh
|
||||
*/15 * * * * system_watchdog.sh
|
||||
@@ -377,7 +382,7 @@ Each folder has a detailed README covering setup, configuration, usage, and the
|
||||
| [README-Media.md](Media/README-Media.md) | Execution order, cleaner profiles, arr cleanup safety procedure |
|
||||
| [README-Transcoding.md](Transcodes/README-Transcoding.md) | Symlink indirection design, Docker mount warning, mode switching, sizing |
|
||||
| [README-Tools.md](Tools/README-Tools.md) | All utility scripts, when to use each, how to add new tools |
|
||||
| [README-unRAID_Essentials.md](unRAID_Essentials/README-unRAID_Essentials.md) | system_watchdog tiers, startup sequence, scheduled maintenance |
|
||||
| [README-Unraid_Essentials.md](unRAID_Essentials/README-Unraid_Essentials.md) | system_watchdog tiers, startup sequence, scheduled maintenance |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user