Shrink global font and tighten spacing so dense slides fit; split the phasing slide into VPS-edge (1-3) and internal/later (4-5). Remove a stray </content> line that leaked into the source. Verified all 13 slides fit via per-slide PNG render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.3 KiB
| marp | theme | class | paginate |
|---|---|---|---|
| true | gaia | invert | true |
Routing TaPPaaS through the VPS
Split-horizon DNS · public exposure on a static IP
MakerFLOSS · June 2026 · technical review
The goal
Publish selected TaPPaaS web services under *.tappaas.makerfloss.eu.
- Public exposure — A records point at the VPS static IP
88.99.32.236, so the cluster's services are reachable from anywhere. - Split-horizon DNS — the same hostname resolves to a local address for internal clients, so they never round-trip to the VPS.
- Isolation preserved — nothing on the makerspace side egresses through the VPS or reaches the homelab.
We are not inventing anything — we clone a pattern already running.
Building block: the proven mf01 pattern
mf01 already publishes *.mf01.makerfloss.eu exactly this way, live since
2026-06-09:
- TLS terminates on the VPS (wildcard cert, Gandi DNS-01).
- Plain HTTP rides the
wg1WireGuard tunnel to an internal reverse proxy. - The internal proxy routes by Host to the right container.
TaPPaaS = the same shape, with Caddy as the internal proxy instead of an internal Traefik. Low risk, known gotchas already solved.
External request flow
flowchart LR
C["Browser<br/>(off-site)"] -->|"https · *.tappaas<br/>DNS → 88.99.32.236"| T["VPS Traefik :443<br/>wildcard cert<br/>TLS ends here"]
T -->|"plain HTTP<br/>inside wg1"| K["FLOSSFirewall / Caddy<br/>10.13.0.9:80"]
K -->|"route by Host"| S["TaPPaaS service<br/>srv01 / srv02 / srv03"]
TLS terminates at the VPS; the backend hop is plain HTTP but encrypted on the wire inside WireGuard.
Internal flow — two views, one name
flowchart TD
N["<svc>.tappaas.makerfloss.eu"]
N -->|"public DNS (Gandi)"| V["VPS 88.99.32.236<br/>VPS wildcard cert"]
N -->|"internal DNS (FLOSSFirewall)"| L["Caddy local IP<br/>Caddy's own LE cert"]
A client only ever sees the cert for the IP it resolved — VPS wildcard externally, Caddy's own cert internally. The two views never collide.
Key decisions
| Decision | Choice | Why |
|---|---|---|
| Transport | New wg1 WireGuard peer |
Mirrors mf01; both ends self-owned; static hub-and-spoke |
| TLS (external) | Terminate at the VPS | Cert issuance while isolated kills passthrough; Gandi DNS-write key stays on the VPS; keeps edge routing/middleware |
| Naming | Wildcard *.tappaas.makerfloss.eu |
One cert + one route; add services with zero VPS change; no apex clash (forgejo.tappaas… ≠ forgejo.makerfloss.eu) |
| Internal DNS | FLOSSFirewall (already runs DNS), cluster first | LAN view deferred — depends on third-party router |
Components — VPS side
All additive in AnsibleBaobabV4/host_vars/makerfloss.yml, mirroring mf01:
- wg1 peer — FLOSSFirewall,
allowed_ips: 10.13.0.9/32. - Wildcard cert — add
tappaas.makerfloss.eu+*.tappaastotraefik_wildcard_sets→ ACME anchor issues it via Gandi DNS-01. - Catch-all route —
tappaas-delegate.yml:HostRegexp(...tappaas...)→http://10.13.0.9:80,passHostHeader: true. - Public DNS —
tappaas+*.tappaasA →88.99.32.236.
After this, new services need zero VPS change — exposure is decided at Caddy.
Components — TaPPaaS / Caddy side
- WireGuard client — peer to the VPS hub, interface
10.13.0.9/32,AllowedIPs = 10.13.0.0/24only → split-tunnel (no general egress through the VPS). - Caddy plain-HTTP backend — Host-routed listener on the wg interface
(
10.13.0.9:80), HTTPS-redirect OFF. Caddy keeps serving:443with its own certs to internal clients, unchanged. - Firewall — allow
tcp/80only from10.13.0.1(the VPS) on the wg interface.
Phasing — VPS edge (steps 1–3)
- Tunnel — FLOSSFirewall up as
wg1peer; ping10.13.0.1 ↔ 10.13.0.9. - Caddy backend — from the VPS,
curl -H 'Host: …tappaas…' 10.13.0.9:80. - VPS edge — add cert + route + DNS; off-site
curl https://<svc>.tappaas.makerfloss.eureturns a valid cert.
Phasing — internal & later (steps 4–5)
- Internal DNS — add the
*.tappaasoverride on the FLOSSFirewall; a cluster node resolves to Caddy's local IP and gets Caddy's own cert (no VPS round-trip). - (Later) makerspace LAN view — conditional-forward + firewall pinhole on the OrangeMakers router.
Isolation — the hard requirement
- Split-tunnel (
AllowedIPs = 10.13.0.0/24) — the cluster never egresses through the VPS; nothing onwg1reaches the makerspace or homelab. - VPS→Caddy locked to
tcp/80 from 10.13.0.1on the wg interface. - Backend hop encrypted inside WireGuard.
- No public-DNS-write credential leaves the VPS — the reason TLS terminates there, not via passthrough.
Risks & open items
- Caddy redirect — the wg-interface listener must not force HTTPS-redirect, or the VPS hits a loop (mf01's known gotcha).
- YAML safety — a syntax error in
tappaas-delegate.ymlbreaks the whole VPS file provider; keep the regex single-quoted. 10.13.0.9free? — confirm before assigning.- TaPPaaS config repo TBD — the FLOSSFirewall/Caddy/DNS config home is not yet identified.
- Phase 5 depends on OrangeMakers router cooperation.
Summary & next steps
- Reuse the proven mf01 pattern — terminate TLS at the VPS, proxy over
wg1to TaPPaaS Caddy, split-horizon DNS for the internal view. - VPS side is a small, additive, zero-new-tech change.
- Next: identify the TaPPaaS config repo, then write the implementation plan and execute phases 1–4.
Design: MakerFLOSS_Troubleshooting/docs/superpowers/specs/2026-06-28-tappaas-vps-publishing-design.md