For years my homelab VPN was OpenVPN, and for years I half-understood it. The config files were long, the certificate authority was a thing I'd set up once following a tutorial and prayed I never had to touch again, and connecting from my phone meant a profile I'd exported in 2021 and could no longer reproduce. It worked, mostly, and every time it didn't I lost an evening to TLS errors that meant nothing to me.
I finally replaced the lot with WireGuard, and the headline is simple: the entire config for a peer fits on a postcard and I can read it.
Here's a client config in full. Not an excerpt, the whole thing:
[Interface]
PrivateKey = <client private key>
Address = 10.10.0.4/32
DNS = 10.10.0.1
[Peer]
PublicKey = <server public key>
Endpoint = home.example.net:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
That's it. There's no certificate authority, no TLS handshake, no cipher negotiation to get subtly wrong. Each end has a private key and the other end's public key, and that's the whole trust model. It's the kind of thing you can hold entirely in your head, which after years of OpenVPN felt almost suspicious, like it must be hiding something. It isn't.
The mental model that made it click: WireGuard isn't really a VPN in the OpenVPN sense of "establish a connection". It's closer to a routing table with encryption. Each peer has a list of AllowedIPs, which does double duty. Outbound, it decides which traffic goes down the tunnel. Inbound, it decides which source addresses are allowed to arrive claiming to be that peer. Once that clicked, the configs stopped being magic.
A few things bit me, so in the spirit of saving you the evening I lost.
AllowedIPs on the server side is per-peer, and it has to be the single address of that peer, not the whole subnet, or you get two peers both claiming 10.10.0.0/24 and traffic going to whichever the kernel last heard from. This is the most common WireGuard mistake and I made it within the first hour.
PersistentKeepalive matters more than the docs let on if your peers are behind NAT, which on a home connection they are. Without it the NAT mapping on your router expires after a couple of minutes of silence and inbound packets get dropped until the client sends something. Twenty-five seconds keeps the hole punched. The server, which has a stable public endpoint, doesn't need it.
DNS was the last loose end. I wanted lab hostnames to resolve over the tunnel, so I pointed each client's DNS at the lab's resolver address and let that handle it. On Linux that needs wg-quick to actually manage resolv.conf, which it does if resolvconf or systemd-resolved is present, and silently doesn't if neither is. Cue ten minutes of "why does ping work but not the hostname".
The performance is a pleasant bonus rather than the point. WireGuard runs in the kernel and the throughput on my link is noticeably better than OpenVPN managed, though honestly for homelab traffic that was never my bottleneck. The reason I switched, and the reason I'm not going back, is that I now understand my own VPN. When it breaks I can fix it, because there are about eight lines per peer and all eight make sense. OpenVPN served me well. I just don't miss it at all.