From 854732bab1fda3d7d2c5bb125148575426ae71f8 Mon Sep 17 00:00:00 2001 From: Lovebug MCP Date: Mon, 25 May 2026 12:51:22 +0000 Subject: [PATCH] =?UTF-8?q?mcp:=20project-plan=20=E2=80=94=20WireGuard=20P?= =?UTF-8?q?ostgres=20Access=20=E2=80=94=20Tower=20to=20herbys-dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/Homelab/wireguard-postgres-access.md | 105 +++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Sources/Homelab/wireguard-postgres-access.md diff --git a/Sources/Homelab/wireguard-postgres-access.md b/Sources/Homelab/wireguard-postgres-access.md new file mode 100644 index 0000000..8adf6e2 --- /dev/null +++ b/Sources/Homelab/wireguard-postgres-access.md @@ -0,0 +1,105 @@ +--- +created: '2026-05-25' +path: Sources/Homelab +project: wireguard-postgres-access +tags: +- wireguard +- postgres +- networking +- knot +- homelab +- herbys-dev +type: project-plan +--- + +## Summary + +Stand up a hand-rolled WireGuard hub-and-spoke overlay terminating on herbys-dev, with Postgres (currently serving 5 MCP services) as the first consumer. Tower (Lab/11) connects over the tunnel to access Postgres on herbys-dev (Private/21) without opening a Lab→Private firewall hole. Knot DNS serves `*.wg.herbylab.dev` for stable hostname access. + +## Goals + +- Tower → herbys-dev Postgres access without VLAN firewall changes +- Future-proof shape: additional peers (other hosts, other services) drop in cleanly +- Knot DNS authoritative for the overlay subdomain from day one +- Manual setup first, Ansible-ize later once the shape is proven + +## Architecture Decisions + +- **Topology**: Hub-and-spoke. herbys-dev is the hub (services live there); all other peers dial in. +- **Termination point**: WireGuard interface on the herbys-dev VM host (not inside containers). Services bind to the hub WG IP via Docker port mapping. +- **Interface name**: `wg-lan` +- **Subnet**: `10.99.0.0/24` (no collision with `10.0.x.x` LAN VLANs) + - hub (herbys-dev): `10.99.0.1` + - tower: `10.99.0.2` + - room for future peers `.3`+ +- **Listen port**: UDP/51820 on herbys-dev +- **Key management**: per-host generation; private keys never leave the host; public keys registered with hub +- **DNS**: Knot serves `wg.herbylab.dev` zone. Names like `db.wg.herbylab.dev` → `10.99.0.1`, `herbys-dev.wg.herbylab.dev` → `10.99.0.1`, etc. +- **Postgres exposure**: Compose `ports:` rebinds from localhost to `10.99.0.1:5432`. `pg_hba.conf` allows `10.99.0.0/24`. + +## Why not the alternatives + +- **Direct VLAN routing**: opens Lab→Private firewall hole; any future Lab host can hit Postgres. Tunnel-as-access-control is cleaner. +- **Tailscale**: works fine and is peer-to-peer on LAN, but adds a third-party control plane for a two-host LAN-local need. WireGuard is already in-kernel. +- **Traefik TCP passthrough**: wrong layer for L4 forwarding of one port. Traefik stays HTTP(S)-focused. +- **SSH tunnel**: per-session, dies with the connection. Not viable for always-on MCPs. + +## Phases + +### Phase 1 — Hub setup on herbys-dev + +- [ ] Install `wireguard` package (Ubuntu repos) +- [ ] Generate hub keypair (`wg genkey | tee privatekey | wg pubkey > publickey`) +- [ ] Write `/etc/wireguard/wg-lan.conf` with `[Interface]` block (private key, address `10.99.0.1/24`, listen port 51820) +- [ ] Open UDP/51820 on herbys-dev firewall + OpenWrt firewall rule allowing tower VLAN → herbys-dev:51820 +- [ ] `systemctl enable --now wg-quick@wg-lan` +- [ ] Verify interface up with `wg show` + +### Phase 2 — Tower peer + +- [ ] Install `wireguard` on tower (Endeavour OS) +- [ ] Generate tower keypair +- [ ] Add tower's `[Peer]` block to hub config; reload hub +- [ ] Write tower's `/etc/wireguard/wg-lan.conf` with `[Interface]` (tower key, `10.99.0.2/24`) and `[Peer]` (hub pubkey, endpoint `10.0.21.207:51820`, AllowedIPs `10.99.0.0/24`, PersistentKeepalive 25) +- [ ] Bring tunnel up; verify handshake with `wg show` +- [ ] Ping `10.99.0.1` from tower + +### Phase 3 — Knot DNS records + +- [ ] Add `wg.herbylab.dev` zone (or records under existing zone) +- [ ] `db.wg.herbylab.dev` → `10.99.0.1` +- [ ] `herbys-dev.wg.herbylab.dev` → `10.99.0.1` +- [ ] Verify resolution from tower via Pi-hole conditional forwarding + +### Phase 4 — Postgres rebind + +- [ ] Update Postgres container compose: `ports: - "10.99.0.1:5432:5432"` +- [ ] Verify `listen_addresses = '*'` in `postgresql.conf` +- [ ] Add `pg_hba.conf` rule: `host all 10.99.0.0/24 scram-sha-256` +- [ ] Reload Postgres +- [ ] Test connection from tower: `psql -h db.wg.herbylab.dev -U -d ` +- [ ] Verify existing 5 MCP services still connect (they're on the host's loopback or docker network — bind change shouldn't affect them, but verify) + +### Phase 5 — Documentation & follow-ups + +- [ ] Document peer registration steps for future hosts +- [ ] Capture key rotation procedure +- [ ] Decide Ansible role shape (extend existing in-progress role) + +## Open Questions + +- Does the Postgres rebind to `10.99.0.1:5432` break the 5 existing MCP services? Need to confirm how they currently connect (loopback on host? docker network?). May need to bind to multiple addresses or rethink published port. +- Should `wg-lan` come up before Docker, so Postgres can bind to it on boot? `After=wg-quick@wg-lan.service` on the docker unit, or reorder via compose. + +## Future-Proofing Notes + +- Subnet has room for ~250 peers; way more than needed +- New peer = one `[Peer]` block on hub + one config on new host +- Any future service on herbys-dev can bind to `10.99.0.1` and inherit the same access model +- When Ansible role lands, hub config becomes templated from peer registry + +## References + +- Related: `traefik-deployment` (Knot DNS already deployed) +- Related: `postgres-consolidation-reflection-layer` (the Postgres instance this exposes) +- Related: `herbys-dev-setup` (host this terminates on) \ No newline at end of file