docs(wg): manual runbook for the WireGuard gate (SP1)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/v1-foundation
parent
c9556bffbf
commit
fa7e1c428e
|
|
@ -0,0 +1,58 @@
|
||||||
|
# WireGuard gate (SP1) — manual runbook
|
||||||
|
|
||||||
|
The host scripts (`docker/wg/clusev-wg.sh`, `clusev-wg-gate.service`, the `install.sh` additions)
|
||||||
|
cannot be exercised by the PHPUnit suite — the test runner is the app container, with no host
|
||||||
|
WireGuard/firewall/kernel access. This runbook is their real verification.
|
||||||
|
|
||||||
|
Run on a **throwaway Debian-13 VM** with the Clusev prod stack up. **Keep an SSH session open the
|
||||||
|
whole time** — it is the escape hatch. Tick each step against its expected result.
|
||||||
|
|
||||||
|
## Pre
|
||||||
|
- [ ] `clusev wg help` prints usage; `clusev wg status` shows wg0 not active, gate off.
|
||||||
|
- [ ] `wireguard-tools` + `qrencode` present (installed by `install.sh`): `command -v wg qrencode`.
|
||||||
|
|
||||||
|
## setup
|
||||||
|
- [ ] `sudo clusev wg setup`, enter a subnet that overlaps the VM's LAN (e.g. the VM's own /24) →
|
||||||
|
**rejected**, re-prompts.
|
||||||
|
- [ ] Re-run, accept the default `10.99.0.0/24` → **accepted**; server keys + first peer created;
|
||||||
|
client config + QR printed; `systemctl is-active wg-quick@wg0` → `active`.
|
||||||
|
- [ ] `/etc/wireguard/wg0.conf` and `/etc/clusev/wg.env` exist, mode `0600`.
|
||||||
|
- [ ] `sudo clusev wg setup` again → it **warns** that wg0.conf exists and does NOT silently clobber
|
||||||
|
it (aborts unless you type `reconfigure`).
|
||||||
|
|
||||||
|
## tunnel (gate still OFF)
|
||||||
|
- [ ] Import the printed client (QR) into the WireGuard app; connect.
|
||||||
|
- [ ] Over the tunnel: `http://<server-tunnel-ip>` reaches the panel.
|
||||||
|
- [ ] Public `http://<public-ip>` still reachable (gate is off).
|
||||||
|
|
||||||
|
## gate up
|
||||||
|
- [ ] `sudo clusev wg up` → prints the escape reminder; refuses (non-zero) if wg0 is down.
|
||||||
|
- [ ] Public `http://<public-ip>` 80/443 now **refused / times out**; the tunnel still serves the panel.
|
||||||
|
- [ ] **SSH still works** (port 22 untouched).
|
||||||
|
- [ ] `clusev wg status` shows the peer + gate on (marker `/etc/clusev/wg-gate.enabled` present, chain
|
||||||
|
`CLUSEV-WG-GATE` present).
|
||||||
|
- [ ] Add a manual rule: `sudo iptables -I DOCKER-USER -s 203.0.113.0/24 -j RETURN`. Run
|
||||||
|
`clusev wg down` then `clusev wg up` → the manual rule **survives** (only `CLUSEV-WG-GATE` and
|
||||||
|
its jump are touched). Remove it afterwards.
|
||||||
|
|
||||||
|
## persistence
|
||||||
|
- [ ] Reboot → wg0 + the gate come back (public still refused, tunnel still serves).
|
||||||
|
- [ ] Restart Docker: `sudo systemctl restart docker` → the gate is re-applied (Docker flushes
|
||||||
|
`DOCKER-USER`, the `clusev-wg-gate.service` re-runs via `WantedBy=docker.service`). Public still refused.
|
||||||
|
- [ ] Force wg0 to fail on boot (`sudo systemctl disable wg-quick@wg0` + reboot) → the gate is **NOT
|
||||||
|
applied** (`ConditionPathExists=/sys/class/net/wg0` fails the unit), the panel is publicly
|
||||||
|
reachable (NOT bricked); SSH + `clusev wg down` recover. Re-enable wg0 afterwards.
|
||||||
|
|
||||||
|
## peers + down
|
||||||
|
- [ ] `clusev wg add-peer client-2` → new config + QR; the split-vs-full-tunnel note is shown.
|
||||||
|
- [ ] `clusev wg remove-peer client-2` → peer gone from `wg show wg0` AND from `/etc/wireguard/wg0.conf`.
|
||||||
|
- [ ] A peer name with a space or odd character round-trips (add then remove) without corrupting wg0.conf.
|
||||||
|
- [ ] `clusev wg down` → public open again; marker + `CLUSEV-WG-GATE` chain gone (`clusev wg status`).
|
||||||
|
|
||||||
|
## Known SP1 limitations (by design — not bugs)
|
||||||
|
- Peer-IP allocation + the subnet collision check assume the default **/24** (`next_free_ip` scans
|
||||||
|
`.2–.254`; the collision check matches the first three octets). Non-/24 subnets work for the tunnel
|
||||||
|
but allocation is /24-shaped. Wider prefixes are SP2 territory.
|
||||||
|
- The collision check is a heuristic (first-three-octets match against host routes/addresses), not a
|
||||||
|
formal CIDR-overlap proof — it catches the common LAN clash, which is the point.
|
||||||
|
- Peers are stored only in `wg0.conf` (no DB). SP2 adds the dashboard status page + peer models.
|
||||||
Loading…
Reference in New Issue