— bash — netgod.dev — 80×24
guest@netgod.dev:~/blog$ cat wireguard-mesh-for-my-homelab.md
← cd ../blog
POST(VPN)netgod.dev manualPOST(VPN)
NAME

$ Building a WireGuard Mesh for My Homelab

DESCRIPTION

I replaced a hub-and-spoke OpenVPN setup with a full mesh of WireGuard peers. Latency dropped, complexity dropped, and I finally understand why everyone moved.

DATE
2025-04-25
DURATION
1 min read
TAGS
./assets/wireguard-mesh-for-my-homelab.pngcover
CONTENT

WireGuard collapsed an entire layer of YAML config into ~10 lines per peer. After a year of running it across 4 sites, here's what I'd tell my past self.

Why mesh, not hub-and-spoke

A hub means every cross-site packet does a round trip through one node. With three sites that's fine. With seven it's painful.

A full mesh means each peer knows every other peer directly. WireGuard's stateless UDP makes this cheap — no persistent connections to manage.

The minimal config

[Interface]
PrivateKey = <yours>
Address = 10.20.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <theirs>
AllowedIPs = 10.20.0.2/32
Endpoint = peer.example.com:51820
PersistentKeepalive = 25

That's it. No certificates, no PKI, no easy-rsa ritual.

The trick: AllowedIPs is routing

This is the part everyone trips on. AllowedIPs is both an ACL and a route. Whatever IPs you list there get pushed into the kernel routing table pointing at this peer. That's how you build the mesh — each peer's AllowedIPs defines the slice of the mesh it owns.

What I'd skip

Don't bother with wg-quick for production. Use systemd-networkd natively — it survives reboots cleanly and integrates with networkctl.

netgod.dev manual2025-04-25END