MakerFLOSS_Troubleshooting/docs/superpowers/specs/2026-06-28-tappaas-vps-publishing-design.md
sjat 41d3b4074d design: route TaPPaaS web services through the VPS
Split-horizon DNS + public exposure under *.tappaas.makerfloss.eu,
reusing the proven mf01 publishing pattern (new wg1 peer, TLS terminates
at VPS, plain HTTP over wg1 to TaPPaaS Caddy). TaPPaaS-side config repo
left as an open item.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 10:00:29 +02:00

8.9 KiB

Design — Routing TaPPaaS web services through the VPS (split-horizon DNS + public exposure)

Date: 2026-06-28 Status: Design approved; implementation not started. Scope: Expose selected TaPPaaS cluster web services publicly via the makerfloss VPS, with split-horizon DNS so internal clients resolve the same names to a local address. Reuses the proven mf01 service-publishing pattern.

Where this lands. The VPS-side changes are implemented in AnsibleBaobabV4 (host_vars/makerfloss.yml) on its main — mirror this design there when execution starts (the mf01 analogue lives at AnsibleBaobabV4/docs/superpowers/specs/2026-06-09-mf01-service-publishing-design.md). This copy lives in the troubleshooting workspace because the design spans repos and the TaPPaaS-side config repo is still open (see Open items). Authoritative values stay in the source repos — values quoted here are proposals and can drift.

Goals

  1. Public exposure of relevant TaPPaaS web services under *.tappaas.makerfloss.eu, so A records can point at the VPS static IP 88.99.32.236.
  2. Split-horizon DNS: internal clients resolve the same hostnames to TaPPaaS Caddy's local IP (no VPS round-trip); external clients resolve to the VPS.
  3. Preserve the isolation requirement — nothing on the makerspace side egresses through the VPS or reaches the homelab; the cluster never becomes a general transit path.

Non-goals

  • Moving TLS authority off the VPS for the external path (no SNI passthrough — see Decisions).
  • Day-one internal resolution for the makerspace LAN (deferred — depends on the OrangeMakers router, which is third-party).
  • Changing how the existing apex services (docs, slides, forgejo, mail, discourse, snipeit, nb) are published.

Decisions (from brainstorming, 2026-06-28)

Decision Choice Rationale
Split-horizon scope Internal view for both cluster + makerspace LAN, phased LAN half depends on third-party router; ship cluster first.
VPS ↔ TaPPaaS transport New wg1 WireGuard peer (FLOSSFirewall) Mirrors mf01; both ends self-owned; static hub-and-spoke.
TLS termination (external) Terminate at the VPS Cert issuance while isolated is the dealbreaker for passthrough; keeps Gandi DNS-write credential on the VPS only; keeps edge routing/middleware.
Naming Delegated wildcard *.tappaas.makerfloss.eu One cert + one route; add services with zero VPS change; avoids apex name clash (forgejo.tappaas... vs existing forgejo.makerfloss.eu).
Internal DNS authority FLOSSFirewall (already runs DNS/DHCP), serving the cluster now LAN deferred per phasing.

Architecture & request flows

External request (off-site client):

browser ─https─▶ <svc>.tappaas.makerfloss.eu   (public DNS: A *.tappaas → 88.99.32.236)
  ─▶ VPS Traefik :443   (wildcard cert *.tappaas.makerfloss.eu via Gandi DNS-01; TLS ends here)
  ─▶ plain HTTP inside wg1 ─▶ FLOSSFirewall/Caddy (wg1 IP 10.13.0.9:80)
  ─▶ Caddy routes by Host ─▶ TaPPaaS service (srv01/02/03)

Internal request (TaPPaaS cluster now; makerspace LAN later):

client ─https─▶ <svc>.tappaas.makerfloss.eu   (INTERNAL DNS: A → Caddy local IP)
  ─▶ Caddy :443   (Caddy's own Let's Encrypt cert; TLS ends here, no VPS round-trip)
  ─▶ TaPPaaS service

Two views, never colliding. Public DNS (Gandi) points the wildcard at the VPS; the FLOSSFirewall's internal resolver points the same wildcard at Caddy's local IP. A client only ever sees the cert for the IP it resolved — the VPS wildcard externally, Caddy's own cert internally.

Components & changes

A. VPS — AnsibleBaobabV4/host_vars/makerfloss.yml (additive, mirrors mf01)

  1. wg1 peer — add FLOSSFirewall to wireguard_server_peers, allowed_ips: 10.13.0.9/32 (next free; mf01 is .8 — confirm free before assigning).
  2. Wildcard cert — add to traefik_wildcard_sets:
    - main: "tappaas.makerfloss.eu"
      sans: ["*.tappaas.makerfloss.eu"]
    
    The ACME anchor router issues it automatically via Gandi DNS-01.
  3. Catch-all route — add tappaas-delegate.yml to traefik_extra_dynamic_files:
    http:
      routers:
        tappaas-wildcard:
          rule: 'HostRegexp(`^.+\.tappaas\.makerfloss\.eu$`)'
          entryPoints: [websecure]
          service: tappaas-backend
          tls: {}
      services:
        tappaas-backend:
          loadBalancer:
            passHostHeader: true
            servers:
              - url: "http://10.13.0.9:80"
    
    Keep the regex single-quoted — a YAML error here breaks the whole file provider.
  4. Public DNS — add tappaas and *.tappaas A records → 88.99.32.236 in gandi_dns_records.

Deploy = the three plays from the mf01 runbook: play_dns.yml, play_containers.yml --limit makerfloss -t traefik, and the wireguard server play. After this, new services need zero VPS change — exposure is decided at Caddy.

B. FLOSSFirewall / Caddy (TaPPaaS side — repo TBD, see Open items)

  1. WireGuard client — peer to the VPS hub (endpoint makerfloss.eu:51820), interface IP 10.13.0.9/32, AllowedIPs = 10.13.0.0/24 only → split-tunnel (cluster never routes general traffic through the VPS; isolation preserved).
  2. Caddy plain-HTTP backend — a Host-routed HTTP listener bound on the wg1 interface (10.13.0.9:80) with HTTPS-redirect OFF. This is what the VPS proxies into. Caddy keeps serving :443 with its own LE certs to internal clients unchanged. (Direct mirror of mf01's internal Traefik: redirect off, no ACME on that path.)
  3. Firewall — allow tcp/80 only from 10.13.0.1 (the VPS) on the wg interface.

C. Internal DNS (FLOSSFirewall's existing DNS)

  • Override/authoritative answer for *.tappaas.makerfloss.eu → Caddy's local IP, served to the cluster now. Makerspace LAN deferred.

Exposure policy

A service is public only if Caddy has a Host route for it; the wildcard + catch-all just carry whatever Caddy publishes. The VPS's existing internal-only@file middleware can gate specific routes that must stay LAN-only despite living under the public wildcard.

Phasing (each phase independently verifiable)

  1. Tunnel — bring up FLOSSFirewall as wg1 peer 10.13.0.9; verify wg show on the VPS and bidirectional ping 10.13.0.1 ↔ 10.13.0.9.
  2. Caddy backend — stand up the plain-HTTP wg-interface listener; from the VPS, curl -H 'Host: <svc>.tappaas.makerfloss.eu' http://10.13.0.9:80 returns the service.
  3. VPS edge — add wildcard cert + catch-all route + public DNS; from off-site, curl -s https://<svc>.tappaas.makerfloss.eu returns the service with a valid cert.
  4. Internal DNS — add the internal *.tappaas override on the FLOSSFirewall; from a cluster node, confirm the name resolves to Caddy's local IP and serves Caddy's own cert (no VPS round-trip).
  5. (Later) makerspace LAN internal view — conditional-forward tappaas.makerfloss.eu → FLOSSFirewall + a LAN→TaPPaaS firewall path on the OrangeMakers router.

Isolation (hard requirement — how it's preserved)

  • FLOSSFirewall is split-tunnel (AllowedIPs = 10.13.0.0/24) — the cluster never egresses through the VPS; nothing on wg1 reaches the wider makerspace or homelab.
  • VPS→Caddy reachability is firewalled to tcp/80 from 10.13.0.1 on the wg interface only.
  • The plain-HTTP backend hop is encrypted on the wire (inside WireGuard).
  • No public-DNS-write credential ever leaves the VPS — the reason TLS terminates there rather than via passthrough.

Risks / watch-items

  • Caddy must not force HTTPS-redirect on the wg-interface listener, or the VPS hits a redirect loop (the gotcha mf01 solved with redirect off).
  • A YAML error in tappaas-delegate.yml breaks the entire VPS file provider — keep the regex single-quoted.
  • 10.13.0.9 must be free on wg1 — confirm before assigning.
  • TaPPaaS is currently firewalled off from production and the VPS link isn't up yet; phase 1 is the prerequisite for everything else.

Open items

  • TaPPaaS-side config repo is undetermined. Only docs were found in ~/Projects/MakerFLOSS; the FLOSSFirewall WireGuard / Caddy / internal-DNS config repo must be identified (or created) before the implementation plan for section B/C.
  • Makerspace LAN internal view (phase 5) depends on OrangeMakers router cooperation.

References

  • mf01 pattern (template): runbooks/publishing-services-mf01.md; AnsibleBaobabV4/docs/superpowers/specs/2026-06-09-mf01-service-publishing-design.md.
  • VPS Traefik / wg1 / Gandi DNS: AnsibleBaobabV4/host_vars/makerfloss.yml.
  • TaPPaaS overview: MakerFLOSS/docs/infrastructure/labdesign.md, MakerFLOSS/docs/infrastructure/vps-and-dns.md, MakerFLOSS/docs/hardware/srv0[1-3].md.
  • Network map / access paths: network-map.md, access.md.