clusev/docs/superpowers/runbooks/wireguard-gate-runbook.md

59 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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