architecture: the system poster committed, its facts given a home, and a rule to keep them together
gates / gates (push) Failing after 5m29s
gates / gates (push) Failing after 5m29s
PART A -- the poster. documentation/architecture/felhom-system-poster.html
(307 KB). Secret scan first: ZERO IPv4, zero PEM blocks, zero ssh keys, zero
Bearer. The one EAA... match is base64 inside an embedded "mime":"font/woff2"
blob, not a Facebook token. "token"/"secret"/"password" appear 11 times and
every one is a NAME ("6. ep0 read token", "the hub seal key"); the poster
itself says "Names only; no secret values". All five long base64 blobs are
declared assets: 1 image/png, 3 text/javascript, 1 font/woff2.
It renders with NO network: the source mentions cdn.jsdelivr.net and Google
Fonts, but the loaded requests are only the HTML plus blob:/data: URLs -- the
bundler inlined everything. Measured, not assumed, and it matters: this is a
disaster-recovery document, so needing the internet to draw would be a defect.
No console errors.
The operator's three Claude Design fixes are all present: (a) no "WG" badge,
WireGuard only for the tunnel, no badge on the ep0-copy tile; (b) the box ->
ep0 arrow reads "encrypted on the box, sent through WireGuard"; (c) "Known
gaps" holds two items and NOT the household-keys sentence, which is now a
neutral "By design" note under the ep0 household namespace.
ONE FACT ON IT WAS WRONG. The felhom.eu tile said "served from DooPlex through
Cloudflare". It is not: Cloudflare is DNS only and the traffic goes direct --
measured this morning for the privacy notice, which states exactly that. The
poster would have contradicted a published page. Fixed in place (a label):
"served from DooPlex, Cloudflare DNS only". The first wording overflowed the
fixed-size tile, so it was shortened to fit and the evidence lives in the
facts file instead -- checked by re-rendering, not by hoping.
PART B -- the facts and the rule. DESIGN-PROMPT-...md is renamed
felhom-system-poster.facts.md (one home per fact), with the three fixes folded
in as explicit instructions so a regeneration cannot undo them, plus a new
"Badges" section saying a "WG" chip must never come back.
New rule, section 6 "The system poster stays true", added IDENTICALLY to all
five copies of unprompted-work.md (the four repos and the workspace root on
DooPlex; verified identical by diff before and after) and to
PROMPT-TEMPLATE.md's end-of-session checklist as a FIFTH coupled artifact.
scripts/poster_facts_gate.py WARNS when the facts file has a newer commit than
the poster. It never fails a push, deliberately: a refresh needs Claude Design
and the operator, --no-verify is forbidden here, so a blocking gate would leave
deleting it as the only way out. It compares COMMIT times, not mtimes, because
a checkout rewrites mtimes and every fresh clone would shout.
RED-PROOF -- and it found a real bug in the gate. The first run warned
correctly but exited 1: a single non-ASCII character in its own warning raised
UnicodeEncodeError on this cp1250 console. A gate whose entire contract is
"never fails a push" was failing pushes. Fixed (ASCII output + an encode
guard), and the decoy now asserts BOTH the warning and exit 0. Three branches
proven: facts newer -> warns, rc 0; poster newer -> quiet, rc 0; poster
missing -> "could not tell", rc 2, not a false all-clear.
The decoy itself was seen to fail, twice, on Linux (the suite needs fcntl and
cannot run on Windows): breaking the warning gives STALE_WARNS=False, and
making it exit 1 gives RC_STALE=1. All 80 felhom.eu decoys behave.
PART C -- do box reports pass through Cloudflare? NO. Two channels. DNS from
PUBLIC resolvers (not DooPlex's own, which answers the LAN address):
hub.felhom.eu is a CNAME to dooplex.hopto.org -> 37.191.56.193, not a
Cloudflare address, and no cf-ray comes back. The manifest: an ordinary k3s
Ingress, Cloudflare named only in a DNS setup comment. THE CONTROL that makes
the negative mean something: iso.felhom.eu resolves to 172.67.x / 104.21.x,
real Cloudflare addresses -- so the method does detect proxying.
So nothing is added to the Cloudflare row: the hub path does not touch it.
06-offsite-connectivity.md section 1 claimed the public edge is a
Cloudflare-Tunnel and "DooPlex has no public IP" -- both untrue today. Kept
and marked STALE with the measurement rather than rewritten, because that
paragraph is the reason ep0 exists and the argument needs its premise visible.
total-loss-of-dooplex.md's "today a CNAME to dooplex.hopto.org" is confirmed
correct.
Register: 137 before, 137 after, 0 opened, 0 closed -- every finding here was
small and fixed in the session.
This commit is contained in:
@@ -366,6 +366,15 @@ Decisions made, architectural state, what's next.
|
||||
`felhom.eu/documentation/{architecture,controller}/`. Spikes/audits → `felhom.eu/documentation/audits/`.
|
||||
|
||||
### N.5 The coupling rule — FOUR artifacts, same session (end-of-session checklist)
|
||||
|
||||
> **FIVE, when a poster fact moved.** **The system poster stays true** — a task that changes a fact
|
||||
> listed in `architecture/felhom-system-poster.facts.md` (a machine, a role, a traffic path, a backup
|
||||
> tier, a time, a retention, a key, a known gap) updates **that file in the same commit**. If the
|
||||
> change is text only, it also edits the matching text in `felhom-system-poster.html`. If it needs a
|
||||
> new drawing, it adds **"System poster needs a refresh: <what changed>"** to `STATUS.md`'s
|
||||
> "waiting on the operator" list. **The report names which of the three it did.** The poster is drawn
|
||||
> in Claude Design and nothing here renders it, so `scripts/poster_facts_gate.py` only WARNS when the
|
||||
> facts outrun the drawing — it never fails a push. Same wording in `.claude/rules/unprompted-work.md` §6.
|
||||
If the task **changed what the platform can do** (new/removed capability, a capability moved status,
|
||||
or **what is open changed**), update **all four** in the SAME session:
|
||||
- **`architecture/00-capability-map.md`** — add/adjust the affected *scenario* row with the correct
|
||||
|
||||
@@ -23,6 +23,11 @@ The operator's one-page picture of what is proven, built, partial and missing.
|
||||
- [`architecture/where-felhom-stands.yaml`](architecture/where-felhom-stands.yaml) — the data behind it; every claim cites its source. Gate: `scripts/check_stands.py`; regenerate with `scripts/render_stands.py`
|
||||
- [`architecture/where-felhom-stands-2026-08-09-snapshot.html`](architecture/where-felhom-stands-2026-08-09-snapshot.html) — **a dated snapshot, NOT maintained.** The original React bundle, kept for the record; its statuses are those of 2026-08-09 before the verification pass
|
||||
|
||||
### The whole system on one page — `architecture/felhom-system-poster.*`
|
||||
A poster for the operator: every machine, path, backup tier, time and key on a single sheet.
|
||||
- [`architecture/felhom-system-poster.html`](architecture/felhom-system-poster.html) — the drawing. **Made in Claude Design, NOT generated by anything in this repo**, so do not expect a renderer; it is self-contained (fonts and scripts are inlined — it opens with no network)
|
||||
- [`architecture/felhom-system-poster.facts.md`](architecture/felhom-system-poster.facts.md) — **the source of every fact on it. Change the facts here first.** Rule: `.claude/rules/unprompted-work.md` §6. Gate: `scripts/poster_facts_gate.py` WARNS (never fails) when this file has a newer commit than the drawing
|
||||
|
||||
### Host agent & platform — `architecture/`, `proxmox-platform.md`
|
||||
The operator-tier agent and the Proxmox platform.
|
||||
- [`architecture/01-topology-and-trust.md`](architecture/01-topology-and-trust.md) — topology & trust model
|
||||
|
||||
@@ -38,6 +38,27 @@ customer box cannot reach it at all. The DR crypto/identity side is done and dri
|
||||
(`SPIKE-dr-recipe-2026-06-16.md`); **this transport is the last missing piece**, and the spike
|
||||
proved the cheapest transport suffices.
|
||||
|
||||
> **STALE AS OF 2026-10-09 — the two transport facts in the paragraph above are no longer true, and
|
||||
> the gap they describe is closed.** Kept rather than rewritten, because the paragraph is the reason
|
||||
> ep0 exists and the reasoning only makes sense with its premise visible.
|
||||
>
|
||||
> **MEASURED 2026-10-09, two channels.** (1) DNS, from public resolvers (`@1.1.1.1` and `@8.8.8.8`,
|
||||
> **not** DooPlex's own, which answers the LAN address): `hub.felhom.eu` is a **CNAME to
|
||||
> `dooplex.hopto.org` → 37.191.56.193**, which is **not** a Cloudflare address, and
|
||||
> `curl -sI https://hub.felhom.eu/` returns **no `cf-ray`** header. (2) The manifest: the hub is an
|
||||
> ordinary k3s Ingress and `manifests/hub.yaml` names Cloudflare only in a setup comment about
|
||||
> pointing DNS at the cluster. **The control that makes this mean something:** `iso.felhom.eu`
|
||||
> resolves to `172.67.183.101` / `104.21.18.218` — real Cloudflare addresses — so the method does
|
||||
> detect proxying when it is there.
|
||||
>
|
||||
> So: **DooPlex is reachable on a public address today** (a dynamic-DNS name, No-IP `dooplex.hopto.org`,
|
||||
> S13 in `runbooks/total-loss-of-dooplex.md`), and **the hub's public edge is NOT a Cloudflare
|
||||
> Tunnel** — boxes reporting to `hub.felhom.eu` reach the home connection directly. Cloudflare is
|
||||
> DNS for that name and nothing more. What Cloudflare *does* carry is the households' **app** traffic
|
||||
> through their tunnels, which is a different path and is the one the system poster's "Known gaps"
|
||||
> box is about. `runbooks/total-loss-of-dooplex.md` §9's "today a CNAME to `dooplex.hopto.org`" is
|
||||
> correct and was confirmed by this measurement.
|
||||
|
||||
---
|
||||
|
||||
## 2. Decisions (settled — recorded, not re-litigated)
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
# felhom-system-poster.facts.md — the source of every fact on the poster
|
||||
|
||||
> **This file is the source of every fact on `felhom-system-poster.html`. Change the facts here
|
||||
> first.** The poster is a drawing made from this list in Claude Design; it is not generated by a
|
||||
> script in this repository, so nothing but discipline keeps the two together — which is why
|
||||
> `scripts/poster_facts_gate.py` warns when this file has a commit newer than the poster, and why
|
||||
> the shared rule file carries **"The system poster stays true."**
|
||||
>
|
||||
> **How to use it.** A session that changes a fact listed here (a machine, a role, a traffic path, a
|
||||
> backup tier, a time, a retention, a key, a known gap) edits THIS file in the same commit. If the
|
||||
> change is text only, it also edits the matching text in the poster. If it needs a new drawing, it
|
||||
> adds a line to STATUS's "waiting on the operator" list and the operator regenerates the poster in
|
||||
> Claude Design from this file. The session report says which of the three it did.
|
||||
>
|
||||
> **History.** Written 2026-10-09 as `DESIGN-PROMPT-infrastructure-infographic-2026-10-09.md` and
|
||||
> renamed here the same day, with the operator's three Claude Design fixes folded in (marked *fix
|
||||
> (a)/(b)/(c)* below) and one measured correction: felhom.eu is served from DooPlex with
|
||||
> **Cloudflare DNS only**, not through Cloudflare.
|
||||
|
||||
---
|
||||
|
||||
## # Claude Design prompt — "Felhom: the whole system on one page" (state of 2026-10-09)
|
||||
|
||||
> Paste everything below the line into Claude Design. Facts were read from the live repository on 2026-10-09
|
||||
> (`01-topology-and-trust.md`, `06-offsite-connectivity.md`, `07-backup-architecture.md` §6.1, `11-os-updates.md`,
|
||||
> `runbooks/total-loss-of-dooplex.md`, `runbooks/ep0-datastore-copy.md`, `audits/dooplex-survival-2026-10-09/PLAN.md`).
|
||||
> No secret, key value, password, token or IP address is in this prompt, and none may appear on the poster.
|
||||
|
||||
---
|
||||
|
||||
## What to make
|
||||
|
||||
One **large poster-style infographic** (landscape, roughly A1 / 1600×1100 px or larger) that shows the whole Felhom system at a glance: every machine and its role, one example customer box opened up, how traffic flows, **what is backed up where, when, and with which key**, and what survives if the operator's home server is lost. It is for the operator (one person) who has lost track of what is backed up where. Clarity beats decoration. Every label must be readable when printed on A2.
|
||||
|
||||
**Style:** calm, technical, light background, a dark-mode-friendly palette is not needed. Use one colour per *kind of thing*, and keep it the same everywhere:
|
||||
- **Green** = household data (apps, files, photos).
|
||||
- **Blue** = backup copies (each tier its own shade of blue, numbered).
|
||||
- **Orange** = operator infrastructure (code, hub, password manager, signing keys).
|
||||
- **Purple** = keys and secrets (shown as key icons with *names only*).
|
||||
- **Grey** = outside services (Cloudflare, Hetzner, mail service).
|
||||
- **Red** outline = a single point of failure or a known gap.
|
||||
Arrows: solid = data traffic; dashed = backup copy; dotted = control (reports, jobs). Every arrow gets a short label and, for backups, a time.
|
||||
|
||||
**Layout (left to right, three zones, plus two strips):**
|
||||
1. **Left zone — "The household's home":** one example customer box, opened up.
|
||||
2. **Centre zone — "The internet":** Cloudflare, Hetzner (ep0 and the Storage Box), the mail service.
|
||||
3. **Right zone — "The operator's home":** DooPlex and the test machines.
|
||||
4. **Bottom strip — "One night, hour by hour"** (a timeline 00:00 → 09:00).
|
||||
5. **Right-hand column or bottom-right box — "If DooPlex is lost"** and **"Keys that must exist on paper"**.
|
||||
A small legend in a corner.
|
||||
|
||||
---
|
||||
|
||||
## Zone 1 — the customer box (draw one, opened up like a cutaway)
|
||||
|
||||
Title: **"A Felhom box (example: one household)"**. A small PC running **Proxmox** (the host operating system).
|
||||
|
||||
Inside, from bottom to top:
|
||||
- **The Proxmox host.** Runs the **host agent** (Felhom's operator-tier program: it holds the only Proxmox key, does backups and restores of the whole guest, OS updates, drive management). The agent never accepts a connection from outside; it **polls the hub** for signed jobs.
|
||||
- **The customer guest** (one Linux container per household, ID 9201). Inside it, **Docker**, running:
|
||||
- the **controller** (the household's dashboard and the app manager; it has no Proxmox key),
|
||||
- **Traefik** (routes each web address to its app),
|
||||
- **cloudflared** (the tunnel to Cloudflare, so no router setup is needed),
|
||||
- **the apps** — draw 4–6 small app tiles labelled with real catalog names, e.g. Nextcloud, Immich, Paperless-ngx, Vaultwarden, Jellyfin, Mealie, and a "+50 more" tile (the catalog has 56 apps).
|
||||
- **The drives:**
|
||||
- the **system disk** (Proxmox + the guest),
|
||||
- **data drive 1** (household data and the **Tier-1** backup folder),
|
||||
- an optional **data drive 2** (the **Tier-2** copy).
|
||||
Note on the drawing: the data drives are attached to the guest from the host; the **whole-guest backups do not include the data drives** (that is what the per-app tiers are for).
|
||||
|
||||
Arrows out of the box:
|
||||
- **Household's phone / laptop → Cloudflare → cloudflared → Traefik → app** (solid, green). Label: "Remote access. HTTPS ends at Cloudflare's edge, so Cloudflare could technically see this traffic (later item: our own relay)." Also a short local arrow: "At home on the LAN: direct to Traefik."
|
||||
- **Box → hub** (dotted): "Reports every few minutes; asks for signed jobs. The hub never connects into a box."
|
||||
- **Box → ep0** (dashed, through a small padlock tunnel labelled **WireGuard**): "Whole-guest backup, encrypted on the box, sent through WireGuard." — *fix (b), 2026-10-09: the label must name BOTH, because "encrypted on the box" alone read as if WireGuard were doing the encrypting.*
|
||||
- **Box → Hetzner Storage Box** (dashed): "Per-app off-site backup (restic), encrypted on the box. The box's key can only ADD copies; old copies are removed only in a weekly clean-up window the hub opens."
|
||||
- **Box → mail service** is not needed; the hub mails households.
|
||||
|
||||
## The backup tiers of a customer box (a table or stacked bars next to Zone 1)
|
||||
|
||||
Title: **"Where a household's data is copied"**
|
||||
|
||||
| Tier | What it copies | Where | When | Kept | Locked by |
|
||||
|---|---|---|---|---|---|
|
||||
| **Tier 1 — recovery unit** | each app: its settings, database dump, volumes | data drive 1, on the box | nightly at **02:30** (W) | 1 point per app | not encrypted (it never leaves the home) |
|
||||
| **Tier 2 — cross-drive** | a mirror of Tier 1, plus the app's files | data drive 2, on the box (only if the household has 2 drives) | nightly **03:30** | mirror | not encrypted |
|
||||
| **Tier 3 — off-site, per app** | Tier 1 + the app's must-keep files | **Hetzner Storage Box** (Germany), one folder per household | nightly **04:15** | 7 daily, 4 weekly, 6 monthly | the household's own restic password |
|
||||
| **Whole guest — local** | the guest's system (not the data drives) | the box's own system disk | daily, in the window **04:30–08:30** | up to 3 copies (fewer on a small disk) | not encrypted |
|
||||
| **Whole guest — off-site** | the same | **ep0** (Hetzner, Germany), one namespace per household | weekly, same window | last 2 | the household's own key, escrowed with a recovery code |
|
||||
|
||||
Footnote: "W = the household's backup window start, 02:30 by default. Tiers 1–3 follow at fixed offsets so they cannot run out of order. A missed night is caught up 15 minutes after the box starts."
|
||||
|
||||
## Zone 2 — the internet
|
||||
|
||||
- **Cloudflare** (grey): DNS for the customer domains and for felhom.eu; the **tunnels**; the **geo-block** (only Hungarian visitors); flood protection. The hub holds a Cloudflare key per customer zone and checks that it reaches only that customer's own domain.
|
||||
- **ep0** (grey box with an orange stripe, a Hetzner cloud server in Germany): runs the **WireGuard endpoint** and the **off-site backup server (PBS)**. Inside, one datastore with **namespaces**:
|
||||
- one namespace **per household** (whole-guest copies, each household's own key),
|
||||
with a NEUTRAL note under it (not a red gap box): "By design: each household holds the key to its own copies; the operator cannot open them without their recovery code." — *fix (c), 2026-10-09: this is a property of the design, not a gap, and a red box said the opposite of what it means.*
|
||||
- the **`operator`** namespace: two groups — **"hub database"** and **"DooPlex copy"** (code, password manager, secrets, signing keys).
|
||||
Prune jobs on ep0: households keep the last 2; `operator` keeps 14 daily + 8 weekly.
|
||||
Mark ep0 with a small shield: "**Protected** — holds the only off-premises copy of real household data."
|
||||
- **Hetzner Storage Box** (grey): the shared box for the households' per-app restic copies (Tier 3), one sub-account per household, add-only keys.
|
||||
- **Mail service** (grey, "Resend"): every mail the hub sends — to the operator and to households.
|
||||
- **The public website** felhom.eu (served from DooPlex — Cloudflare DNS only, the traffic does not pass through it; MEASURED 2026-10-09: the public A record is the home address, not a Cloudflare one, and no `cf-ray` header comes back) and **iso.felhom.eu** (where households download the installer): draw them as two small web pages near Cloudflare. Do not draw where iso.felhom.eu is hosted.
|
||||
|
||||
## Zone 3 — the operator's home
|
||||
|
||||
**DooPlex** (big orange box, the home server; mark it "**Protected — everything else can be rebuilt from it**"). Inside it, a small Kubernetes cluster (k3s) and host services. Show these parts as tiles:
|
||||
- **Gitea** — all the code (10 repositories) and the **container registry** (the images the boxes run). The CI runner runs here too.
|
||||
- **The hub** — customer records, box reports, the job queue, alarms, the escrow of household keys, the System page (OS updates, kernel approvals).
|
||||
- **Vaultwarden** — the operator's password manager.
|
||||
- **Prometheus + Alertmanager** — the operator's alarms.
|
||||
- **The signing keys** — they sign every agent update and config bundle a box accepts.
|
||||
- **The website** (felhom.eu) and the contact form's mailer.
|
||||
- **Local backups** — several restic sets on DooPlex's own disks (red outline: "all on the same machine").
|
||||
- **ep0-copy** — a nightly pull of the whole ep0 datastore back to DooPlex (ciphertext only; DooPlex cannot read households' copies).
|
||||
|
||||
Arrows from DooPlex (dashed, orange → ep0):
|
||||
- **00:20 "DooPlex copy"**: the code (614 MB), Gitea's database and settings, the **password manager**, the nightly secrets export, the **signing keys**. Encrypted on DooPlex with the **DooPlex off-site key**. The key that writes it **cannot delete** old copies. Tested back every Sunday.
|
||||
- **02:30 "Hub database"**: encrypted with the **hub-DB key**. Tested back every Sunday at 04:30.
|
||||
- **Left out on purpose:** the container registry (27.7 GB) — "rebuilt from the code".
|
||||
Arrow ep0 → DooPlex (dashed, 05:00): "**ep0-copy** pull: a second copy of ep0 at home. Keeps 8 weekly copies. A daily job removes a deleted customer's copy within 30 days."
|
||||
|
||||
**The test machines** (small, plain tiles near DooPlex, labelled "disposable"):
|
||||
- **demo-hp** (a mini PC) — ring 0: it gets OS updates, Docker and kernels first. Also hosts the **scratch guest 9202** (a second guest with no hub link, for tests) and the **Tester 1** virtual machine (a whole Felhom box inside a VM).
|
||||
- **demo-felhom** (an Intel N100 mini PC) — ring 0.
|
||||
- **The test bench** — a throwaway guest where app updates are tested before any box gets them.
|
||||
- **Tester 2** — the first outside tester's laptop, at his own home. Draw it in Zone 1's colour family, as a second, smaller customer box, with a note "real household, often off".
|
||||
|
||||
## Control and updates (a small panel, dotted arrows)
|
||||
|
||||
Title: **"Who tells a box what to do"**
|
||||
- The **hub** queues jobs; the operator **signs** each one; the **agent** checks the signature before it acts.
|
||||
- **Updates, in rings:** ring 0 (demo boxes) first → the operator approves on the System page → ring 1 (customers).
|
||||
- **Apps:** each new app version is tested on the bench and the scratch box first; boxes update at night, after a fresh backup.
|
||||
- **Debian security fixes:** nightly, after the whole-guest backup.
|
||||
- **Proxmox programs, Docker, the kernel:** slow lanes, one approved set at a time.
|
||||
- **Kernel:** the household gets a mail the day before; the box restarts at night; a crash falls back to the old kernel by itself; a freeze needs someone to unplug the box.
|
||||
- **Hub buttons** (no signature needed, a fixed safe list): off-site backup now, run a check now, stop or extend a deletion countdown.
|
||||
|
||||
## Bottom strip — "One night, hour by hour"
|
||||
|
||||
A horizontal timeline from **00:00 to 09:00**, two rows:
|
||||
- **DooPlex row:** 00:00 database dumps · **00:20 DooPlex copy → ep0** · **02:30 hub database → ep0** · 03:30 ep0 prunes households · 03:45 ep0 prunes `operator` · **05:00 ep0-copy pull → DooPlex** · 07:30 ep0-copy prune · 08:00 deleted-customer clean-up. Sundays: 04:30 restore tests.
|
||||
- **Customer box row:** **02:30 Tier 1** · **03:30 Tier 2** · **04:15 Tier 3 off-site** → app updates → **04:30–08:30 whole-guest backup** (local daily, off-site weekly) → Debian fixes → (when approved) Proxmox, Docker, kernel restart. 05:00 the hub checks every box made its backup.
|
||||
- A small note: "Household mails about a kernel restart go out the day before, 09:00–20:00."
|
||||
|
||||
## Right column — "If DooPlex is lost"
|
||||
|
||||
Two lists side by side:
|
||||
- **Survives (off DooPlex):** ep0 (the DooPlex copy and the hub database, plus every household's whole-guest copies); the Hetzner Storage Box (households' per-app copies); the boxes themselves (they keep running and backing up, but cannot report or update until the hub is back); the operator's workstation.
|
||||
- **Lost and not in any copy:** the container registry (rebuild from code), DooPlex's own SSH key, local build files, Prometheus history, other homelab apps.
|
||||
|
||||
A short numbered path: "1 New machine → 2 Reach ep0 → 3 Open the DooPlex copy with the **paper key** → 4 Password manager first → 5 Gitea → rebuild images → 6 Hub (mail held) → 7 Point DNS at the new home → boxes reconnect by themselves."
|
||||
|
||||
## Right column, bottom — "Keys that must exist on paper, away from home" (purple)
|
||||
|
||||
Show as a row of key icons with **names only** (never values):
|
||||
1. **DooPlex off-site key** — opens the DooPlex copy (the key to everything else).
|
||||
2. **Hub-DB off-site key** — opens the hub database copy.
|
||||
3. **Hub seal key** — opens the console passwords inside the hub.
|
||||
4. **DooPlex backup passphrase** — opens the secrets export.
|
||||
5. **Signing keys** (recovery + operational) — let the operator update boxes again.
|
||||
6. **ep0 read token** — reads the copies.
|
||||
7. **Hetzner login** — reaches ep0 if DooPlex is gone.
|
||||
8. **Cloudflare login** — moves DNS to the new home.
|
||||
Plus one in a "head" icon: **the password-manager master password** (memorised, never written on the sheet).
|
||||
Caption in red: "**A key kept only in the password manager is not off DooPlex** — the password manager runs on DooPlex."
|
||||
|
||||
## Badges — what may and may not carry one
|
||||
|
||||
*fix (a), 2026-10-09.* **"WG" is not a badge.** The whole-guest backup tier carries no "WG" tag;
|
||||
the word **WireGuard** appears only where the WireGuard tunnel itself is meant (the box → ep0
|
||||
padlock, and ep0's own "WireGuard endpoint" role). **The ep0-copy tile carries no badge at all.**
|
||||
A regeneration that puts a "WG" chip back on a backup tier has reintroduced the error.
|
||||
|
||||
## Small boxes for known gaps (red outlines, one line each)
|
||||
|
||||
- Cloudflare can read remote-access traffic (HTTPS ends at its edge) — a later item: our own relay.
|
||||
- DooPlex's local backups all sit on one machine; only the DooPlex copy and the hub database leave it.
|
||||
|
||||
## Header and footer
|
||||
|
||||
- **Header:** "Felhom — the whole system on one page" and "State of 9 October 2026".
|
||||
- **Footer:** "Sources: architecture documents 01, 06, 07, 11 and the total-loss runbook in the felhom.eu repository. Names only; no secret values."
|
||||
|
||||
**Do not invent** anything that is not above (no extra servers, clouds or services). If something does not fit, drop detail from the app tiles first, never from the backup table, the timeline or the key list.
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user