Rewrite README and Manual front pages in project voice

The repo front page read like generic documentation rather than a record of
why any of this exists. Adds the origin story, the current honest state, real
failure history, and fixes drift in platform_*() naming, the fallback tier
variable pattern, and the Plugin/unraid script locations.
This commit is contained in:
Gmer4Lfe
2026-08-01 23:47:50 -04:00
parent 671bf2352b
commit c54039392d
2 changed files with 173 additions and 17 deletions
+110 -13
View File
@@ -23,6 +23,51 @@ correct adapter. The scripts themselves never branch on the OS.
---
## ━━━ HOW THIS GOT HERE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**One server. One script. Three lines.**
That's genuinely where this started. Something needed doing on a schedule, so I wrote three
lines and moved on.
Then it was two servers, 50 miles apart, and about **60 scripts** with nothing holding them
together. Every one standalone. Every one with its own hardcoded paths, its own container
names, its own idea of how to log something or send a notification.
**And it worked.** That's the part worth saying. The stack stayed up, the media kept playing,
the backups kept running. It was not broken.
It was just *miserable to change.*
Every adjustment meant finding every script that touched the thing, on both machines, and
editing each one the same way — then hoping I'd found them all. Miss one and it didn't error.
It just quietly kept doing the old thing until I noticed weeks later. Two servers meant two
copies of every mistake, and the two copies drifted apart a little more every time I touched
them.
So it got rebuilt, in roughly this order:
```
git stop editing live scripts on two machines and calling it version control
common.sh one place for log, notify, locking, host detection, retries
master.conf thresholds and toggles — shared, one copy
host*.conf credentials, paths, container names — per server
load_config.sh sources all of it, in the right order, at the top of every script
```
Then the long part: refactoring 60 standalone scripts into that shape, one at a time, until
every value lived in a conf file and every shared behaviour lived in `common.sh`. Change the
retry count once, every script gets it. Rename a container in one place, everything follows.
That is the whole idea, and it's why the structure looks the way it does. The three-file
config model and the shared library aren't design patterns picked out of a book — they're
the specific answer to "I have 60 scripts on two machines and I'm scared to touch any of
them."
That became Varaverk.
---
## ━━━ WHERE THIS ACTUALLY IS RIGHT NOW ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
This is a live system, not a finished product. HOST1 has been running the whole stack
@@ -57,7 +102,7 @@ HOST1 — unRAID-Gmer4Lfe
HOST2 — unRAID-Jayred365
Hardware: Intel i5 10th gen, 64GB RAM
Location: Remote — different building, different power utility
Location: Remote — 50 miles away, different power utility and ISP
Domain: Gmer4Lfe.us
Arrs: Anime_Shows, Anime_Movies — union with HOST1 via arr_sync
His own Emby — for his household
@@ -173,6 +218,10 @@ as sync targets and mount points — a mismatch is a broken path.
## ━━━ THE MEDIA LIBRARY MODEL ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Two households, one library, and a hard line between "our media" and "your stuff." Everything
in this section comes down to that split — media is pooled and shared freely, personal data
never is, and no script gets to blur the two.
### ── Common Libraries — Shared Pool ─────────────────────────────────────────
Common media like Movies, Music, and TV Shows are a **shared pool**. Every container
@@ -257,8 +306,13 @@ across separate shares per-user or per-application.
## ━━━ WHAT SYNCS AND WHAT DOESN'T ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Not everything needs to sync. Not everything should sync. Understanding what goes
where determines whether you need encryption and whether sync failure matters.
Not everything needs to sync. Not everything *should*. Two households means some of this
data is mine, some of it is his, and some of it belongs to both of us — and treating all
three the same way is how you end up either leaking someone's photos or losing the thing you
actually needed a copy of.
Where a piece of data lands in this table decides two things: whether it needs encryption,
and whether a failed sync is something to fix tonight or something to shrug at.
---
@@ -504,6 +558,15 @@ Monitoring:
## ━━━ FOLDER STRUCTURE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Folders are grouped by **what a script does to the system**, not by which service it happens
to talk to. There's no `Sonarr/` folder — cleaning up after Sonarr is media work, watching
whether its container is alive is watchdog work, and those two things belong next to their
own kind.
Every folder has its own README explaining the group, and every script has a header
explaining itself. If you're looking for one specific thing, the README reference near the
bottom of this page is the faster route.
```
varaverk/
@@ -563,6 +626,16 @@ varaverk/
## ━━━ CONFIGURATION — Configurations/ FOLDER, THREE FILES ━━━━━━━━━━━━━━━━━━━
This is the part that fixed the 60-script problem. Three files, one rule:
**Thresholds and toggles go in `master.conf`. Credentials, paths and container names go in
`host*.conf`.** If you find yourself about to hardcode a value in a script, it belongs in one
of these instead — that's the whole discipline, and everything else follows from it.
Sparse checkout means each server only ever receives its own `host*.conf`. HOST1 never has
HOST2's credentials sitting on disk, and vice versa. The partner's conf arrives at runtime
through the RAM cache, which is why `conf_sync.sh` exists.
```bash
# ─────────────────────────────────────────────────────────────────────────────
# All three conf files live in Configurations/. load_config.sh sources them.
@@ -642,7 +715,8 @@ Every 4 hours:
2:30am Sunday:
weekly_sync_maintenance.sh stop → update images → clean sync → start → weekly restarts
+ playback_aware_lidarr/radarr/sonarr_discovery.sh (behavior-driven arr discovery)
+ playback_aware_{lidarr,radarr,sonarr}_discovery.sh
(behaviour-driven discovery from real playback history)
8am daily:
weekly_health_digest.sh DIGEST_PROFILE controls when it actually notifies
@@ -714,8 +788,9 @@ restart lands on the new image. Change the order and things break quietly rather
## ━━━ THE SELF-HEALING STACK ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Problems are handled at the most appropriate level. Scripts escalate only when the
level below them has failed:
Nothing here jumps straight to the big hammer. Each layer only gets involved because the one
below it already tried and failed — and the layer holding the biggest hammer, the one that
can reboot the box, is the most reluctant of all:
```
Problem: Emby container using 22GB RAM (limit: 18GB)
@@ -833,7 +908,12 @@ CPU-based) instead of PaddleOCR. Same plugin, no VRAM.
## ━━━ SETUP — WHERE TO START ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
If you're setting this up from scratch on two servers:
If you're setting this up from scratch on two servers, the order below is not a suggestion.
Steps 2 and 3 are cheap now and expensive later — renaming a container or a share after the
confs, the fallback tiers and the sync profiles all reference it means touching every one of
them, and missing one doesn't error.
Do the naming first. Everything after it assumes the names are already right.
```
1. Follow Manual.md — end-to-end setup guide
@@ -854,6 +934,11 @@ If you're setting this up from scratch on two servers:
bash fallback_test.sh when ready — uses iptables simulation, no real downtime
```
**Do step 5.** Untested failover isn't redundancy, it's a belief. `fallback_test.sh` simulates
the outage with iptables rather than actually pulling the other server down, so there's no
excuse not to run it — and finding out your tier lists have a typo is a lot nicer on a Tuesday
afternoon than at 2am when the power's actually out.
---
## ━━━ FOLDER README REFERENCE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -976,15 +1061,18 @@ Every one of these cost me something to learn. Reading them here is cheaper.
# --dry-run --log first on a new system. README-Media.md has the full procedure.
# 9. Scripts never call OS commands directly.
# All platform-specific operations go through plugin_*() functions defined in
# All platform-specific operations go through platform_*() functions defined in
# Plugin/$PLATFORM/adapter.sh. rc.d scripts, emhttp, dynamix, disks.ini — all
# isolated in the adapter. This is what makes the codebase portable.
# Adding a new OS = writing one adapter file, not patching dozens of scripts.
# 10. System_Essentials/ is platform-agnostic at the script level.
# Scripts like server_reboot.sh, mover_stop.sh, and webgui_watchdog.sh call
# adapter functions (platform_is_mover_running, platform_restart_service, etc.)
# The adapter handles what those mean on the actual OS. The scripts are clean.
# 10. Top-level System_Essentials/ is platform-agnostic. Plugin/unraid/ is not.
# server_reboot.sh lives at the top level and calls adapter functions only —
# platform_is_mover_running, platform_restart_service. It never names an OS.
# Scripts that manipulate an Unraid subsystem directly — mover_stop.sh,
# webgui_watchdog.sh, php_fpm_max_children.sh — live under Plugin/unraid/
# instead, because there is no generic version of them to write.
# Which folder a script is in tells you whether it survives a platform change.
# ─────────────────────────────────────────────────────────────────────────────
```
@@ -996,4 +1084,13 @@ Every one of these cost me something to learn. Reading them here is cheaper.
Name: Varaverk
Repository: git@192.168.50.2:FailedProxy/Varaverk.git
Install path: /boot/config/plugins/varaverk
```
```
---
This is a home media stack for two households. It is not an enterprise product, it doesn't
want to be one, and it makes trade-offs no enterprise would accept — because the thing it's
actually optimising for is that nobody in either house has to know any of this exists.
The measure of success here isn't uptime percentages. It's that the power goes out 50 miles
away, and the show keeps playing.