master.conf says unRAID-Jayred36 and the tailnet device is unraid-jayred365, so the exact-key lookup found nothing and every remote card rendered with no IP, no online state and no containers.
Windows with runs but no bytes say 'no data moved' rather than 0.00 GB, and rows before the byte-parser fix are excluded rather than summed into a false total.
A fresh install reproduced the single lump folder because Step 12 only ever called fallback_folder.php; it now mirrors the owner's layout first and hands the fallback folder just what is left.
Step 12 filed all thirteen deployed containers under <Owner>-Fallback, which says whose they are and nothing about what they do — and they are not failover coverage, they run there continuously.
The API answered and simply had no vms node, but that was recorded as an API fallback, and the monitor reads any fallback with a key present as 'Unraid API unreachable — check API key in host conf.'
The wizard had a Skip beside Create API Key and a second link that renamed itself Go to Scheduler/Partnership, so leaving early and finishing looked like the same action.
It was a browser flag set on click, and refreshing is the first thing anyone does when a page looks stuck — which put them back on the phase-1 panel the state exists to replace.
The mirror's own job ends in seconds while Phase 2 runs for minutes on the owner, so the screen sat unchanged on the phase-1 panel — which reads as a hang, and the reasonable response to a hang is to start clicking.
SSH_TIMEOUT comes from the calling script, so a caller without it made timeout fail before ssh ran; with stderr discarded the fallback then named this host's SCRIPTS_DIR as the remote's.
Step 1b ran the owner's SCRIPTS_ROOT path over SSH on the mirror, so it failed on every appdata install; the wizard poll expired at 5 minutes against a Phase 2 that takes over 4.
The lookup grepped for a quoted container name that appears in no Unraid template, so every offboard reported four WebUIs it could not reconfigure. The final sync counted a share synced whenever Tier 1 was on, ignoring rsync.sh's status entirely.
The .plg hardcoded the flash path and runs every boot, so an appdata node served a stale copy that never receives pulls — fixes appeared to do nothing, indefinitely.
With nothing blocking but optional keys unfilled the banner rendered an empty string, so a finished onboard showed a blank panel beside a Join button still greyed at Running.
The phase-2 branch of the mirror panel returned the same Join partnership / Onboard block as the not-started state, so a finished onboard read as one that never ran.
The guard tested Tier 1 only, so onboard Step 1d's posture — Tier 1 open, every Tier 2 closed — made a healthy partner climb toward auto-offboard every 30 minutes. The counter holds intervals, not days, and was rendered raw.
HOST<n>_PHASE*_DONE only ever describe the mirror, so on the mirror the owner's card computed phase 0 and offered to onboard the host that had just onboarded it.
The scp reused the local absolute path on the remote, so an appdata-mode mirror never received it, and nothing wrote the mirror's own state file at all — a fully onboarded mirror rendered as having no partnership.
grep -v > tmp && mv keeps the temp file's umask mode, so an offboard left authorized_keys 0666 and sshd StrictModes silently refused every key in it — including the one the next onboard installs.
A previous offboard blocklists the mirror and rsync.sh refuses blocklisted hosts, so on a re-onboard Step 1e was being refused and the auth stack would have deployed against empty directories.
Onboard now ends at Phase 2: connected, running, and saying so. Phase 3 sets the seeding gate posture and dispatches the seed. With MEDIA_SEED_ENABLED false there is no Phase 3 and the model is two phases.
Deploying first meant Authelia, Lldap, NPM and both databases initialised themselves against empty directories. The gate arming moves to Step 1d for the same reason: the provisioning sync is an rsync, and Tier 1 stops every rsync. Tier 2 now ends the onboard off rather than as-found.
Step 1 printed 'Rsync stopped' over a file-not-found, and the closing block asserted a clean separation and a synced auth config regardless of what happened.
A first seed is ~28 TB behind a 12.5 MB/s bwlimit, and it ran inline as Step 9d, so the
phase-2 flag every status reader depends on was written only after it finished.
Phase 1 exists to hand the partner its identity before the install, but the push refused any
host without varaverk.cfg — so the conf could only ever reach a node that no longer needed it
to be told who it was. It now resolves the remote's conf directory across both install layouts
and creates the internal one when neither exists.
Both checks already answered their question on demand and both needed
somebody to press a button on the right row. One host here has returned
nothing but 5xx for months.
Filed as findings, which is the existing answer to a condition that
persists while nobody is looking. Grouped by cause rather than by
hostname: a default policy of bypass produced twenty-two findings that
were one sentence repeated, and they have one fix between them.
A low uptime figure, a refused login and a certificate that stopped
renewing all looked the same from the row: a number, with the reason
split across NPM, an Authelia config and the directory.
The why-check goes and looks — TCP to the forward target, HTTP through
the proxy, a second handshake with verification off to tell a broken
certificate from a broken service. Forward hosts are docker names that
only resolve on NPM's network, so an unresolvable one is redirected to
the container address and the substitution is reported; a check that
could not be made must never read as a check that failed.
The access simulator walks the rules the way Authelia does and shows the
ones it stepped over, reading whichever instance the chosen host points
at rather than the one conf names — there are two here.
Cert triage counts runs rather than log lines and orders by rotation
suffix rather than mtime, both of which change the answer.
NPM's access log only describes hosts somebody visited; the host most likely to be quietly broken
is the one nobody does. Probes carry a User-Agent npm_access_stats.sh drops — unmarked, this
monitor would be fifty thousand requests a day in the very logs it reports on.
NPM writes an access log per host and counts nothing, so 475 MB of logs held the only answer to
"is anything using this". Aggregated on a schedule and read from a few kB of JSON; the row also
now says whether an auth_request block is in front of the site, which nothing showed before.
Saving a host sent advanced_config as an empty string and reset http2, both HSTS flags, meta,
locations and enabled — so changing a port removed the auth_request block that puts Authelia in
front of the site. Twenty-five of the thirty-five hosts here carry one.
NPM knows what a certificate is today and nothing about what it was, so ten of them could fail
renewal for months — 1001 certbot runs, zero successes — without anything on any page saying so.
Counts start at zero and are only ever observed; only first_seen is seeded, from NPM's own date.
NPM answers a successful DELETE with the bare literal true, which vv_npm_raw() is typed to
return an array from — so deleting or toggling a proxy host has always thrown a TypeError
rather than doing the thing.
Authentik is the likely destination and the page had Authelia and lldap wired in at every
level, so the seam goes in now: the panels and every endpoint action route off one conf value,
and a stack that cannot be driven yet says so rather than drawing controls with nothing behind.
Opening the editor to fix a name and then having to close it to reach a password or a group
was three dialogs for one sitting; the row buttons stay for one-click access from the list.
lldap lets you edit five things about a user and one about a group; the page reached two of
them, so correcting a surname or a group's name still meant opening the container's own WebUI.
The block is rebuilt from the parsed model on every save and the parser discarded comments,
so one press of Save deleted the five ## lines that are the only thing in the file saying
what each rule is for — which inline editing was about to make far easier to press.
Most rules carry thirteen or fourteen domains, which in one table cell was a four-hundred
character run that answered no question at a glance; the group is what you are looking for
and it is now the heading.
The value was written as typed, bash expanded it when the read-back sourced the file, and
the guard rolled the whole write back with nothing on screen but "save failed" — which is
also what an empty value, a trailing space, and a stale API-key check had been doing.
Not set, rejected and unreachable all reached the page as one message about checking
credentials, which sends you to a password when the field is simply empty — as both of
HOST1's were, with no card on the page to fill them in from.
vv_is_ai_host() was `=== 'host1'`, which made a physical fact — that is where the
GPU is — look like a rule. AI_OWNER_HOST declares it, so the card can move to a
rebuilt host3 or a friend's spare.
The gate was also doing two jobs. Assistant docks and findings strips now ask
whether a model is reachable, so a node without a GPU gets them by borrowing;
the AI tab asks whether this is the owner, because that page carries the bug
reports, the index and the model configuration — the surface where the
vocabulary assumes you built the mesh.
Resolution is local, then owner, then anyone else declaring a model, pinned once
it answers. Pinned rather than re-derived per call: a mesh that re-decides every
request eventually decides differently mid-conversation, and a chat whose second
turn lands on another machine has no history there. Cleared only on a transport
failure, and only when there is somewhere else to go — a single-node mesh whose
model is down should say so, not report AI as unconfigured.