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

185 lines
8.9 KiB
Markdown

# 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`:
```yaml
- 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`:
```yaml
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`.
</content>
</invoke>