Skip to content

docs(adr): ADR-0041 — the CRS326 runs RouterOS, keeps neo, and serves TLS - #491

Merged
Gerrrt merged 1 commit into
mainfrom
gerrrt/replace-neo-switch-tls-3ecdec
Sep 17, 2026
Merged

Gerrrt merged 1 commit into
mainfrom
gerrrt/replace-neo-switch-tls-3ecdec

Conversation

@Gerrrt

@Gerrrt Gerrrt commented Sep 17, 2026

Copy link
Copy Markdown
Owner

What changed

Nothing, to the running lab. neo is still the MokerLink and still on plain
HTTP. This adds ADR-0041, which decides how the already-bought CRS326 is
configured, and swap-the-switch.md, the three-phase procedure for the
cabling window. ADR-0018's banner is amended to point at both.

Why

#444 has already moved past the
decision its body asks for: the switch was bought on 2026-09-13 and recorded by
#463, the buy table is down to two rows, and the correction comment narrowed the
justification to one property — the TLS management interface, with #84 riding
along. What is left is a cabling window, and the device is not here (delivery
estimate slipped to 2026-09-23).

ADR-0018's note said the successor ADR would be written when the switch was
racked. That is the wrong time. neo carries every VLAN, so the swap is a
house-wide outage, and an outage is not when to weigh a dual-boot device's two
operating systems. This decides the half that cannot be changed later; the
serial, MAC and shipped firmware go to hardware.md at the bench.

What ADR-0041 decides: RouterOS over SwOS (SwOS is HTTP-only and v1/v2c-only
— it reproduces the limit the purchase exists to escape). The name neo and
10.7.7.2 are inherited and the switch LAN stays, for a reason it did not
originally have: network.md explains that LAN as a workaround for a UI that
would not bind to a tagged interface, which is the MokerLink's limit and leaves
with it — it survives because an untagged link to morpheus is the way back in
after a bad bridge VLAN-filtering commit. www-ssl from an estate-CA leaf, not
the tier's (a switch cannot ask for an ACME renewal, and blackbox already
verifies estate-CA leaves by ca_file). SNMPv3 authPriv, v2c off. Mirroring
stays disabled per ADR-0006 — buying a device that can mirror was never a
decision to mirror.

Two things the issue's own cutover list does not mention, both in the
runbook:

  • network.md:251 blocks the switch LAN apart from 10.7.7.2:80. Disabling
    plain www before widening that pass to 443 leaves a correctly configured
    switch that Hicks — the workstation running the window — is not allowed to
    reach. Widen, prove, then close 80.
  • SECURITY.md records that the MokerLink's SNMP community leaked into a
    session transcript on 2026-08-20 and was deliberately not rotated, because
    rotating it meant repeating the residual. That reasoning expires with the
    hardware only if the value does too, so commissioning derives nothing from it.
    (Raised by the session working Retire the MokerLink switch's previous SNMP community #84; verified against SECURITY.md before
    writing.)

Also: no per-port VLAN map exists anywhere in this repository, so capturing one
off the MokerLink is the first bench step — 26 cables and no map is how the
house comes back wrong.

Blast radius

None now. The estate runs unchanged until the window. The runbook's Phase 3 is
where network.md, generator.yaml, the SNMP and blackbox targets and
snmp-verify.sh change, and none of them are touched here — two peer sessions
own #84 and #85 and those files are theirs until then.

One thing that could still imply a purchase, flagged rather than assumed: 26
copper ports are replaced by 24 plus two SFP+. If the port census shows more
than 24 populated, an SFP+ copper module edits Everything still to buy in the
same commit. The buy table is unchanged by this PR#463 already took the
switch's row off it.

  • No change to network segmentation or firewall rules
  • No new port published to a VLAN that could not already reach the service
  • No credential added outside secrets/*.sops.yaml

Verification

  • python3 scripts/check_docs.py — green at 10 assertions. It caught
    the README counts, as it did on ADR-0039 and ADR-0040: 40 ADRs → 41 and
    25 runbooks → 26. The tree comment at README.md:210 was separately stale
    at 39 and is corrected to 41.
  • ./scripts/lint.sh --require-all — all five linters pass. markdownlint
    is the gate that matters here: ADR-0018's supersede note is folded into
    its existing blockquote
    , because two adjacent blockquotes are MD028.
  • Every relative link in both new files resolves. One was wrong on the first
    pass — ADR-0013 is superseded by ADR-0025, which is the current firewall
    record.
  • make validatevia CI, not locally. Validate configs, Lint and
    Secret scan are all green on this head. Locally it did not finish: a run
    was killed by its own 25-minute budget inside check_dashboard_roundtrip,
    which boots Grafana, after every prior step passed — a known slow step on
    this host under a busy shared docker daemon, and unrelated to a change
    that touches no stack, rule, dashboard or compose file.
  • Deployed to the lab and confirmed working — n/a, nothing deploys.
  • Docs updated

Refs #444, #84, #85 — none of them close here. #444 and #84 close at the window.

🤖 Generated with Claude Code

… TLS (#444)

#444 asked for a switch that can do TLS. The purchase already happened —
a used MikroTik CRS326-24G-2S+RM, 2026-09-13, recorded by #463 — and the
issue's own plan says nothing changes until a cabling window. This is the
decision half of that plan, written now rather than at the rack.

ADR-0018's note said the successor ADR would be written when the switch was
racked. That is the wrong time: `neo` carries every VLAN, so the swap is a
house-wide outage, and an outage is not when to weigh a dual-boot device's
two operating systems or to decide whether a management LAN survives. The
note is amended to say so. Nothing else about it changes, and nothing in the
estate does either — `neo` is still the MokerLink, still on plain HTTP.

What ADR-0041 decides: RouterOS over SwOS, because SwOS serves HTTP only and
speaks v1/v2c only, which reproduces the limit the purchase exists to escape
on hardware that is capable of better. The name `neo` and `10.7.7.2` are
inherited, and the switch LAN stays — for a reason it did not originally
have. network.md explains that LAN as a workaround for a UI that would not
bind to a tagged interface; that is the MokerLink's limit and it leaves with
it. It survives because an untagged point-to-point link to morpheus is the
way back in after a bad bridge VLAN-filtering commit, on the one device that
carries every VLAN. `www-ssl` serves a leaf from the estate's CA, not the
tier's — a switch cannot ask for an ACME renewal, and blackbox already
verifies estate-CA leaves by ca_file, so the switch-ui probe can move to
https and actually check the certificate. An SNMPv3 authPriv user, v2c off.

Port mirroring stays disabled. It was in #444's selection criteria, and
ADR-0006 decided the sensor belongs on morpheus with the switch's mirroring
off and available on demand; buying a device that can mirror was never a
decision to mirror.

swap-the-switch.md is the procedure, in three phases, because only the
middle one needs the house offline. Two things in it are not in #444's list.
The first is a firewall rule: network.md blocks the switch LAN apart from
`10.7.7.2:80`, so disabling plain www before widening that pass to 443
leaves a correctly configured switch that Hicks is not allowed to reach —
widen, prove, then close 80. The second is that the MokerLink's SNMP
community leaked into a session transcript on 2026-08-20 and SECURITY.md
records it as deliberately not rotated, because rotating it meant repeating
the residual. That reasoning expires with the hardware only if the value
does too, so commissioning derives nothing from it.

Also: no per-port VLAN map exists in this repository, and the runbook makes
capturing one off the MokerLink the first bench step — 26 cables and no map
is how the house comes back wrong. And the port census is the one thing here
that could still imply a purchase: 26 copper ports replaced by 24 plus two
SFP+, so if more than 24 are populated, an SFP+ copper module edits
*Everything still to buy* in the same commit. The buy table is unchanged by
this commit; #463 already took the switch's row off it.

README's ADR count goes 40 to 41 and its runbook count 25 to 26, both
required by check_docs.py; the tree comment at line 210 was separately stale
at 39 and is corrected. roadmap.md gains a *Decided but not built* entry,
which is what an accepted ADR with no work behind it is.

#444 and #84 both stay open until the window.

Verified: python3 scripts/check_docs.py green at 10 assertions,
./scripts/lint.sh --require-all green.

Refs #444 #84 #85

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Gerrrt
Gerrrt merged commit aca2550 into main Sep 17, 2026
3 checks passed
@Gerrrt
Gerrrt deleted the gerrrt/replace-neo-switch-tls-3ecdec branch September 17, 2026 23:27
Gerrrt added a commit that referenced this pull request Sep 17, 2026
… counts

`main` is red. Three failures, all from two PRs merging within a minute of each
other without seeing one another:

    README.md:95 claims 41 ADRs; the repository has 42
    README.md:96 claims 26 runbooks; the repository has 27
    ADR-0041 is claimed by 2 files — renumber the one that landed second

#491 gave ADR-0041 to *Run the CRS326 on RouterOS* at 23:27:57Z and #495 gave
the same number to *Terminate the remote path on the lab* at 23:28:52Z. The
ADR-numbering assertion is exactly the check for this; it fired one merge too
late, because each branch was green against a `main` that did not yet hold the
other.

The remote-path ADR landed second, so it becomes **ADR-0042** — which is what
`check_docs.py` asks for by name. Renumbered: the filename, its own H1, eleven
links that targeted it, and thirteen bare `ADR-0041` mentions that meant it.
Every remaining `ADR-0041` in the tree is the CRS326 one, checked individually
rather than by pattern, because the two ADRs shared a number and a
search-and-replace would have renumbered both.

Two of the bare mentions are inside other ADRs' amendment blockquotes (ADR-0011,
ADR-0014). Updating a pointer to a renumbered file is not revising a decision,
so ADR-0001's immutability is not in question — and leaving them would be
leaving a reference to a number that now means something else.

`open-the-remote-path.md`'s pfSense rule descriptions change with it
(`WireGuard peers — ADR-0042`). Safe: the tunnel does not exist, its runbook is
gated on the jumpbox of #436, and `restore-the-firewall.md` still counts the
tripwires as though it were unbuilt.

The two README counts are the arithmetic consequence of the same two merges —
one ADR and two runbooks arrived, and the sentence that counts them did not
move.

Refs #491 #495

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant