Some checks failed
Build control-plane image / build-image (push) Has been cancelled
Restructure the deployment model: instead of bundling and owning its own Traefik + wg-easy, the control-plane now plugs into a Traefik and wg-easy the operator already runs (as sibling containers, or otherwise reachable). This avoids duplicating infra self-hosters commonly already have, and sidesteps having to run a second ACME/DNS setup entirely — the operator's own Traefik already has a working cert resolver. - New control_plane/wgeasy_v15.py: a wg-easy v15 REST client, verified live against a real running container (auth model, route shapes, and the new per-client PresharedKey all differ materially from v14's API). Threaded the preshared key through to the box side (furtka/wireguard.py in the furtka repo) so v15's handshake actually completes. - GATEWAY_CERT_RESOLVER is now a real env var instead of a GATEWAY_MODE- derived hardcoded "le", so it can mirror whatever resolver name (if any) the operator's own Traefik already has configured. - Root docker-compose.yaml/ops/deploy.sh: control-plane only now. deploy.sh asks how the operator's Traefik reaches it (same docker network, joined via `docker network connect`, or a separate host) instead of prompting for DNS-01 providers and port remaps single-parallel mode needed. - single-parallel mode is retired outright — nothing needs it once furtka-gateway doesn't own a second Traefik/wg-easy to remap ports for. - The old bundled stack (own Traefik+wg-easy, HTTP-01) moves to examples/starter-stack/ as the documented zero-infra on-ramp. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3jVwAqESRjPdW9P9nvfem
59 lines
3 KiB
Text
59 lines
3 KiB
Text
# Zero-infra starter stack: bundles its own Traefik + wg-easy alongside the
|
|
# control-plane. If you already run Traefik and/or wg-easy, use the main
|
|
# repo's root docker-compose.yaml + ops/deploy.sh instead — it plugs into
|
|
# what you already have rather than running a second copy.
|
|
#
|
|
# Filling this file in by hand? Run `deploy.sh` instead — it prompts for
|
|
# the values below, generates the secrets/tokens, handles the `$$`
|
|
# escaping gotcha noted under WG_EASY_PASSWORD_HASH for you, and renders
|
|
# traefik/static/traefik.active.yml + traefik/dynamic/control-plane.yml.
|
|
|
|
# The hostname (or IP, for a first local smoke test) wg-easy advertises to
|
|
# peers as the WireGuard endpoint. Must be reachable on udp/51820.
|
|
GATEWAY_PUBLIC_HOST=vpn.example.com
|
|
|
|
# ACME email for Let's Encrypt registration (HTTP-01, per-subdomain —
|
|
# fine at self-hosted scale, nowhere near Let's Encrypt's ~50-certs/
|
|
# registered-domain/week limit with a handful of published apps).
|
|
GATEWAY_ACME_EMAIL=admin@example.com
|
|
|
|
# bcrypt hash of the wg-easy admin password. Generate with:
|
|
# docker run --rm ghcr.io/wg-easy/wg-easy:14 node -e \
|
|
# "console.log(require('bcryptjs').hashSync(process.argv[1], 10))" 'your-password'
|
|
#
|
|
# IMPORTANT: bcrypt hashes contain literal `$` characters (e.g.
|
|
# "$2a$10$..."), and Docker Compose's own .env-file parser treats `$word`
|
|
# as a variable reference to substitute — confirmed by actually hitting
|
|
# this: an unescaped hash silently got truncated to "$2a$10" with
|
|
# everything after dropped. Every `$` in the value below MUST be doubled
|
|
# as `$$`, e.g. WG_EASY_PASSWORD_HASH=$$2a$$10$$abc123...
|
|
WG_EASY_PASSWORD_HASH=
|
|
|
|
# PLAINTEXT password matching the hash above. wg-easy's admin API (this
|
|
# specific pinned image, ghcr.io/wg-easy/wg-easy:14 — confirmed by reading
|
|
# its actual source, which turned out to differ from what wg-easy's current
|
|
# docs describe) has no login call or session cookie at all: every request
|
|
# just carries this password as a plain `Authorization` header, checked
|
|
# with bcrypt against WG_EASY_PASSWORD_HASH. No username concept exists.
|
|
WG_EASY_ADMIN_PASSWORD=
|
|
|
|
# The one box token this stack accepts at /v1/boxes/register, skipping
|
|
# full account/registration-token issuance. Generate with: openssl rand -hex 32
|
|
GATEWAY_BOX_TOKEN=
|
|
|
|
# Hostname a Furtka box actually reaches the control-plane API on — needs
|
|
# its own A/AAAA record pointing at this VPS. Not read by docker-compose
|
|
# itself; it's what deploy.sh substitutes into traefik/dynamic/control-plane.yml.
|
|
GATEWAY_CONTROL_PLANE_HOST=gw.example.com
|
|
|
|
# Bearer token required to create accounts via POST /v1/accounts.
|
|
# Only meaningful once account endpoints exist (Phase 2+); harmless to set
|
|
# now. Generate with: openssl rand -hex 32
|
|
GATEWAY_ADMIN_TOKEN=
|
|
|
|
# Optional: override the control-plane image `docker stack deploy` pulls
|
|
# (Swarm ignores docker-compose.yaml's `build:` key). Defaults to the
|
|
# `latest` tag CI publishes on every push to master; pin to a specific
|
|
# commit-sha tag for a reproducible deploy. Not read by plain
|
|
# `docker compose up`, which always builds locally.
|
|
GATEWAY_CONTROL_PLANE_IMAGE=
|