How HydraNeck joins the HydraGuard WireGuard mesh and reads partner-managed venue routers (Citymesh MikroTik) over the tunnel — instead of over the public internet.
Companion to the Partner Network Design (high-level shared document) and the hydraguard runbooks for venue enrollment (citymesh-venue.md, omada-venue.md).
Partner-managed routers (Citymesh MikroTik at cloud-seven, rupelmonde) do not accept API calls from the public internet. The design avoids public-internet API exposure entirely by routing operator-side access through the WireGuard mesh:
hydraneck.experiencenet.com (Hetzner nbg1)
│ air peer in mesh
▼
HydraGuard Hub (Brussels, 10.10.0.1)
│ WG tunnel
▼
Citymesh MikroTik @ cloud-seven (10.10.2.1)
│ routes venue LAN
▼
Venue LAN 10.0.X.0/24
Side benefits:
HydraNeck is enrolled once as a Hydra Air peer (10.10.100.x range). It doesn't bridge a LAN of its own; it just consumes the mesh.
ssh ubuntu@hydraguard.experiencenet.com
hydraguard air add hydraneck
hydraguard apply
hydraguard air config hydraneck > /tmp/hydraneck.wg.conf
The private key is printed to stdout once on air add; save it. air config includes it in the generated file.
ssh root@hydraneck.experiencenet.com
apt-get install -y wireguard
install -m 600 /path/to/hydraneck.wg.conf /etc/wireguard/wg0.conf
systemctl enable --now wg-quick@wg0
wg show # expect handshake with the hub
ping -c1 10.10.0.1 # hub
Once at least one venue peer is installed by the partner:
ping -c1 10.10.2.1 # cloud-seven MikroTik (WG side)
curl -sk https://10.10.2.1/rest/system/resource # MikroTik REST over WG
If hydraneck can ping the venue but the venue cannot ping hydraneck, the issue is a missing MikroTik route — MikroTik does not auto-derive routes from WireGuard AllowedIPs. Citymesh must add /ip route add dst-address=10.10.0.0/16 gateway=<wg-interface> manually. This is always the Citymesh side; hydraneck and the hub are open to all wg0→wg0 traffic.
Once HydraNeck has mesh reach, point per-venue MikroTik credentials at the WG-side address (NOT a public WAN IP). Edit /root/.hydraneck/config.yaml.
Before doing so, confirm with the partner that HydraNeck's WG address is allowlisted in the MikroTik firewall for inbound TCP 443 (REST) and optionally TCP 8729 (legacy binary). The hub does pure routing with no NAT — the MikroTik sees HydraNeck's WG IP (10.10.100.14 for the current air-hydraneck enrollment) as the source, not the hub IP. No public internet IP needs to be whitelisted.
venues:
cloud-seven:
mikrotik:
host: 10.10.2.1 # WG tunnel address, not public WAN
user: <readonly-user-from-partner>
pass: <password-from-partner>
transport: rest # REST on :443 — preferred
# transport: legacy # legacy binary on :8729 — fallback
rupelmonde:
mikrotik:
host: 10.10.3.1
user: <readonly>
pass: <password>
transport: rest
The exact WG addresses (10.10.2.1, 10.10.3.1, …) are whatever hydraguard apply assigned — confirm via hydraguard status on the hub or the venue's row in mesh.yaml.
Self-signed TLS certs on RouterOS are the normal posture; the REST client in pkg/mikrotik/rest handles this — no extra configuration required on the consumer side.
After updating the config, restart hydraneck:
systemctl restart hydraneck
hydraneck scan cloud-seven # expect non-empty Clients() and Bandwidth()
If a venue's partner peer isn't installed yet, HydraNeck sees only the hub and any already-installed peers. Scans for the missing venue return connect-refused; the venue's tile in the admin dashboard shows offline; no crash, no cascading failures. Existing healthy venues are unaffected.
Today there is one district (Brussels). When a second district opens, two options:
wg0 for Brussels, wg1 for district-2. Per-venue config carries the right WG address.No decision required until a second district is real. The single-hydraneck path is simpler and works fine if interface counts stay manageable.
End-to-end smoke after a fresh enrollment:
ssh root@hydraneck.experiencenet.com wg show — handshake with the hub.ping -c1 10.10.0.1 from the hydraneck server.curl -sk https://<venue-WG-IP>/rest/system/resource — RouterOS responds with system info JSON.hydraneck scan <venue> — clients and bandwidth populated./admin/venues/<venue> — correlation table populated, no red rows for known bodies.hydraguard/docs/runbooks/citymesh-venue.md — the matching hub-side procedure for enrolling a Citymesh venue.hydraguard/docs/runbooks/air-body.md — the air-peer enrollment pattern reused here for hydraneck.