diff --git a/README.md b/README.md index 698bd6d..686c419 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ documents for different readers. the Makefile, the scripts, the workflow and the runbooks resolves its image from `compose.yaml` too, so an image that is not pinned there cannot be run at all. -- **Documented decisions and runbooks.** 33 ADRs covering what was chosen +- **Documented decisions and runbooks.** 34 ADRs covering what was chosen and what was rejected — including the costs accepted knowingly; 20 runbooks for the operations that are easy to get wrong at 1am, one of which is the handover page a successor reads first. @@ -325,8 +325,14 @@ Open work is tracked in [`docs/roadmap.md`](docs/roadmap.md) is the narrative — what is outstanding and why it is in that order. -The current top items: rack the shelf switch, and buy the spare ProDesk that -turns the firewall's restore runbook from a hypothesis into something rehearsed. +The current top items: rack the shelf switch, rehearse the firewall restore on +the ProDesk bought on 2026-09-08, and then build the sensitive tier on that same +box ([#404](https://github.com/Gerrrt/HomeLab/issues/404), [ADR-0034](adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md)). **Every purchase still outstanding, in one place:** a +second drive for that box sized to the photo library, and the NAS +([#95](https://github.com/Gerrrt/HomeLab/issues/95)). A dedicated firewall +spare is deferred, not on the list. This sentence used to name three purchases +coupled to the UPS work and omit the tier's host entirely, which is how one +ProDesk came to be bought for two jobs. The UPS is finished — a pack went into `mjolnir` on 2026-08-28, passed its self-test, and the card is set to test itself every fortnight ([#93](https://github.com/Gerrrt/HomeLab/issues/93)) — but the switch between @@ -334,7 +340,7 @@ the monitoring host and the network still has no battery at all, so both laptops stay running and go deaf on a mains cut ([#110](https://github.com/Gerrrt/HomeLab/issues/110), reopened on 2026-09-08 after a commit message had closed it by accident); and the config export -itself now leaves the monitoring host nightly, so the spare is what is left +itself now leaves the monitoring host nightly, so the rehearsal is what is left ([#92](https://github.com/Gerrrt/HomeLab/issues/92)). ## License diff --git a/docs/adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md b/docs/adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md new file mode 100644 index 0000000..5425f9c --- /dev/null +++ b/docs/adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md @@ -0,0 +1,114 @@ +# ADR-0034: Run the sensitive tier on the ProDesk, and make it the spare hardware + +**Status:** Accepted · 2026-09 + +## Context + +[ADR-0008](0008-place-services-by-data-trust.md) put the sensitive tier — +Vaultwarden, Immich, Paperless-ngx, Home Assistant, behind Caddy and step-ca, +with AdGuard Home, ntfy and Homepage alongside — on a mini PC on Winterfell, +and said in its consequences: *"New hardware is required … Two purchases where +the plan originally assumed zero."* Separately, +[#92](https://github.com/Gerrrt/HomeLab/issues/92) asked for a cold spare for +the firewall: the same ProDesk 600 G4 model as `morpheus`, so a pfSense restore +goes straight through, racked on a shelf and **left powered off** so that a +spare on the network is not exposed to whatever took the primary. + +Those are two machines. Only one of them was ever on the shopping list. +`README.md`'s "current top items" sentence named the UPS pack, the shelf +switch and the spare ProDesk, and every session that answered "what should I +buy" answered from it. The tier's host lived in ADR-0008's consequences and, +from 2026-09-04, in one roadmap paragraph; +[#102](https://github.com/Gerrrt/HomeLab/issues/102) closed that day by +splitting into one issue per service, and the box itself got none. No spec +was ever written beyond "low-power mini PC" and, twice in passing, +"N100-class". + +On 2026-09-08 one ProDesk 600 G4 was bought — i5-8500T, 32 GB, 512 GB SSD — +as the spare, because that was the only ProDesk anyone had been told to buy, +and in the belief that it would also host the tier. This ADR decides what it +is for, rather than treating a second purchase as the default. + +**What the tier's workload actually is**, read from its issues rather than +from the phrase "low-power": Immich's machine learning is the most +memory-hungry thing that will run in the estate +([#132](https://github.com/Gerrrt/HomeLab/issues/132)); Paperless OCR takes +every core it is given for minutes at a time +([#133](https://github.com/Gerrrt/HomeLab/issues/133)); Postgres with the +vector extension, Redis and Home Assistant sit beside them; and seven more +services have been proposed for the same box since. Six cores and 32 GB fit +that. Four cores and 16 GB, which is what "N100-class" means in practice, is +the box on which #132 already expects to disable the machine learning on day +one. + +**What the cold spare actually protects against.** A dead `morpheus`, restored +in twenty minutes at 1am rather than in an hour. The config it would restore +is exported nightly, encrypted, verified and copied to `oracle` +([ADR-0015](0015-give-oracle-the-off-host-jobs.md)); the restore path exists +without the spare, onto any hardware, with an interface-assignment dialogue in +it. And the drill that #92 exists for — proving the runbook is not a +hypothesis — needs the box on a bench once, not in a drawer for a year. + +## Decision + +**The ProDesk bought on 2026-09-08 is the sensitive tier's host.** It is +rehearsed on first, as the firewall spare, and it is the firewall's spare +hardware for as long as there is no other. + +1. **Rehearse the firewall restore on it before it holds anything.** + [`restore-the-firewall.md`](../runbooks/restore-the-firewall.md)'s bench + procedure, on this box, closes the rehearsal half of #92 on exactly the + hardware that would be the spare in a disaster. That is a better-tested + restore path than a powered-off box nobody has booted. +2. **Then wipe it and build the tier**, under + [#404](https://github.com/Gerrrt/HomeLab/issues/404), which is the tracker + the host lost when #102 split. The order there is the one + [ADR-0022](0022-expire-the-sso-deferral-when-the-tier-holds-real-data.md) + and [ADR-0023](0023-keep-the-household-recovery-path-outside-the-estate.md) + require: disk encryption decided, the stack built empty, the off-estate + copy proven, TOTP enrolled, and only then the first real photo. +3. **In a disaster the tier box is the spare hardware.** If `morpheus` dies, + the tier box is wiped and the newest export restored onto it — same model, + so the interface names match and the restore goes straight through. The + tier is down until a replacement ProDesk arrives. ADR-0023 already says one + mini PC cannot be made highly available and nothing the household needs in + an emergency may run through it, so "the tier is allowed to be down" is a + property this estate has already accepted, not a new one. +4. **The cold spare is deferred, not rejected.** #92's objection to a + powered-on spare — a box holding the firewall's config, reachable on the + network — does not apply to a box running Immich. What is given up is the + twenty-minute restore. A dedicated spare is bought when the tier holding + real data makes an hour of firewall downtime, and the household services + down with it, unacceptable; that is a judgement to make then, with the data + in hand, not now. + +The 512 GB disk is enough for everything on the tier except the photo library. +The G4 has a free bay; a second drive is sized when the library's size is +known, under #404, and is the only purchase this decision leaves outstanding +for the host. + +## Consequences + +- **One box does two jobs, and the second job destroys the first.** A firewall + restore onto this box is a wipe of the tier. That is the whole trade, and it + is written into `restore-the-firewall.md`'s *Afterwards* section: order a + replacement ProDesk the same day, because until it arrives the estate has no + password manager, no photo library and no Home Assistant. +- **#92 narrows to the rehearsal.** The purchase half is done by this box; the + "racked on the shelf, powered off" half is withdrawn. + [`fit-the-ups-battery.md`](../runbooks/fit-the-ups-battery.md) step 2, item + 4 no longer applies; the shelf carries the switch and nothing else until + #404 decides where the host lives — which is also where + [#134](https://github.com/Gerrrt/HomeLab/issues/134)'s USB radio question + is answered, since a rack in a closet is a poor place for one. +- **The shopping sentence in `README.md` names every outstanding purchase**, + not the three coupled to the UPS work. A sentence that answers "what should + I buy" and omits a machine is how this decision came to be needed, and it is + the same defect class [ADR-0026](0026-check-the-documents-where-the-truth-is.md) + describes: prose about what is outstanding that nothing checks. +- **ADR-0008 is not superseded.** Its placement and its "two purchases" hold; + this ADR decides which machine one of them is and defers the other. +- **Reopened by:** the tier holding real data and a firewall failure costing + more than an hour being judged unacceptable — buy the dedicated spare and + restore #92's shelf paragraph; or the tier outgrowing this box, which is a + second tier host and this box becoming the spare after all. diff --git a/docs/hardware.md b/docs/hardware.md index 09f1d0b..d515c3c 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -80,6 +80,13 @@ revisions of this repository treated `shiva` as the hypervisor itself. the unmanaged switch that feeds `prometheus` and `oracle`. It is not in the rack table above because it is not yet in the rack ([#110](https://github.com/Gerrrt/HomeLab/issues/110)) +- HP ProDesk 600 G4 Micro — i5-8500T, 32 GB, 512 GB SSD, the same model as + `morpheus` — ordered 2026-09-08, in transit. The sensitive tier's host and + the firewall's spare hardware in a disaster + ([ADR-0034](adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md)). + It enters the Compute table when + [#404](https://github.com/Gerrrt/HomeLab/issues/404) builds it, after the + firewall restore has been rehearsed on it. - USB stick holding the pfSense installer — **in transit; it belongs in the rack beside the KVM once it arrives**, and is not there yet. [`restore-the-firewall.md`](runbooks/restore-the-firewall.md) lists it as diff --git a/docs/roadmap.md b/docs/roadmap.md index d5419c9..52dd624 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -318,11 +318,16 @@ what left this one unfireable for months. converge in one run from any divergence. The far side's login shell is zsh, where an unmatched glob is fatal rather than literal, so the prune deletes by explicit basename and sends no pattern over the wire at all. - What remains is the spare — the same ProDesk model, racked on the #110 - shelf, powered off — and the rehearsal, which is what turns + What remains is the rehearsal, which is what turns [`restore-the-firewall.md`](runbooks/restore-the-firewall.md) from a hypothesis into a runbook; it now carries the bench procedure to follow and - what to record. Writing that procedure found the runbook's own decrypt + what to record. **The box to rehearse on is bought**, 2026-09-08 — the same + ProDesk 600 G4 model, i5-8500T, 32 GB — and [ADR-0034](adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md) + decides it is not a cold spare on a shelf: it is rehearsed on first, then + wiped and built as the sensitive tier's host ([#404](https://github.com/Gerrrt/HomeLab/issues/404)), and it is the + firewall's spare hardware in a disaster at the cost of the tier being down + until a replacement arrives. The powered-off shelf spare is deferred to the + day that cost is unacceptable. Writing that procedure found the runbook's own decrypt command had never been run: it passed `--input-type binary`, which sops rejects on the first byte of a real export, so a restore following the runbook would have stopped at step one. Fixed, and it is the kind of thing @@ -340,8 +345,9 @@ what left this one unfireable for months. battery at all — the pack in #93 protects the rack, not the monitoring path. **The shelf is on hand; what is left is the rack visit**, to the spec measured at the rack on 2026-08-21: 4-post, square holes, full 1U with rear support - rather than a cantilever. The spare ProDesk from - [#92](https://github.com/Gerrrt/HomeLab/issues/92) racks here too, powered off. + rather than a cantilever. The shelf carries the switch and nothing else: + the ProDesk from [#92](https://github.com/Gerrrt/HomeLab/issues/92) is the + sensitive tier's host ([ADR-0034](adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md)), and [#404](https://github.com/Gerrrt/HomeLab/issues/404) decides where that lives. **Reopened 2026-09-08.** GitHub had closed the issue on 2026-08-27, when the commit that wrote the runbook said the switch's power move "is the one that closes #110" and the phrase was read as a close keyword. Nothing was racked; @@ -359,13 +365,17 @@ what left this one unfireable for months. 664. The pages survive a disk failure because Wiki.js syncs from the Lemmiwinks repository; the accounts, history and configuration do not. - **[#102](https://github.com/Gerrrt/HomeLab/issues/102) Build ADR-0008's - sensitive tier on VLAN 99.** A low-power mini PC running Vaultwarden, Immich, + sensitive tier on VLAN 99.** One box running Vaultwarden, Immich, Paperless-ngx and Home Assistant behind Caddy and step-ca, with AdGuard Home, - ntfy and Homepage alongside. Nothing is bought and nothing is built. The - placement is not the outstanding part — ADR-0008 settled it, and + ntfy and Homepage alongside. **The box is bought and nothing is built.** It + is the ProDesk 600 G4 of 2026-09-08, by [ADR-0034](adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md) + — the one purchase this tier needed, made under #92's name because the + tier's host had no issue and no place in the shopping sentence after this + issue split; [#404](https://github.com/Gerrrt/HomeLab/issues/404) is the tracker it lost. The placement is not the + outstanding part — ADR-0008 settled it, and [ADR-0010](adr/0010-keep-the-resolver-on-the-gateway.md) has since been - decided on top of it. What is outstanding is a purchase, a stack, and four - firewall rules the ADR counted as two. + decided on top of it. What is outstanding is the build under #404, a stack, + and four firewall rules the ADR counted as two. **ADR-0010 costs more to implement than it reads, measured 2026-09-04.** Unbound on `morpheus` is recursive and DNSSEC-validating with zero @@ -609,7 +619,8 @@ with nothing tracking it is indistinguishable from a rejected one after six months. - **[#102](https://github.com/Gerrrt/HomeLab/issues/102)** ADR-0008's sensitive - tier — the mini PC, its nine services and the four firewall rules. Under + tier — its host (#404, the ProDesk of ADR-0034), its nine services and the + four firewall rules. Under **Infrastructure** above, because it has a shape now rather than only a decision. - **[#103](https://github.com/Gerrrt/HomeLab/issues/103)** The SSO deferral diff --git a/docs/runbooks/fit-the-ups-battery.md b/docs/runbooks/fit-the-ups-battery.md index 12cb413..bf5eb8d 100644 --- a/docs/runbooks/fit-the-ups-battery.md +++ b/docs/runbooks/fit-the-ups-battery.md @@ -146,10 +146,11 @@ the cases that genuinely need the wire, and reads the credential from SOPS. closes #110. A switch that has been relocated onto a shelf but left on a wall socket is tidier and no better protected — the laptops still go deaf on a mains cut. -4. **Rack the cold-spare ProDesk from - [#92](https://github.com/Gerrrt/HomeLab/issues/92) beside it**, cabled for - its cold-spare role and **left powered off**. A spare that is plugged in and - on the network is exposed to whatever took the primary. +4. **Nothing else racks here.** This step used to rack the cold-spare ProDesk + from [#92](https://github.com/Gerrrt/HomeLab/issues/92) beside the switch, + powered off; [ADR-0034](../adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md) + makes that box the sensitive tier's host instead, and + [#404](https://github.com/Gerrrt/HomeLab/issues/404) decides where it lives. 5. **Fit the APCRBC115 pack** last, per the Smart-UPS front-bezel procedure, and confirm the card comes back with the battery-replacement date reset. diff --git a/docs/runbooks/restore-the-firewall.md b/docs/runbooks/restore-the-firewall.md index f2fdf78..ec63e87 100644 --- a/docs/runbooks/restore-the-firewall.md +++ b/docs/runbooks/restore-the-firewall.md @@ -171,6 +171,14 @@ different hardware drops you into the interface-assignment dialogue at the console, at whatever hour this is happening. `morpheus` also uses a USB NIC for the switch-management LAN, so the spare needs one too. +**The spare is the sensitive tier's host**, by +[ADR-0034](../adr/0034-run-the-sensitive-tier-on-the-prodesk-and-make-it-the-spare-hardware.md): +the same model, running Immich and the rest. Step 0 is therefore wiping it, +and everything on it is gone until a replacement ProDesk arrives — order one +the same day (§5). The rehearsal below is done on this box before it holds +anything ([#404](https://github.com/Gerrrt/HomeLab/issues/404), step 1); until +it has been, this section is still a hypothesis. + 1. Install the same pfSense version the backup came from. **Restoring a config onto an older build can fail silently**; check the `` field, which `make backup-firewall` prints on every verify. @@ -264,8 +272,12 @@ And once the denials are verified, verify the thing that watches them. ## 5. Afterwards - Take a fresh backup from the restored box — the old one is now historical. -- If a spare was consumed, order another. A spare used once and not replaced is - a spare you no longer have. +- If the spare was consumed, order another ProDesk the same day. Since ADR-0034 + the spare is the sensitive tier's host, so consuming it took the password + manager, the photo library and Home Assistant down with the firewall, and + they stay down until the replacement is built. A spare used once and not + replaced is a spare you no longer have — and here it is also a tier you no + longer have. - Record what happened in [`roadmap.md`](../roadmap.md) if the cause is something the design should prevent. @@ -314,9 +326,10 @@ and to write the answers back into §3. power-on to verified, and everything that asked a question. Put it in [`roadmap.md`](../roadmap.md) under #92, fix §3, and delete the hypothesis sentence above. -6. Shred the plaintext, power the spare off, and rack it on the U4 shelf - ([#110](https://github.com/Gerrrt/HomeLab/issues/110)) beside the switch — - **off**. A restored spare on the shelf turns §3 into "move the cables and - power on", at the cost of carrying a config that ages from the day it was - restored; on the day, still restore the newest export from `oracle` over it - before trusting it. +6. Shred the plaintext and hand the box to + [#404](https://github.com/Gerrrt/HomeLab/issues/404): it is wiped and built + as the sensitive tier's host (ADR-0034). Nothing on it survives the + rehearsal, which is why the rehearsal comes first. The powered-off shelf + spare that used to be this step is deferred by that ADR; if it is ever + bought, it racks on the U4 shelf beside the switch, **off**, and on the day + the newest export from `oracle` is still restored over whatever it carries.