Skip to content

Latest commit

 

History

History
533 lines (490 loc) · 34 KB

roadmap.md

File metadata and controls

533 lines (490 loc) · 34 KB

Roadmap

The tracking lives in Issues. This file is the shape of the work — what is outstanding, what gates it, and why it is in this order. Whether a thing is started, blocked or done is on its issue. What happened, and what it found, is in changelog.md, dated. Two places holding the same checkbox is how a checkbox stops being true, and for a month this file was the second place — #577 moved the history out.

The order is the seven milestones, each of which states what closes it. This file adds what a milestone cannot say: the order between them, and inside each the order and the gate where an issue cannot carry it alone.

What an entry here may contain:

  • A link, the gate, its place in the order, and why. Nothing else. No date except a gate that is a date.
  • When the issue closes, the entry leaves. Anything worth keeping goes to changelog.md as a dated entry, in the same PR.
  • An accepted ADR with work behind it has an issue in a milestone. One that does not is the bug, not a section here.
  • A PR that implies a purchase edits Everything still to buy in the same commit. That section is the one place a purchase enters or leaves, and the README's count of outstanding purchases is checked against it.

The order

  1. Nothing blocks these — first because nothing gates them, and three of them carry a date.
  2. trinity — the return on the box closes 2026-10-08, and the rehearsal is the step that ends it.
  3. NAS and Saruman: the domain, then the SOC — side by side, with no order between them. The domain, which everything else on Saruman points at, is built and closed; the NAS's first issue, the one-disk mirror, is done.
  4. automation — the pipeline that populates the domain; it runs from phoenix, which exists.
  5. last — gated on the domain, on a household observation, or on something to publish.
  6. Tier extras — decision-gated, and outside the order until one is decided.

Nothing blocks these

Closes when it is empty.

  • #444 Swap the MokerLink for the CRS326. Decided by ADR-0041. Gate: Phase 1 at the bench, then a rack window outside working hours — neo carries every VLAN, so the swap cannot share the day with anyone working on them. → runbook
  • #84 Retire the MokerLink's previous SNMP community. Closes with #444: the row cannot be verified, so it is retired by the hardware leaving, not by a measurement. → runbook
  • #574 Shut down on the UPS's signal. Decided by ADR-0049. Steps 0–4 were built on 2026-09-23: NUT on morpheus, its rules, and Saruman and smaug subscribed. The sequence is armed and not proved. The gate is a rack visit, which proves the order with upsmon -c fsd and pulls the mains once to replace the card's 47-minute claim with a number. Shares a window with #444 if its parts have landed. → runbook

The rest of the milestone has no order between its issues.

trinity

Closes when the nine services serve from trinity and the firewall restore has been rehearsed on it.

  • #92 Rehearse the firewall restore — done 2026-09-27. The machine was proved on 2026-09-26, inside the return window that closed 2026-10-08 (#674). The rehearsal restored config-20260926T043704Z — taken from oracle, schema 24.6, 112 rules — onto pfSense CE 2.9.0 on trinity in 42 minutes, and it booted with no interface-assignment prompt: WAN on em0, LAN on igc0, all six VLANs, 112 rules, the four tripwires, the twelve Tunnel_Peers rules and six Kea scopes, and a laptop tagged into VLAN 99 leased 10.0.99.100. Three things asked questions the runbook had not answered — Secure Boot (and HP's four-digit confirmation code), a kernel panic from the undisclosed Wireless-AC 9560 under iwm (fixed with hint.iwm.0.disabled), and an installer that needs the internet — and all three are now in §3. The box went to #404 with the I226 card still fitted. It was recorded as in the drawer until the build found it in the slot on 2026-09-28, and it stays there, unconfigured, for the day trinity has to be the firewall. → runbook

  • #404 Build the tier's host. Built and deployed 2026-09-28 (ADR-0034, → runbook). What is left:

    • the DNS failure test, which proves AdGuardNotAnswering pages (and closes #135);
    • the step 10 gate, which the first real photos passed on 2026-09-28 while most of it was still open: the second age recipient, the off-estate copy, ADR-0022's identity-provider record and ADR-0023's Independent test. The Immich restore rehearsal is done (#132, → runbook). Until #455 exists, the originals' only copy beyond the USB disk is the nightly one to oracle, in the same room (ADR-0064).

    #533's converge timer is authored and installs report-only; it closes when trinity applies and a Dependabot bump to stacks/sensitive lands with nobody at a shell (→ runbook). #534's CI re-check is already done (#646).

  • The nine services, each authored ahead of the hardware and each open until it serves from the host: #129 Caddy and #130 step-ca first, because everything else sits behind the one and is issued by the other (ADR-0037 — → runbook); then #135 AdGuard Home, serving since 2026-09-28 with morpheus forwarding to it alone (ADR-0010, ADR-0055) and both probes live, open only for the failure test (→ runbook); #131 Vaultwarden; #132 Immich; #133 Paperless-ngx; #134 Home Assistant (ADR-0035); #136 ntfy — authored, with the decision taken both ways at once: the in-house topics replace ntfy.sh for all three real channels, and urgent and security page ntfy.sh as well, because a phone away from home cannot reach the tier. The deploy and the observed end-to-end check remain (→ runbook); and #137 Homepage, authored on 2026-09-28 against the running tier: home.matrix.elysium, a directory and not a status page, with live numbers only where a read-only token can read them (Immich, Paperless-ngx) or none is needed (Prometheus), and its widget path measured through Caddy with placeholder tokens before the real ones exist. Deployed and reading real numbers since; on 2026-09-29 it took Tokyo Night, groups by VLAN, and four more tiles read from Prometheus (UPS, firewall, iLO, NAS) with no new rule or credential. The restore path is rehearsed already: → runbook.

  • #455 The off-estate copy. The drive is here. It was bought 2026-09-22 and arrived 2026-09-29 (hardware.md). The key is decided: on 2026-10-01 ADR-0073 settled the first of ADR-0023's two conditions. The copy is encrypted to the household holder's key, with ADR-0024's second recipient as a fallback. The keys are kept in stacks/sensitive/household.recipients and not in a sops rule. The drive holds age archives on exFAT. The copy is built: make household-copy carries it, HouseholdCopyStale watches it, and the holder's page is open-the-household-copy.md. The drive was formatted and rehearsed on 2026-10-01. What is left is a person: choosing the holder, and the holder opening the copy once from their own device, without the operator present. Both were meant to come before the tier held real data, and they did not. ADR-0022's first trigger, the first real photo, fired on 2026-09-28. Until this lands, ADR-0064's nightly copy to oracle stands in for the library, off-host and not off-estate. When this lands, it supersedes ADR-0064.

NAS

Closes when a workstation can mount the share. Its other condition, the faulted Exos replaced and the mirror resilvered, is met and is in changelog.md.

Saruman: the domain, then the SOC

Closes when it is empty. Both things its name names are done. The domain was built by hand on 2026-09-24 and 25, and #414 closed on 2026-10-02 with its authentication generator running and §10 read from Hicks. The SOC followed: Wazuh and Velociraptor reported the six agents in on 2026-09-27.

  • #671 Prove the lab's second key. secrets/lab.sops.yaml is encrypted to the offline technical second as well as alexander's key since 2026-10-07. What remains is make secrets-verify-backup STACK=lab KEY=… with the offline copy.
  • #920 One on-demand VM per dotfiles OS layer. It ships in four phases (ADR-0090):
    1. Debian, Fedora and Windows (test-the-dotfiles-layers.md);
    2. openSUSE and Arch;
    3. Alpine and Gentoo, from their published images;
    4. NixOS.
  • #921 garuda, an analyst workstation. Kali Purple without its SOC, always on beside odin, and the home of dotfiles-Defense (ADR-0091). It ships in three phases:
    1. Template 910, the guest, its tools and dotfiles (build-the-analyst-workstation.md).
    2. Enrolling it in Wazuh and Velociraptor, the first Linux guest in either (ADR-0092).
    3. OpenVAS on demand, scoped to the domain's six by nftables (ADR-0093).
  • #538, #529, #562 and #576 are the host's own blind spots, with no order between them. #576 watches the Proxmox firewall that #566 turned on, so it is the one of the four that has already lost its excuse for waiting.

automation

Closes on BloodHound running where nothing attacks it.

  • A chain, in this order: #440 Packer (done 2026-10-03, ADR-0074: 901 Ubuntu, 911 Windows 11 and 912 Server 2025 built from smaug-iso, each clone passing scripts/packer-smoke.sh, SSH included, → runbook; Kali's template waits for ifrit, #790) → #445 OpenTofu (done 2026-10-03, ADR-0076: state encrypted, escrowed, and both proofs run against a real apply, → runbook) → #448 Ansible and ADR-0029's six guests from the pipeline (written, ADR-0077, → ansible/; applied to the hand-built six on 2026-10-03, with a second run of changed=0 and verify.yml passing on all six; closes on a tofu destroy and rebuild, so it waits for the six to be declared in tofu/ with pinned MACs; #440's templates exist since 2026-10-03) → #449 users and deliberate weaknesses (the population and the authentication generator are --tags population,authgen, ADR-0078; what remains is the rest of build-the-lab-domain.md §5, which covers the tiers, the SPN account, the Tier 0 GPO and the shares, and then the weaknesses, each its own tag on top of the population) and #450 Sysmon and Pktmon (ADR-0080) → #451 BloodHound (ADR-0081, → runbook), which closes the milestone. All of it runs from phoenix (ADR-0043, → runbook). #440's templates read their installers from smaug-iso, the ISO store ADR-0072 put on erebor/iso. Every file there is hashed daily on Saruman against the list in scripts/collect-iso-store-state.sh, and IsoChecksumMismatch pages if one changes, because the export trusts an address and Packer does not check an ISO it is handed from storage. Copying the installers there, listing their hashes and installing the check is build-the-lab-templates.md §2b.

last

Gated on the domain, on a household observation, or on something to publish.

  • #421 Buy ifrit and build the range. Gated on #414 and the SOC: an attack VM pointed at an uninstrumented estate teaches nothing. Both are met. What gates the build now is its RAM kit and NVMe drive, in Everything still to buy, and its place in the #919 rack move. → runbook
  • #447 A cloud relay — only if there is ever something to publish; the day it exists it replaces the dynamic DNS record (ADR-0044).

Tier extras

Beyond ADR-0008's nine: each needs its own decision before it is authored, and none is in the order until one is taken.

  • #147 Miniflux — decided by ADR-0057, deployed on trinity 2026-09-29. What remains is committing the encrypted secrets/sensitive.sops.yaml that carries its two keys, and seeing miniflux-db-data in a nightly set.
  • #145 Memos — decided by ADR-0059 and deployed on trinity 2026-09-29, and reachable from Hicks by name the same day. The admin registered and closed registration on 2026-10-02. Nothing is left; #145 closes with this. It holds no real notes until ADR-0023's Durable condition is met, which is the tier's condition and not this issue's.
  • #146 Mealie, as recipes.matrix.elysium. Decided by ADR-0060 and deployed on trinity 2026-09-29. It is the one service here meant for the household to open rather than to benefit from. It uses no new firewall rule and no SOPS secret, and it has no second factor, which is named alongside Immich and AdGuard. The default admin was renamed and re-passworded the same day. Nothing is left.
  • #144 linkding — decided by ADR-0061 and authored in stacks/sensitive. Deployed on trinity 2026-09-29, with its host override, and the operator's first login with the superuser password from SOPS is done. Nothing is left.
  • #143 Stirling-PDF is deployed on trinity 2026-09-29 (ADR-0063): behind Caddy at pdf.matrix.elysium, login from SOPS, and its documents held on a tmpfs so none reaches a disk. The pdf override on morpheus is in, and TOTP is enrolled on the admin. Nothing is left; #143 closes with this.

Everything still to buy

The one list, because purchases kept appearing one at a time in issues, ADRs and runbooks until one box had been bought for two jobs (ADR-0034). Nothing enters the table without a decision the operator made, and a PR that implies a purchase edits this section in the same commit. Parts on hand are in hardware.md; a part in transit is its issue's to track. smaug's memory and the off-estate drive both left this table on 2026-09-22 by that rule, bought rather than dropped (#599, #455) — and it was bought to a different shape than the row described, which is in hardware.md and in changelog.md rather than here. The two Windows 11 Pro keys left it on 2026-09-25 by the same rule. They were bought and activated on the lab domain's two endpoints, carbuncle and siren (ADR-0029, #414). The replacement for smaug's faulted Exos never entered it. The eBay return came back as a refund rather than a new drive, and the drive was bought outright on 2026-09-24, the day the choice was known (#558). It is in hardware.md.

Buy these, and the estate as decided is fully bought. The table was empty from 2026-09-25 until ifrit was bought on 2026-10-05, short of the spec its ADR set; its last two rows are what it still needs. On 2026-10-13 the move into the 32U rack (#919) put its parts here, which had been listed only in its runbook's §0.1, and Saruman's memory joined them. Already on hand, so not listed: the frame, the VESA mount, trinity's ProDesk tray and the velcro.

Item For Decided by When it is needed
Four-post shelf, adjustable to 29", at least 17" deep, rated for 50 lb or more. StarTech ADJSHELFHDV fits: 19.5–38", 27.5" tray, 330 lb smaug on its side, U5–U9 hardware.md, 2026-10-12 Before the #919 window
2 × 1U four-post vented shelf, adjustable to 29" prometheus U10, oracle U12 hardware.md Before the #919 window
1U sliding keyboard drawer, front-rail mount The console, U24 hardware.md Before the #919 window
1U mount made for a ThinkCentre Tiny, holding its brick ifrit, U18 hardware.md Before the #919 window
1U horizontal cable manager U20, between switch and panel hardware.md Before the #919 window
1U vented blank U22, the air gap over the CRS326 hardware.md Before the #919 window
One factory-made Cat6 patch cable, long enough for the run The XB7's striped 2.5G port to morpheus's em0, replacing the hand-crimped patch #923 Now: it should not wait for the move
Short factory-made Cat6 patch cables, a pack, in the ADR-0009 VLAN colours Switch to patch panel in the new rack move-into-the-32u-rack.md §6.1 Before the #919 window
Spare M6 cage nuts and screws, a pack The frame move-into-the-32u-rack.md §0.1 Before the #919 window
8 × 16 GB DDR4 RDIMM, dual-rank, matched to a fitted stick's label (2Rx4 or 2Rx8, PC4-2400) Saruman, 128 GB to 256 GB, one more per channel on both CPUs The operator, 2026-10-13: headroom In the #919 window, while the DL360 is out of the rack
2 × 16 GB DDR4 SO-DIMM kit ifrit, replacing the 8 GB it shipped with ADR-0017: 32 GB socketed Before build-the-playground.md §1
1 TB NVMe SSD ifrit's range and its snapshot reverts ADR-0017: NVMe Before build-the-playground.md §1

The last one, bought 2026-10-05: ifrit, the range host — a quiet SFF box, NVMe, two socketed DIMM slots with 32 GB fitted, one NIC (ADR-0017, #421). The box is a refurbished ThinkCentre M80q, and it arrived on 2026-10-14. It shipped with 8 GB and a 256 GB SSD, so the two rows above are still to buy and fit. hardware.md records the box.

Only if a decision is taken, and none is pending — these are not on the list, and each names what would put it there:

  • A dedicated firewall cold spare: deferred by ADR-0034 until the tier holding real data makes an hour of firewall downtime unacceptable. There is one ProDesk, not two — trinity is the tier's host and the firewall's spare hardware — and the reserved name zion belongs to the box this bullet would buy (ADR-0038).
  • A Zigbee or Z-Wave coordinator for Home Assistant: only if a device needs one, and nothing on Skids does today — Ring is cloud, Hue has its own bridge, the assistants are Wi-Fi (#134).
  • More memory for ifrit than ADR-0017's 32 GB: only if 32 GB proves short. Reaching 32 GB is above, in the purchase itself.
  • A Coral TPU and RTSP cameras: declined with Frigate (ADR-0032).
  • A reachable address for the WireGuard endpoint, in either of its paid forms: ADR-0044 answers it with a free dynamic DNS record instead. A static address is not sold on the residential service the house buys and enters only if that service changes; a VPS relay is #447's purchase, entered when there is something to publish.

Never, and the documents say so: anything to make prometheus or oracle faster or bigger, and any disk or memory on account of Wazuh — ADR-0030 sizes it to what Saruman has. A 2012 MacBook running the whole observability stack is the point, not a problem to spend money on.

The one exception, and it narrows this line rather than reversing it: a consumable whose failure is a safety or availability event is not an upgrade. prometheus's cell was that case and is replaced (#454); so is oracle's, fitted 2026-09-29 (#531). Nothing else about either machine is.

Considered and declined

The mirror of the roadmap, and recorded for the reason turned around: a service rejected for good reasons with nothing written down is indistinguishable from one nobody thought of. It gets proposed again, evaluated again, and can be deployed on the second pass because the first pass left no trace (#150).

These are declines, not bans. Each records what was weighed, so a later proposal argues with the reasoning rather than restarting from nothing — and several of them name the condition that would change the answer.

  • Nextcloud — the obvious "one app for everything" answer, and declined because it overlaps three services already chosen: Immich (#132) for photos, Paperless-ngx (#133) for documents, and file sync. It is more surface and more upkeep than all three together, and its app ecosystem is a second, unpinned supply chain operating outside compose.yaml — the same objection that rules out Home Assistant add-ons in #134. If the want is file sync rather than a suite, Syncthing does that with no server-side application at all, and would be the thing to evaluate instead.
  • The *arr stack — Sonarr, Radarr, Lidarr and the indexer and subtitle services around them. Five or more services, each holding indexer credentials and each with a standing outbound appetite, added to the tier ADR-0008 deliberately defined as low consequence. The media tier's whole justification is that its compromise costs a film night; this raises what is at stake there while adding the most moving parts of anything on the list. Declined for now rather than permanently — but it should be its own decision with its own reasoning, not a footnote to the NAS build.
  • YunoHost-class installers — YunoHost, Tipi, HomelabOS, StartOS and similar. They own the compose file, the update path and often the reverse proxy, which conflicts with essentially everything this repository does on purpose: one compose stack per host (ADR-0004), every image pinned by tag and digest, configuration validated in CI, secrets rendered from SOPS at deploy time. Adopting one trades the properties that make this estate reproducible for a faster first install. Wrong trade here — and the trade, not the software, is the reason.
  • Guacamole — a clientless browser-reachable RDP/VNC gateway. Convenient, and a larger concession on the management segment than SSH already is: it turns any browser session on Hicks into a potential path to every console in the estate, and it stores connection credentials to do it. The estate already has a KVM in U6 for physical console access. Declined. The remote-access question it gestured at is answered differently by ADR-0042: WireGuard to the lab jumpbox, terminating on ImaginationLAN and reaching the lab only. That is not a softening of this decline — it stores no connection credentials at a gateway, it never touches Winterfell, and the boundary is the firewall's rather than an application's. Guacamole's objection was about the management segment, and nothing about ADR-0042 goes near it.
  • Frigate — locally-processed object detection on camera streams, and the one service on the shortlist that would change the network's shape rather than its population: continuous RTSP from every camera through the 99 → 20 rule ADR-0008 authorised for Home Assistant's occasional control traffic, a clip archive that is the most sensitive data store in the house on the management segment, and a Coral or GPU the sensitive tier does not have. Declined by ADR-0032 on a fact that comes before all four: every camera on Skids is a Ring device, and Ring exposes no local stream, so Frigate has nothing to consume. Adopting it is a camera replacement first, which is its own decision. Reopened by RTSP cameras, an accelerator, and a separate row in ADR-0008's table for the continuous rule — all three, each decided on its own (#149).
  • Plex — the media server the household already knows, with polished clients, and ADR-0008 listed it beside Jellyfin for that reason. It is also the one proprietary service on the shortlist: clients authenticate through plex.tv even on a local network, nobody outside the vendor can read the image that digest pinning fixes, and features have moved behind a subscription before. ADR-0016 deferred it against one test, whether any screen on CasaBonita lacks a working Jellyfin client, and the test was run by 2026-09-28: the LG OLED, a console, and the phones and tablets all play from Jellyfin, and the Xumo box is not used for the library. Declined by ADR-0056. Reopened by a screen the household uses for library media that has no working Jellyfin client, with Remote Access off even then (#139).
  • HomeBox — a home inventory with items, locations, warranties and receipts as attachments. It was proposed for the sensitive tier as the place for the serials hardware.md withheld. By the time it was argued, hardware.md carried the serials and warranty dates itself. Paperless-ngx already held the receipts and manuals, and a licence key is Vaultwarden's. What remained was a list of household objects, which does not earn a place on the segment ADR-0008 calls its real cost, and which would be a second inventory that drifts from the first. Declined by ADR-0058. Reopened by a household need to track non-infrastructure possessions that Paperless's tags cannot meet, with the proposal saying what leaves hardware.md so there is still one inventory (#148).
  • Proxmox clustering — joining Saruman and ifrit into one cluster once #421 makes them two Proxmox hosts on VLAN 30: one pane of glass, guest migration, shared storage. The first entry here that is a capability rather than a service, and declined by ADR-0039 because a cluster is one /etc/pve, one realm and one quorum across exactly the boundary ADR-0007 draws — root on the attacker's host becomes root on the estate's — and cannot be built without the second NIC or VLAN-aware bridge ADR-0014 names as grounds to reopen it, on a host that is off between sessions by design and would take the estate's hypervisor's quorum down with it. Reopened by a third host that is neither attacker nor defended estate, a live-migration need that snapshot-and-rebuild does not serve, or ifrit ceasing to hold attack tooling — each its own decision (#443).
  • Authelia / Authentik — already decided, and listed only so the next shortlist does not present it as new. ADR-0008 defers SSO knowingly for two users with no external access; ADR-0022 gives that deferral an expiry, which is what #103 closed on. An identity provider is also the only route to a second factor for Grafana, Immich and AdGuard Home, none of which can carry one themselves — so this decline has a known end, unlike the others here. Pocket ID, the lighter passkey-only provider, has been weighed and changes nothing until a reopen condition fires. It is the first candidate when one does (#860, the note on ADR-0075).

Done

What closed, when, and what it found is in changelog.md, newest first. An entry leaves this file on the day its issue closes and goes there with the date.