wg-easy + Traefik docker-compose stack (Phase 1) plus a stdlib-only control-plane API for box registration, WireGuard peer provisioning via wg-easy, and per-box route publish/unpublish backed by Traefik's file provider (Phase 2, single-tenant mode). SQLite holds accounts/boxes/routes so a later multi-tenant shared instance is the same schema with more rows, not a reshape. wg-easy's actual REST API was verified against its source rather than assumed: it has no bearer-token auth (session-cookie login via POST /api/auth/password) and no way to accept an externally-generated public key (it always mints the keypair itself, private key included) — both corrected from the original plan during implementation.
43 lines
2 KiB
Markdown
43 lines
2 KiB
Markdown
# furtka-gateway
|
|
|
|
WireGuard (wg-easy) + Traefik reverse-proxy that lets a Furtka box — typically
|
|
sitting behind NAT/CGNAT with no public IP — expose individual apps to the
|
|
internet under a real domain with automatic TLS.
|
|
|
|
A Furtka box becomes a WireGuard peer of this gateway. The gateway's Traefik
|
|
reverse-proxies public HTTPS traffic over that tunnel to whichever apps the
|
|
box owner has explicitly published. Only apps whose Furtka `manifest.json`
|
|
declares `internet.viable: true` can be published at all, and publishing is
|
|
always an explicit per-app opt-in on the box side — the gateway never exposes
|
|
anything on its own.
|
|
|
|
Supports two deployment modes from the same codebase:
|
|
|
|
- **`single`** — the common case: one person/operator runs this on their own
|
|
VPS with their own domain's A/AAAA records pointed at it, for their own
|
|
Furtka box(es).
|
|
- **`shared`** — one larger, multi-tenant instance (operated by the Furtka
|
|
project) for people who don't want to run their own. Same schema, same
|
|
code; `single` is just the one-account case.
|
|
|
|
See `docker-compose.yaml` and `control_plane/` for the moving parts. Status:
|
|
**Phase 1 (scaffold)** — wg-easy + Traefik + a stub control-plane exposing
|
|
only `/healthz`, enough to manually prove the wiring end-to-end before the
|
|
real control-plane (accounts/boxes/routes) lands.
|
|
|
|
## Local dev
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# edit .env: set GATEWAY_PUBLIC_HOST to a real hostname you control (or a
|
|
# LAN-reachable IP for a first smoke test), and a PASSWORD_HASH for wg-easy
|
|
# (see https://github.com/wg-easy/wg-easy for how to generate one).
|
|
docker compose up -d
|
|
curl http://127.0.0.1:8090/healthz
|
|
```
|
|
|
|
Traefik's dashboard/API and wg-easy's own UI are intentionally not published
|
|
on a host port — reach them via `docker compose exec` / port-forwarding
|
|
during development. Neither should ever be reachable from the internet in a
|
|
real deployment; only the control-plane (`8090`, bound to `127.0.0.1`) and
|
|
Traefik's `80`/`443` entrypoints are meant to be exposed.
|