MakerFLOSS/docs/presentations/2026-06-28-tappaas-vps-publishing.md
sjat 3a0f062f37
All checks were successful
Build docs site / build (push) Successful in 53s
Build slides / build (push) Successful in 1m12s
slides: fix TaPPaaS deck overflow + stray tag
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>
2026-06-28 10:59:46 +02:00

6.3 KiB
Raw Blame History

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 wg1 WireGuard 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["&lt;svc&gt;.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:

  1. wg1 peer — FLOSSFirewall, allowed_ips: 10.13.0.9/32.
  2. Wildcard cert — add tappaas.makerfloss.eu + *.tappaas to traefik_wildcard_sets → ACME anchor issues it via Gandi DNS-01.
  3. Catch-all routetappaas-delegate.yml: HostRegexp(...tappaas...)http://10.13.0.9:80, passHostHeader: true.
  4. Public DNStappaas + *.tappaas A → 88.99.32.236.

After this, new services need zero VPS change — exposure is decided at Caddy.


Components — TaPPaaS / Caddy side

  1. WireGuard client — peer to the VPS hub, interface 10.13.0.9/32, AllowedIPs = 10.13.0.0/24 only → split-tunnel (no general egress through the VPS).
  2. Caddy plain-HTTP backend — Host-routed listener on the wg interface (10.13.0.9:80), HTTPS-redirect OFF. Caddy keeps serving :443 with its own certs to internal clients, unchanged.
  3. Firewall — allow tcp/80 only from 10.13.0.1 (the VPS) on the wg interface.

Phasing — VPS edge (steps 13)

  1. Tunnel — FLOSSFirewall up as wg1 peer; ping 10.13.0.1 ↔ 10.13.0.9.
  2. Caddy backend — from the VPS, curl -H 'Host: …tappaas…' 10.13.0.9:80.
  3. VPS edge — add cert + route + DNS; off-site curl https://<svc>.tappaas.makerfloss.eu returns a valid cert.

Phasing — internal & later (steps 45)

  1. Internal DNS — add the *.tappaas override on the FLOSSFirewall; a cluster node resolves to Caddy's local IP and gets Caddy's own cert (no VPS round-trip).
  2. (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 on wg1 reaches the makerspace or homelab.
  • VPS→Caddy locked to tcp/80 from 10.13.0.1 on 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.yml breaks the whole VPS file provider; keep the regex single-quoted.
  • 10.13.0.9 free? — 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 wg1 to 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 14.

Design: MakerFLOSS_Troubleshooting/docs/superpowers/specs/2026-06-28-tappaas-vps-publishing-design.md