You installed WireGuard on your VPS. You read three contradictory tutorials. The wg0.conf you pasted doesn't ping, or it pings but DNS leaks, or the kill switch nukes your entire machine when you disconnect. The cause is almost always the same: a template copied without understanding the original context.
This guide ships 8 production-ready wg0.conf templates for the Contabo Cloud VPS 10, with use case, known gotchas, and the four lines you need to adapt. Pick the one that matches your scenario, swap keys, connect. Five minutes.
Why use templates instead of generating everything by hand
WireGuard is known for having a minimalist configuration compared to OpenVPN, but minimalist doesn't mean trivial. Every section has an implicit meaning that tutorials copy-paste without explaining, and a single wrong value can either silently break the tunnel or leak traffic in the clear with no immediate visible symptom. Over the past six months we counted more than twenty Reddit threads where beginners asked the same question: "my tunnel comes up, ping works to the server, but no HTTP connection works from the client". In 9 out of 10 cases it was a misplaced AllowedIPs or a missing PostUp/PostDown.
The templates below cover 8 distinct, real-world deployment scenarios. Each one ships with a context comment describing who it's for, what it guarantees, and the known limits. If your case matches the template at 80%, you adapt the remaining 20%; if your case fits no template, you rebuild from the closest template and keep only the directives that apply to you. That's faster than starting from scratch and more reliable than re-stitching from a random 2020 Stack Overflow answer.
The other reason to use templates is long-term maintenance. When WireGuard 1.1 ships (likely 2026-2027) with directive changes, we'll republish the templates with the adjustments clearly marked, and you'll know exactly which line to update in your wg0.conf. It's the VPN equivalent of a versioned Kubernetes manifest - the value isn't in the initial content, it's in the ability to iterate cleanly on top.
Shared conventions
Every template follows the same rules - simplify your mental model:
- Client subnet:
10.66.66.0/24(peers.2→.254) - Public server interface:
eth0(check withip route | awk '/default/ {print $5}') - UDP port:
51820(changeable and must be opened in the firewall; see template 7 obfuscation) - Keys: generated via
wg genkey | tee server.key | wg pubkey > server.pub - Sysctl:
net.ipv4.ip_forward=1enabled on the server (/etc/sysctl.conf) - MTU: 1420 by default, tuned when needed
PrivateKey blocks below are placeholders - replace with your own. Never commit these files to a public git repo.
Template 1 - Standard WireGuard server (1 roadwarrior client)
The most common case: your Contabo VPS exposes a tunnel for your MacBook on the road.
# /etc/wireguard/wg0.conf (server)
[Interface]
PrivateKey = SERVER_PRIVATE_KEY_HERE
Address = 10.66.66.1/24
ListenPort = 51820
MTU = 1420
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# Eric's MacBook
PublicKey = CLIENT_PUBLIC_KEY_HERE
AllowedIPs = 10.66.66.2/32
Client side:
# /etc/wireguard/wg0.conf (macOS/Linux client)
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.66.66.2/24
DNS = 9.9.9.9, 149.112.112.112
MTU = 1420
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Watch points:
AllowedIPs = 0.0.0.0/0, ::/0routes ALL client traffic through the VPS - that's what you want for a classic VPN.PersistentKeepalive = 25is mandatory if the client sits behind NAT (hotel network, 4G) - without it, the tunnel dies after ~3 min of idle.DNS = 9.9.9.9forces Quad9 resolution - otherwise the client uses local DNS and your queries leak.
Template 2 - Home VPN (split-tunnel: local LAN excluded)
You want VPN for your web traffic but keep local LAN access (printer, NAS) without going through the tunnel.
# Home client
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.66.66.2/24
DNS = 9.9.9.9
MTU = 1420
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
# Everything except RFC1918 LAN + multicast + APIPA
AllowedIPs = 0.0.0.0/1, 128.0.0.0/2, 192.0.0.0/3, 224.0.0.0/4, 240.0.0.0/5, 248.0.0.0/6, 252.0.0.0/7, 254.0.0.0/8, 255.0.0.0/9
PersistentKeepalive = 25
The fragmented subnet trick (instead of 0.0.0.0/0) makes WireGuard add specific routes that don't override the default route. Your 192.168.x.x and 10.x.x.x LAN stay reachable directly.
Online tools to generate these ranges: wg-allowed-ips.compute() or Tunsafe / WireGuard Network Calc.
Template 3 - Travel VPN with strict netfilter kill switch
You're flying to China, Iran, Russia. If the tunnel drops, nothing leaks. Solution: netfilter kill switch that drops everything except traffic via wg0 and the server handshake.
# Travel kill-switch client
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.66.66.2/24
DNS = 9.9.9.9
MTU = 1280
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PostUp = ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Those four PostUp/PreDown lines are the real kill switch - not an application popup. Until wg-quick down wg0 runs, no packet leaves the interface that isn't WireGuard-marked.
MTU 1280 for picky networks (hotels, 3G). Losing 1% throughput beats a flaky tunnel.
Template 4 - Multi-peer (5 devices, same user)
You have a MacBook, iPhone, iPad, work VPS, Raspberry Pi. You want them all routed via the same VPN with separate subnets for monitoring.
# /etc/wireguard/wg0.conf (server)
[Interface]
PrivateKey = SERVER_PRIVATE_KEY_HERE
Address = 10.66.66.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# MacBook
PublicKey = MAC_PUBKEY
AllowedIPs = 10.66.66.2/32
[Peer]
# iPhone
PublicKey = IPHONE_PUBKEY
AllowedIPs = 10.66.66.3/32
[Peer]
# iPad
PublicKey = IPAD_PUBKEY
AllowedIPs = 10.66.66.4/32
[Peer]
# Worker VPS (Hetzner)
PublicKey = WORKER_PUBKEY
AllowedIPs = 10.66.66.5/32
[Peer]
# Raspberry Pi home
PublicKey = RPI_PUBKEY
AllowedIPs = 10.66.66.6/32
Each peer holds a fixed IP on the 10.66.66.0/24 subnet. If you monitor via Prometheus (see the monitoring guide), you can label by IP and know who burns how much bandwidth.
Template 5 - Hub-and-spoke (peer-to-peer between clients)
By default WireGuard doesn't route between peers. If you want your iPhone to talk to your Raspberry Pi through the hub server:
On the server, add:
sysctl -w net.ipv4.ip_forward=1
And in server [Peer] blocks, set AllowedIPs = 10.66.66.X/32 (peer's unique IP).
On the clients, change AllowedIPs:
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
# Whole subnet, not just 0.0.0.0/0
AllowedIPs = 10.66.66.0/24
Now from your iPhone (10.66.66.3) you can ssh pi@10.66.66.6 directly - the hub forwards.
Template 6 - Per-peer egress restriction (allowlist)
Advanced case: a peer (your kid, a guest, an automated service) should connect to the tunnel but only reach specific domains/IPs.
Add to the server PostUp, in addition to MASQUERADE:
iptables -A FORWARD -s 10.66.66.50/32 -d 1.1.1.1 -j ACCEPT
iptables -A FORWARD -s 10.66.66.50/32 -d 142.250.0.0/15 -j ACCEPT # Google
iptables -A FORWARD -s 10.66.66.50/32 -j REJECT
Peer 10.66.66.50 can only reach 1.1.1.1 (DNS) and Google IPs. Everything else is rejected.
Template 7 - Obfuscation on port 443 via udp2raw
Some corporate firewalls block outbound UDP. Solution: encapsulate WireGuard inside fake TCP/443 via udp2raw.
Server side:
udp2raw_amd64 -s -l 0.0.0.0:443 -r 127.0.0.1:51820 -k "p@ssw0rd_long" --raw-mode faketcp
Client side:
udp2raw_amd64 -c -l 127.0.0.1:50000 -r vpn.example.com:443 -k "p@ssw0rd_long" --raw-mode faketcp
In the client wg0.conf, change Endpoint:
Endpoint = 127.0.0.1:50000
Throughput drops (~30% overhead) but it tunnels through almost any corporate DPI.
Template 8 - Site-to-site (two LANs bridged)
Two houses, two Raspberry Pi gateways, one Contabo VPS as hub. Each LAN sees the other as if it were local.
Server (VPS hub):
[Interface]
PrivateKey = HUB_PRIVATE_KEY_HERE
Address = 10.66.66.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# Site A (LAN 192.168.10.0/24)
PublicKey = SITE_A_PUBKEY
AllowedIPs = 10.66.66.10/32, 192.168.10.0/24
[Peer]
# Site B (LAN 192.168.20.0/24)
PublicKey = SITE_B_PUBKEY
AllowedIPs = 10.66.66.20/32, 192.168.20.0/24
Site A (Raspberry Pi):
[Interface]
PrivateKey = SITE_A_PRIVATE_KEY_HERE
Address = 10.66.66.10/24
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
[Peer]
PublicKey = HUB_PUBLIC_KEY_HERE
Endpoint = vpn.example.com:51820
AllowedIPs = 10.66.66.0/24, 192.168.20.0/24
PersistentKeepalive = 25
Don't forget ip_forward on both Raspberries and a static route on other LAN machines if they need to answer from the other site.
Quick diagnostic when nothing works
You pasted the template, you run wg-quick up wg0, it starts - but ping fails. Checklist in this order:
wg show: last handshake recent? If "never" → handshake KO, checkEndpoint, UDP port on server firewall (ufw statusoriptables -L).ip routeon client: route to VPN subnet present? If not → clientAllowedIPsborked.dig @9.9.9.9 ifconfig.me +shortfrom connected client: does it return the VPS IP? If not → MASQUERADE missing on server, orip_forward = 0.tcpdump -i wg0on server: do you see packets coming in? If yes but nothing exitseth0→ FORWARD/MASQUERADE rule missing.- MTU:
ping -M do -s 1400 1.1.1.1from client. If "Frag needed" → drop MTU inwg0.confto 1380 or 1280. Our WireGuard MTU fix guide walks the full do-not-fragment measurement and the right value per link type.
If you're starting from scratch and stuck, the Contabo step-by-step setup guide walks the entire install from initial SSH.
In production: what these templates skip
They're intentionally minimal. For long-term prod, plan:
- Regular backup of
/etc/wireguard/(losing the server key = regen all clients) - Key rotation every 12-18 months (procedure: generate new key, add parallel peer, migrate clients one by one, retire old peer)
- Monitoring via Prometheus +
wireguard_exporter(see monitoring guide) - Fail2ban on UDP port 51820 if you spot port scan attempts in
journalctl -u wg-quick@wg0 - Per-peer bandwidth limit via
tc(Linux traffic control) if a peer hogs throughput
And above all: never commit a real wg0.conf to a repo, even private. Keep them .gitignore'd or encrypt with age / sops.
When WireGuard isn't enough: V2Ray for censored countries
WireGuard is excellent for standard privacy use cases. However, vanilla WireGuard (including NordLynx) is now systematically blocked by China's Great Firewall and increasingly filtered in Russia and Iran - GFW's ML-DPI fingerprints WireGuard sessions within minutes.
If your goal is to bypass active censorship (China, Iran, Russia), WireGuard templates won't help on their own. You need obfuscation: either WireGuard + Cloak (TLS masking layer) or a full protocol switch to V2Ray VMess/VLESS with REALITY for China, Iran, Russia. V2Ray's REALITY protocol makes your server indistinguishable from a Microsoft CDN node - the current state of the art against GFW's deep packet inspection in 2026.
Going deeper
If you want to understand why WireGuard outpaces OpenVPN at equal CPU, we ran a detailed technical comparison with real iperf3 benchmarks on Contabo, kernel module vs userspace, and iPhone battery profile.
And for the leak-stopper part, the Linux kill switch guide (iptables + systemd) shows how to guarantee zero leak even when WireGuard crashes.
Prefer a visual wizard over raw INI blocks? Our WireGuard config generator takes your server IP, subnet and peer count and outputs a ready-to-paste wg0.conf in under a minute. And to check whether the Contabo Cloud VPS 10 is cheaper than your current NordVPN plan over 2 years, plug the numbers into our self-hosted VPN cost calculator.
Every template above is built to run on a Contabo Cloud VPS 10 - enough headroom for a stable production tunnel plus other self-hosted services alongside it.
★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed
Run these templates on a Contabo Cloud VPS 10 → 5.50 €/moPublic IPv4 · root access · enough headroom for WireGuard + other self-hosted services→★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed
Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region→

