My OpenVPN setup worked, which is the most damning thing I can say about it. It had accreted over years: a certificate authority I'd set up and half-forgotten, a server.conf with options I'd copied from forums and was afraid to remove, TLS auth keys, a ccd directory of per-client overrides, and a startup that took long enough that I'd learned to be patient with it. None of it was broken. All of it was more than I wanted to maintain. So when I finally sat down with WireGuard, the thing I was really testing was whether the simplicity people kept promising was real.
It is. I'll show you the whole thing, because the whole thing fitting on a screen is the point.
the config, in its entirety
Here's the server side. This is not an excerpt. This is the file.
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <server private key>
[Peer]
# laptop
PublicKey = <laptop public key>
AllowedIPs = 10.10.0.2/32
[Peer]
# phone
PublicKey = <phone public key>
AllowedIPs = 10.10.0.3/32
And the client is the mirror image of that: its own key, the server's public key, the server's endpoint, and which addresses to route over the tunnel. There's no certificate authority. There's no TLS negotiation. There's no concept of a long-lived connection at all, because WireGuard is just UDP with public-key crypto bolted to it, and a peer is "up" the moment it has a valid key and an address. The mental model is roughly SSH keys for a network interface, and once that clicked I stopped reaching for the OpenVPN documentation entirely.
the things that actually caught me out
It wasn't completely frictionless, and the friction is worth naming so you don't lose an evening to it like I nearly did.
The first is AllowedIPs, which does double duty and confuses everyone at least once. On the client, it's a routing rule: which traffic goes down the tunnel. On the server, for a given peer, it's also the access control list: which source addresses that peer is allowed to send from. Get it wrong and your packets vanish silently with no error to chase, because WireGuard's whole design philosophy is to say nothing to anyone it doesn't recognise. That silence is a security feature and a debugging curse in equal measure.
The second is PersistentKeepalive. Because there's no persistent connection, a peer behind NAT can fall off the map once the router's UDP mapping expires, and the server has no way to reach back in. Setting PersistentKeepalive = 25 on the roaming clients sends a tiny packet often enough to hold the NAT mapping open. My phone, which roams across mobile and wifi all day, needs this. The server, with a fixed public endpoint, does not.
The third was just IP forwarding and a firewall rule, the same as any router setup: net.ipv4.ip_forward = 1 and a MASQUERADE rule so tunnel traffic could reach the rest of the LAN. Nothing WireGuard-specific, but easy to forget when you're used to OpenVPN doing more of it for you. WireGuard deliberately stays out of the routing and firewalling business; it moves packets and does crypto, and everything around that is your kernel's job, configured the normal way. That's more setup than OpenVPN's all-in-one feel, but it's setup you already understand from running any Linux box as a router, and there's no second configuration dialect to learn.
The fourth, and the one I'd flag to anyone migrating, is key management. WireGuard has no certificate authority and no enrolment protocol, which is half of why it's so simple, but it also means there's no built-in story for handing keys out or taking them back. Adding a peer is editing a file on the server and reloading. Revoking one is deleting those lines. That's fine for my handful of devices, where the whole thing fits in my head, but it's the part that would need real tooling at any scale, and it's worth being honest that "just edit the config" is a feature of small deployments, not a property of WireGuard you can lean on forever.
the part that surprised me
I expected the convenience. I didn't expect the roaming to be this good. My phone moves between the office wifi, mobile data, and home wifi over the course of a day, and with OpenVPN every one of those transitions meant a visible reconnect and a few seconds of dead air. WireGuard simply doesn't care. Because there's no session to tear down and rebuild, a peer changing its source address is a non-event. The first packet from the new address just updates where the server sends replies. I've had an SSH session survive a walk from the train to the front door without a hiccup, which OpenVPN never once managed.
The reconnect speed is the other quiet pleasure. Bringing the tunnel up is wg-quick up wg0 and it's done before you've finished reading the command. No certificate dance, no handshake you wait on. And because the interface is a real kernel network device, the usual tools work on it the usual way: ip addr, tcpdump -i wg0, ordinary routing. wg show gives you the live state of every peer, including when it last handshook and how many bytes have gone each way, which is the one piece of WireGuard-specific tooling you actually reach for and it's exactly enough.
was it worth tearing out something that worked?
Yes, and not mainly for the speed, though the speed is real and the in-kernel implementation is genuinely fast. It's still an out-of-tree module today, installed via DKMS so it rebuilds against each new kernel, and that's the one wart in an otherwise clean story. Jason has been working towards mainline and I'll happily drop the DKMS step the day it lands, but even as a module the thing has been rock solid for me. It's the surface area. OpenVPN is a large, old, flexible codebase with a configuration language that lets you do almost anything, which means there's almost always more of it loaded and running than you actually understand. WireGuard is small enough that I can hold the entire thing in my head: a handful of keys, an interface, a list of peers, two settings I might tweak. When the security boundary of your home network is something you can fully comprehend on one screen, that's worth more than any feature I gave up.
I've kept the OpenVPN config in an archive folder, the way you keep a manual for an appliance you've replaced. I don't expect to open it. The certificate authority can finally be forgotten on purpose.