ADR-003: Self-hosted home cluster behind Cloudflare Tunnel

Status: Accepted Date: 2026-10-10

Context

The budget is zero beyond domains until the pilot proves the product. The team has two always-on machines in different homes in Vietnam, each with a UPS and a public IPv4 address. Use is classroom-only for now, so short outages are acceptable. vgu-graduation exposed its homelab by port-forwarding with no edge protection (its ADR-009), which is not acceptable for children's data.

Decision

Run the API, PostgreSQL and object storage on k3s across the two home nodes. Reach them only through Cloudflare Tunnel (free), with a connector on each node: no inbound ports, no dynamic DNS, and Cloudflare's WAF and DDoS protection in front. Move DNS for both domains from Spaceship to Cloudflare. Phase 0 runs on node A; node B joins during the pilot with a PostgreSQL replica, Garage at two copies (one zone per home) and a second tunnel connector. PostgreSQL is backed up nightly to Cloudflare R2's free tier from day one. Every node uses full-disk encryption.

Alternatives considered

  • Port-forwarding as in vgu-graduation: exposes home IPs and has no WAF.
  • A VPS or managed PostgreSQL: better uptime, but a monthly cost before there's revenue. It's the planned move after funding.

Consequences

  • An outage lasts as long as a power or ISP failure at the primary home. Two nodes cannot form an HA control plane; that needs a third.
  • Cloudflare's free Universal SSL covers one subdomain level, which shapes hostnames (ADR-006).
  • Cloudflare, as the TLS terminator, is a subprocessor of student data.