browser to DNS to Lets Encrypt TLS on wg-pk to the WireGuard tunnel to a DNAT on srv-b to CT 100. Proven 200 over v4 and v6, 301 from http, and real build JSON through the full chain.
No WireGuard change and no route were made. The hub peer entry for srv-b is still a slash 32, as all twenty peers are. An earlier plan widened it to carry the service network; that was abandoned once the hub convention was read. Every vhost there proxies to a 10.110.0.x tunnel address directly, so following the convention removed the only step that could have locked the operator out of srv-b.
The srv-b side is one DNAT rule in nat PREROUTING, scoped to the hub as source so the other nineteen peers cannot reach the service network through it. Added live, proven from the hub, then persisted. Rollback copy kept. POSTROUTING order verified unchanged after iptables-save rewrote the file, and mail from srv-b was confirmed delivered afterwards because it traverses the same interface.
WORK-ORDER-004 is rewritten as executed rather than as planned. Its section 0 states that the original proposed a route and a WireGuard change, that neither was done, and why. The original text stays in history at a8081e1.
Three things recorded as not settled: renewal has never been observed to succeed for this name and is first due before 2026-12-10; no acceptance criteria exist for the composer itself, only for the path to it; and the service has no authentication. Also filed an estate finding: shell.infra.civicus.us and corpusdb.infra.civicus.us publish an AAAA one hex digit off the address wg-pk holds, so both are broken for v6 preferring clients.
141 lines
5.8 KiB
Markdown
141 lines
5.8 KiB
Markdown
# WORK-ORDER-004 — public ingress for the composer
|
|
|
|
**CLOSED 2026-09-11.** The composer is live at `https://dev.mechcomp.kane-il.us`.
|
|
|
|
| | |
|
|
|---|---|
|
|
| Mode | Infrastructure (`PROCESS.md` §2) |
|
|
| Created | 2026-09-11 |
|
|
| Closed | 2026-09-11 |
|
|
| Executed on | `wg-pk` and `srv-b`, by CIVICVS |
|
|
|
|
---
|
|
|
|
## 0. This document was rewritten mid-execution
|
|
|
|
The original proposed widening `AllowedIPs` on the hub's peer entry for `srv-b`
|
|
to carry `10.20.0.0/24`, adding a route, and warned at length about the lockout
|
|
risk of changing a live WireGuard peer.
|
|
|
|
**None of that was done, and none of it was necessary.** It was written before
|
|
reading the hub, from an assumption about how the estate must be wired.
|
|
|
|
Reading it showed the convention: every vhost on `wg-pk` —
|
|
`witness.diagnostics.kane-il.us`, `otium.civicus.us`, `shell.infra.civicus.us`,
|
|
`corpusdb.infra.civicus.us` — proxies to a `10.110.0.x` tunnel address directly.
|
|
Not one routes into a subnet behind a peer. All twenty peers carry a `/32`.
|
|
|
|
Following that convention removed the WireGuard change entirely, and with it the
|
|
only step that could have locked the operator out of `srv-b`.
|
|
|
|
The original text is in git history at `a8081e1`. It is kept there rather than
|
|
here, because a work order describing a plan nobody executed is exactly the stale
|
|
record this project does not tolerate.
|
|
|
|
---
|
|
|
|
## 1. What was actually built
|
|
|
|
```
|
|
browser
|
|
-> dev.mechcomp.kane-il.us A 198.58.111.109
|
|
AAAA 2600:3c00::f03c:92ff:fe42:43d7
|
|
-> nginx on wg-pk, Let's Encrypt TLS, expires 2026-12-10
|
|
-> proxy_pass http://10.110.0.12:8770 srv-b's own tunnel address
|
|
-> DNAT on srv-b -> 10.20.0.10:8770
|
|
-> mechcomp.service in CT 100
|
|
```
|
|
|
|
Four changes, in the order made:
|
|
|
|
**1. DNAT on `srv-b`**, added live, persisted only after being proven from the
|
|
hub. Rollback copy at `/etc/iptables/rules.v4.before-mechcomp-dnat`.
|
|
|
|
```
|
|
-A PREROUTING -s 10.110.0.1/32 -d 10.110.0.12/32 -i wg0 \
|
|
-p tcp -m tcp --dport 8770 -j DNAT --to-destination 10.20.0.10:8770
|
|
```
|
|
|
|
Scoped to the hub as source. The other nineteen tunnel peers cannot reach the
|
|
service network through it.
|
|
|
|
`curl http://10.110.0.12:8770` from `srv-b` itself fails, correctly:
|
|
locally-originated traffic traverses `OUTPUT`, not `PREROUTING`. Test from the
|
|
hub.
|
|
|
|
**2. DNS.** `A` and `AAAA` for `dev.mechcomp.kane-il.us`, TTL 300. Not a CNAME —
|
|
the hub's other names are all A/AAAA, and matching the zone's own convention beat
|
|
the marginal tidiness of an alias. The `AAAA` was safe to publish immediately
|
|
because `witness` and `otium` already carry `listen [::]:443 ssl`.
|
|
|
|
Nothing was created at `mechcomp.kane-il.us`: CIVICVS never serves at the root of
|
|
a subdomain.
|
|
|
|
**3. Port-80 vhost on `wg-pk`**, no TLS. HTTP-01 needs a live vhost to validate
|
|
against, and a `listen 443` block naming certificate paths that do not exist yet
|
|
fails `nginx -t` and takes the reload down with every other site.
|
|
|
|
**4. `certbot --nginx -d dev.mechcomp.kane-il.us`**, run once. HTTP-01 through
|
|
the nginx plugin, matching all four existing certificates — verified by reading
|
|
`/etc/letsencrypt/renewal/*.conf` rather than assuming. No DNS plugin is
|
|
installed and BIND was not involved. Certbot wrote the 443 block, the redirect
|
|
and the certificate lines into the same file.
|
|
|
|
---
|
|
|
|
## 2. Acceptance — all met 2026-09-11
|
|
|
|
| | Criterion | Result |
|
|
|---|---|---|
|
|
| 1 | `https://dev.mechcomp.kane-il.us/` from outside | `200` |
|
|
| 2 | Let's Encrypt chain, no `-k` | issued, expires 2026-12-10 |
|
|
| 3 | `/api/build` returns real JSON | confirmed |
|
|
| 4 | Reachable over IPv6 | `200` |
|
|
| 5 | HTTP redirects rather than serving plaintext | `301` |
|
|
| 6 | **Negative:** `mechanical-compiler.dev.infra` still answers | `200` |
|
|
| 7 | **Negative:** CT 100 direct still answers | `200` |
|
|
| 8 | **Negative:** mail from `srv-b` still delivers | delivered to `theron@` via `wg-pk` and `mx1` |
|
|
|
|
The three negatives matter as much as the positives. `iptables-save` rewrote the
|
|
whole ruleset on `srv-b`, and mail traverses the same `wg0` interface the DNAT
|
|
was added to. `POSTROUTING` order was verified unchanged — the `RETURN` still
|
|
precedes both masquerades.
|
|
|
|
---
|
|
|
|
## 3. What this did not settle
|
|
|
|
- **Renewal has never been observed to succeed for this name.** The certbot timer
|
|
is scheduled and the other four certificates are managed identically, but the
|
|
first renewal for `dev.mechcomp` is due before 2026-12-10 and nobody has
|
|
watched one complete. `certbot renew --dry-run` counts against a rate limit and
|
|
was not repeated after one attempt timed out.
|
|
- **No acceptance criteria exist for the composer itself**, only for the path to
|
|
it. A `200` says the chain works, not that the page is right.
|
|
- **The service has no authentication.** It is world-reachable and computes
|
|
geometry for anyone who asks. Acceptable for a development name; it should be a
|
|
conscious decision before anything else is published this way.
|
|
|
|
---
|
|
|
|
## 4. Found while working, not this project's to fix
|
|
|
|
`shell.infra.civicus.us` and `corpusdb.infra.civicus.us` publish `AAAA`
|
|
`2600:3c00:e000:365::`. `wg-pk` holds `2600:4c00:e000:365::` — one hex digit
|
|
apart, `3c` against `4c`. **Both names are unreachable for v6-preferring clients
|
|
right now**, while v4 clients see working sites: the intermittent fault that
|
|
looks like anything except DNS.
|
|
|
|
Recorded in `STAGING-STATE.md` §6 so it does not evaporate with the scrollback.
|
|
|
|
---
|
|
|
|
## 5. Method note
|
|
|
|
The one thing that made this go quickly, after several turns of it not going
|
|
quickly at all: **read the estate's own conventions before designing against
|
|
it.** Every wrong turn in this work order's history — a route that was not
|
|
needed, a lockout risk that did not exist, a CNAME where the zone uses A/AAAA, a
|
|
DNS-01 challenge where HTTP-01 was already standard — came from proposing a
|
|
design before reading what four working services already did.
|