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.
76 lines
2 KiB
YAML
76 lines
2 KiB
YAML
services:
|
|
wg-easy:
|
|
image: ghcr.io/wg-easy/wg-easy:14
|
|
container_name: furtka-gateway-wg-easy
|
|
environment:
|
|
- WG_HOST=${GATEWAY_PUBLIC_HOST}
|
|
- PASSWORD_HASH=${WG_EASY_PASSWORD_HASH}
|
|
- PORT=51821
|
|
- WG_PORT=51820
|
|
volumes:
|
|
- wg_easy_data:/etc/wireguard
|
|
ports:
|
|
- "51820:51820/udp"
|
|
cap_add:
|
|
- NET_ADMIN
|
|
- SYS_MODULE
|
|
sysctls:
|
|
- net.ipv4.ip_forward=1
|
|
- net.ipv4.conf.all.src_valid_mark=1
|
|
restart: unless-stopped
|
|
networks:
|
|
- internal
|
|
# wg-easy's own admin UI/API (port 51821) is intentionally NOT published
|
|
# to the host. Only control-plane, on the internal network, talks to it.
|
|
|
|
traefik:
|
|
image: traefik:v3.1
|
|
container_name: furtka-gateway-traefik
|
|
command:
|
|
- --configFile=/etc/traefik/traefik.yml
|
|
volumes:
|
|
- ./traefik/static/traefik.${GATEWAY_MODE:-single}.yml:/etc/traefik/traefik.yml:ro
|
|
- ./traefik/dynamic:/etc/traefik/dynamic:ro
|
|
- traefik_acme:/acme
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
restart: unless-stopped
|
|
networks:
|
|
- internal
|
|
# Traefik's own dashboard/API is disabled in both static configs
|
|
# (api.dashboard: false, api.insecure: false) — never reachable at all,
|
|
# let alone publicly.
|
|
|
|
control-plane:
|
|
build: ./control_plane
|
|
container_name: furtka-gateway-control-plane
|
|
environment:
|
|
- GATEWAY_MODE=${GATEWAY_MODE:-single}
|
|
- GATEWAY_STATE_DIR=/data
|
|
- GATEWAY_DYNAMIC_DIR=/dynamic
|
|
- GATEWAY_ADMIN_TOKEN=${GATEWAY_ADMIN_TOKEN}
|
|
- GATEWAY_BOX_TOKEN=${GATEWAY_BOX_TOKEN}
|
|
- WG_EASY_URL=http://wg-easy:51821
|
|
- WG_EASY_ADMIN_USERNAME=${WG_EASY_ADMIN_USERNAME:-admin}
|
|
- WG_EASY_ADMIN_PASSWORD=${WG_EASY_ADMIN_PASSWORD}
|
|
volumes:
|
|
- control_plane_data:/data
|
|
- ./traefik/dynamic:/dynamic
|
|
ports:
|
|
- "127.0.0.1:8090:8090"
|
|
restart: unless-stopped
|
|
networks:
|
|
- internal
|
|
depends_on:
|
|
- wg-easy
|
|
- traefik
|
|
|
|
networks:
|
|
internal:
|
|
driver: bridge
|
|
|
|
volumes:
|
|
wg_easy_data:
|
|
traefik_acme:
|
|
control_plane_data:
|