HydraBooks

WireGuard Mesh Overview

8.2 KB Pushed by api Updated 23 Mar 2026 Raw

WireGuard Mesh Overview

Cross-project overview of how WireGuard connects the Hydra streaming infrastructure. This is the central entry point — individual project docs cover their specific areas.

Topology

Hub-and-spoke WireGuard mesh with a single hub in Brussels (OVHcloud). All inter-site traffic routes through the hub.

                        ┌─────────────────────────────┐
                        │   Hub (141.227.136.12)       │
                        │   10.10.0.1/24               │
                        │   OVHcloud Brussels           │
                        │                              │
                        │   Also runs:                 │
                        │   - hydraneckwebrtc controller│
                        │   - hydraneckwebrtc worker   │
                        │   - coturn TURN server       │
                        └──────────┬───────────────────┘
                                   │
              ┌────────────────────┼────────────────────┐
              │                    │                     │
     ┌────────┴────────┐  ┌───────┴────────┐  ┌────────┴────────┐
     │  Venues          │  │  Air Units      │  │  Neck Air       │
     │  10.10.1-49.x    │  │  10.10.100.x    │  │  10.10.50-99.x  │
     │  + LAN subnet    │  │  Windows bodies  │  │  + LAN subnet   │
     │  (Omada/Gateway) │  │  (render nodes)  │  │  (Mikrotik)     │
     └──────────────────┘  └─────────────────┘  └─────────────────┘

Address Scheme

| Type | WG tunnel range | LAN range | Capacity | |------|----------------|-----------|----------| | Hub | 10.10.0.1/24 | -- | 1 | | Venues | 10.10.1-49.1/32 | 10.0.X.0/24 | 49 | | Neck Air | 10.10.50-99.1/32 | 10.0.X.0/24 | 50 | | Hydra Air | 10.10.100.1-254/32 | -- (no LAN) | 254 |

How Each Project Touches WireGuard

hydraguard (mesh manager)

Manages the hub-and-spoke mesh from a single mesh.yaml inventory.

| What | Where | |------|-------| | Repo | github.com/cederikdotcom/hydraguard | | Runs on | Hub server (141.227.136.12) | | Source of truth | /root/.hydraguard/mesh.yaml | | Generated config | /etc/wireguard/wg0.conf | | API | http://hydraguard.experiencenet.com:8081 (keep stopped when not enrolling) | | Binary | /usr/local/bin/hydraguard | | Docs | runbook.md, DEPLOYMENT.md, OPERATIONS.md |

Key commands: hydraguard status, hydraguard air add <id>, hydraguard apply, hydraguard export

hydracluster (node provisioning)

Provisions WireGuard on body machines via recipes. Calls hydraguard API to enroll peers.

| What | Where | |------|-------| | Repo | github.com/cederikdotcom/hydracluster | | Runs on | hydracluster.experiencenet.com | | Recipes | recipes/hydraguard-air-windows.yaml, recipes/hydraguard-air-linux.yaml | | Config key | hydraguard.url + hydraguard.token in hydracluster config | | Integration | pkg/api/handlers_body.goprovisionHydraGuardAir() calls /api/v1/air/provision |

When a node is assigned the hydraguard-air role:

  1. Hydracluster calls hydraguard API to create the peer (gets WireGuard config back)
  2. The recipe is sent to the hydranode agent on the body
  3. Recipe installs WireGuard, writes config, starts the tunnel service

hydraneckwebrtc (WebRTC relay)

Runs on the same box as the hub. Reaches body machines via WireGuard tunnel addresses (10.10.100.x) to pair with Sunshine on port 47990 and proxy WebRTC streams.

| What | Where | |------|-------| | Repo | github.com/cederikdotcom/hydraneckwebrtc | | Runs on | Hub server (141.227.136.12) — same box as hydraguard | | Connects to bodies via | WireGuard tunnel (10.10.100.x:47990 for Sunshine API) | | TURN relay | coturn on same box, port 3478, forces iceTransportPolicy: relay |

The worker is on the hub's WireGuard interface (10.10.0.1), so it has direct mesh access to all peers without needing a separate WireGuard peer entry.

hydranode (node agent)

Runs on every body machine. Executes the hydraguard-air recipe steps that install and configure WireGuard.

| What | Where | |------|-------| | Repo | github.com/cederikdotcom/hydranode | | Runs on | Every body machine (Windows/Linux) | | WireGuard config (Windows) | C:\ProgramData\hydraguard-air\hydraguard-air.conf | | Tunnel service (Windows) | WireGuardTunnel$hydraguard-air | | Recipe execution | pkg/body/recipe.gorunPendingProvisions() |

Peer Lifecycle

1. Enroll body in hydracluster (web UI or API)
2. Assign hydraguard-air role
3. Hydracluster calls hydraguard API → peer added to mesh.yaml
4. Hydracluster sends recipe to hydranode agent
5. Hydranode installs WireGuard + writes config + starts tunnel
6. Peer handshakes with hub → body reachable at 10.10.100.x
7. hydraneckwebrtc can now create streaming sessions to the body

Key Files

On the hub (ubuntu@141.227.136.12)

| File | Purpose | |------|---------| | /root/.hydraguard/mesh.yaml | Peer inventory (source of truth) | | /root/.hydraguard/api.yaml | API server config (token, listen, auto_apply) | | /etc/wireguard/hub.key | Hub WireGuard private key | | /etc/wireguard/wg0.conf | Generated WireGuard config (from mesh.yaml) | | /root/.hydraneckwebrtc/config.yaml | Worker config (sessions, TURN, controller URL) | | /root/.hydraneckwebrtc-controller/config.yaml | Controller config (domain, admin token) | | /root/.hydraneckwebrtc-turn-credential | coturn TURN credential |

On body machines (Windows)

| File | Purpose | |------|---------| | C:\ProgramData\hydraguard-air\hydraguard-air.conf | WireGuard tunnel config | | C:\hydranode\hydranode.exe | Node agent binary |

In hydracluster

| File | Purpose | |------|---------| | recipes/hydraguard-air-windows.yaml | Recipe: install WG, write config, start tunnel, configure Sunshine | | recipes/hydraguard-air-linux.yaml | Same for Linux bodies | | recipes/hydraguard-gateway-linux.yaml | Recipe for on-prem LAN gateways |

Cross-Project Troubleshooting

Body can't reach the hub

  1. Check peer in mesh: hydraguard status on the hub
  2. Verify keys match: body's public key must match what's in mesh.yaml
  3. Check the body's tunnel: hydracluster exec <nodeId> '& "C:\Program Files\WireGuard\wg.exe" show hydraguard-air'
  4. If endpoint shows old IP, restart the tunnel on the body:
    & 'C:\Program Files\WireGuard\wireguard.exe' /uninstalltunnelservice hydraguard-air
    Start-Sleep 3
    & 'C:\Program Files\WireGuard\wireguard.exe' /installtunnelservice 'C:\ProgramData\hydraguard-air\hydraguard-air.conf'
    

hydraneckwebrtc can't reach a body ("Sunshine unreachable")

  1. Ping the body from the hub: ping 10.10.100.x
  2. If ping works but port 47990 fails: Windows Firewall on the body is blocking. Check the HydraGuard WG firewall rule allows remoteip=10.10.0.0/16
  3. If ping fails: body's WireGuard tunnel is down or key mismatch (see above)
  4. Check body's Sunshine is running: hydracluster exec <nodeId> 'Get-Service SunshineService | Format-Table Name,Status'

Peer keys got out of sync

This can happen when the hydraguard API regenerates keypairs (issue #64). Symptoms: handshake never completes, transfer: 0 B received.

Fix:

  1. Get the body's actual public key: hydracluster exec <nodeId> '& "C:\Program Files\WireGuard\wg.exe" show hydraguard-air'
  2. Update mesh.yaml on the hub to match
  3. Regenerate wg0.conf: hydraguard export > /etc/wireguard/wg0.conf
  4. Hot-reload: wg set wg0 peer <correct-key> allowed-ips 10.10.100.x/32 (remove old key too)

Recipe provisioning doesn't run on Linux nodes

The hydranode agent reports the full distro name (e.g. Ubuntu 24.04) but recipes use os: linux. Fixed in hydracluster v1.9.32 — ensure the hydracluster server is on v1.9.32+.