papa-hq reads 01 research -> 03 decision -> 02 design. The order is a scar, not a choice: 02-DESIGN existed from its initial commit, and when adr/ was finally promoted on 2026-07-13 it took the next free number rather than its place in the sequence. By then design was too settled to renumber. hal-hq was three commits old, so it is not. adr/ becomes 02-DECISIONS and 02-DESIGN becomes 03-DESIGN, and following the folder numbers now walks the process in the order it happens: research produces a decision, the decision authorises a design. 00-GENESIS becomes 00-META, matching papa's rename from the same restructure. Every path reference rewritten across documents, frontmatter, playbooks and skills. All links resolve; all 58 frontmatter blocks parse and their path fields still point at files that exist.
51 lines
2.4 KiB
Markdown
51 lines
2.4 KiB
Markdown
---
|
|
status: active
|
|
initiated: 2026-08-22
|
|
touches: [03-DESIGN/00-as-is/01-mesh-and-transport.md, 03-DESIGN/01-to-be/01-end-to-end-testing.md]
|
|
became: [02-DECISIONS/0016-a-lab-node-is-a-virtual-machine.md]
|
|
---
|
|
|
|
# 004 — Reproducing the mesh network in a lab
|
|
|
|
- **Initiated by:** jochen, 2026-08-22 — *"the most difficult part of our VM setup will be
|
|
the networking part"*
|
|
- **Areas touched:** `modules/wireguard`, `modules/dnsmasq-app`, `modules/traefik`,
|
|
`modules/mesh-ca`, `node_accessors`, `nodes.site` / `nodes.underlay_addr`.
|
|
|
|
## Summary
|
|
|
|
The network is **entirely generated from mesh-DB rows by module hooks**. `install.d` performs
|
|
no network configuration whatsoever — no WireGuard, no DNS, no firewall. That makes a faithful
|
|
lab primarily a *data* problem rather than a networking problem, and means the lab exercises
|
|
the real code path instead of a reimplementation of it.
|
|
|
|
One constraint decides whether the lab works at all: the WireGuard endpoint rule tests the
|
|
underlay address against an RFC1918 regex to decide reachability. **A simulated public segment
|
|
addressed from RFC1918 space silently prevents the mesh from forming** — no endpoint is written
|
|
for the hub, so nothing can ever initiate. The simulated public segment must therefore use
|
|
TEST-NET-3 (`203.0.113.0/24`).
|
|
|
|
With that one substitution the lab reproduces the production topology exactly, including the
|
|
case that is hardest to get right: a node that is publicly *named* but sits behind NAT, whose
|
|
endpoint the hub can only learn from a handshake.
|
|
|
|
Detail in [`analysis.md`](analysis.md).
|
|
|
|
## Settled
|
|
|
|
**The lab issues its own certificates.** Public names are certified by an ACME server on the
|
|
lab's wan segment; `.internal` names keep the mesh CA. The lab preserves production's two-CA
|
|
split rather than collapsing it, because a single-CA lab would hide any bug living in that
|
|
split. It also makes the router's port forward load-bearing — HTTP-01 must reach the
|
|
published-but-NATed node on port 80, so a broken forward becomes a reproducible certificate
|
|
failure instead of a mystery.
|
|
|
|
Requires one change: `caServer` is not set on the reverse proxy today, so it defaults to the
|
|
public authority's **production** endpoint. It must become configurable, defaulting to
|
|
production so real nodes are unaffected.
|
|
|
|
## Open
|
|
|
|
- Not yet stood up. `incus` is declared in `modules/hal/developer/module.yml` and merged
|
|
(PR #944); the lab itself is unbuilt.
|