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>
This commit is contained in:
parent
f11e6e12a4
commit
41d3b4074d
1 changed files with 185 additions and 0 deletions
|
|
@ -0,0 +1,185 @@
|
||||||
|
# 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>
|
||||||
Loading…
Add table
Reference in a new issue