Build a WireGuard VPN
Configure the WireGuard peers
Give each interface its private address and key, then authorize the exact address owned by the other peer.
8 minute lesson
Each peer needs a config with two parts: an [Interface] section describing itself, and a [Peer] section describing who it talks to.
Create /etc/wireguard/wg0.conf on the server:
[Interface]
Address = 10.14.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
[Peer]
PublicKey = LAPTOP_PUBLIC_KEY
AllowedIPs = 10.14.0.2/32
The server describes itself with its VPN address, its listening port, and its private key. The [Peer] block authorizes the laptop: traffic from that public key may claim the source address 10.14.0.2, and traffic destined to 10.14.0.2 goes to that peer.
On the laptop, create the matching peer configuration:
[Interface]
Address = 10.14.0.2/24
PrivateKey = LAPTOP_PRIVATE_KEY
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.14.0.0/24
PersistentKeepalive = 25
The asymmetries are worth reading twice. Only the laptop has an Endpoint, because only the laptop knows where to find the other side — the server learns the laptop’s address from its first authenticated packet, which is what lets the laptop roam between networks. The laptop’s AllowedIPs covers the whole 10.14.0.0/24, sending the entire VPN subnet through the tunnel. And PersistentKeepalive = 25 sends a small packet every 25 seconds so the NAT mapping in the laptop’s home router never expires.
AllowedIPs is the setting people misread. It does two jobs at once: it is a routing rule (which destinations go to this peer) and a source filter (which addresses this peer is allowed to use). Narrow on the server — exactly /32 per client — and wider on the client.
Replace the documented placeholders locally with the keys you generated. Then set private configuration permissions to 600, because the file contains a private key:
sudo chmod 600 /etc/wireguard/wg0.conf
The classic mistake here is swapped keys. Each [Peer] block must contain the other side’s public key. Paste a peer’s own public key into its config and the handshake never completes — wg show will report the peer with no latest handshake line, which is your cue to re-check every key.
Lesson completed