# 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.