WireGuard on Hetzner

A practical guide to setting up and securing WireGuard on Hetzner servers for fast, private VPN tunnels.
the article body in Markdown:
WireGuard is a modern, lean VPN protocol that provides fast, secure tunneling with simple configuration. If you’re hosting services or connecting remote machines on Hetzner, WireGuard can offer a reliable, low-overhead solution. This guide walks you through deploying WireGuard on Hetzner servers, covering installation, configuration, firewall considerations, and tips for performance and maintenance.
Why choose WireGuard on Hetzner?
Hetzner provides powerful servers with generous bandwidth and predictable latency. WireGuard complements this by delivering:
- Simplicity: a small codebase and minimal configuration.
- Speed: efficient cryptography and a lightweight protocol.
- Security: robust modern cryptography and straightforward key management.
When you run WireGuard on Hetzner, you’re often balancing two use cases: a private site-to-site link between your Hetzner instances or a client-to-site VPN for remote access to services hosted on Hetzner. The setup is the same in principle, with several best practices to ensure reliability and security.
Prerequisites and planning
Before you start, prepare these basics:
- A Hetzner server (cloud or dedicated) with a public IPv4 address and an optional IPv6 allocation.
- A non-root user with sudo privileges on each host you plan to connect.
- Basic network knowledge: IP subnets, routing, port forwarding.
- A plan for your allowed IPs and peer keys. WireGuard uses public/private key pairs for each peer.
Useful planning questions:
- Will this be a point-to-point tunnel between two Hetzner servers, or a hub-and-spoke with multiple clients?
- What subnets will you allocate for the VPN (e.g., 10.0.0.0/24 for the tunnel network)?
- Do you want persistent keepalive, and what intervals fit your network stability?
Installing WireGuard on Hetzner servers
The exact commands depend on your Linux distribution. Here’s a typical setup for Debian/Ubuntu and RHEL/CentOS families. WireGuard on Vultr: a practical guide to deploying secure VPN servers
Debian/Ubuntu
Update: sudo apt update && sudo apt upgrade -y
Install: sudo apt install wireguard-tools wireguard-dkms
Enable kernel module: sudo modprobe wireguard
Verify: sudo wg, version WireGuard on Linode: a practical guide to setting up secure VPN access
Red Hat / CentOS / Rocky
Enable EPEL (if needed) and install: sudo dnf install epel-release
Install: sudo dnf install wireguard-tools wireguard-kernel
Enable: sudo modprobe wireguard
Verify: sudo wg, version WireGuard on Oracle Cloud
Key file locations:
- Private / public keys per peer: typically in ~/.ssh or ~/.config/wireguard/keys.
- Interface config file: /etc/wireguard/wg0.conf (on most setups, wg0 is the common name).
Generating keys (one-time per host or per peer):
- Generate: wg genkey | tee privatekey | wg pubkey > publickey
- The privatekey is kept secret. The publickey is shared with peers.
Core configuration: wg0.conf example
A minimal, practical example to connect two Hetzner servers (A and B) over a private tunnel.
On Server A (IP 1.2.3.4, internal subnet 10.0.0.0/24)
- Contents of /etc/wireguard/wg0.conf: [Interface] Address = 10.0.0.1/24 PrivateKey = SERVER_A_PRIVATEKEY ListenPort = 51820 MTU = 1420
[Peer] PublicKey = SERVER_B_PUBLICKEY AllowedIPs = 10.0.0.2/32 Endpoint = 1.2.3.4:51820 PersistentKeepalive = 25 WireGuard on DigitalOcean
On Server B (IP 5.6.7.8, internal subnet 10.0.0.0/24)
- Contents of /etc/wireguard/wg0.conf: [Interface] Address = 10.0.0.2/24 PrivateKey = SERVER_B_PRIVATEKEY ListenPort = 51820 MTU = 1420
[Peer] PublicKey = SERVER_A_PUBLICKEY AllowedIPs = 10.0.0.1/32 Endpoint = 5.6.7.8:51820 PersistentKeepalive = 25
Notes:
- Addresses: 10.0.0.1/24 and 10.0.0.2/24 are the tunnel endpoints. You can choose another private subnet as long as it doesn’t collide with existing networks.
- AllowedIPs defines which IPs are reachable via the tunnel. For a simple point-to-point link, use the tunnel IPs. For hosting multiple subnets, you might use 0.0.0.0/0 to route all traffic through the tunnel, but consider performance and security.
Starting and enabling:
- Start: sudo wg-quick up wg0
- Enable on boot: sudo systemctl enable wg-quick@wg0
- Check status: sudo wg show
If you plan to route traffic from other networks through this tunnel, you’ll need to adjust the server’s routing table and enable IP forwarding: WireGuard on Google Cloud: a practical guide to deploying secure VPNs in GCP
- Enable IP forwarding: echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- For IPv6, enable net.ipv6.conf.all.forwarding similarly if you intend to route IPv6.
Firewall, NAT, and traffic rules
Hetzner servers sit behind a firewall that may block UDP 51820 by default. Ensure the following:
- UDP port 51820 is open on both servers (or the port you choose for the WireGuard interface).
- If you want to route traffic from the private tunnel to the public network or vice versa, you may need NAT rules.
Example UFW rules for Debian/Ubuntu:
- Allow WireGuard: sudo ufw allow 51820/udp
- Allow forwarding: sudo bash -c 'echo "net/ipv4/ip_forward=1" >> /etc/ufw/sysctl.conf'
- Add a basic NAT rule if routing to the Internet through the tunnel:
- sudo ufw default allow routed
- sudo ufw route allow in on wg0 out on eth0
- sudo ufw allow in on eth0 to any port 22
- If using firewalld (RHEL/CentOS):
- sudo firewall-cmd, add-port=51820/udp/udp
- sudo firewall-cmd, permanent, add-port=51820/udp
- Enable masquerading if you want NAT: sudo firewall-cmd, add-masquerade, permanent
Remember: keep a fallback console or a separate management path when opening firewall rules, so you don’t lock yourself out.
DNS, routing, and multi-hop setups
- DNS considerations: Use a consistent DNS strategy for endpoints behind WireGuard. If you route traffic for specific services through the tunnel, ensure DNS resolution doesn’t leak to the public internet in an unintended way.
- Splitting vs. full tunneling:
- Point-to-point (split) routing: Only traffic destined for the tunnel endpoints uses WireGuard. This is simpler and often safer.
- Full tunnel (0.0.0.0/0) routing: All traffic travels through the tunnel. This can be convenient for privacy or accessing private networks but adds overhead and potential latency. Use policy-based routing if you need selective traffic through the tunnel.
Table: comparison of routing modes
| Routing mode | Pros | Cons |
|---|---|---|
| Point-to-point | Simple, low overhead, stable | Only connects specific subnets |
| Full-tunnel | All traffic protected, easier to enforce | Higher latency, more bandwidth usage |
| Split-tunnel (custom) | Flexible, controls who uses the tunnel | Requires careful route management |
Monitoring, maintenance, and troubleshooting
- Basic checks:
- sudo wg show to verify peers and data transfer
- ip a to check WireGuard interface presence (wg0 with 10.0.0.x addresses)
- netstat -nupu or ss to see active connections
- Common issues:
- Mismatched public keys or pre-shared keys: re-check keys on both sides.
- Firewall blocking UDP: verify UDP 51820 (or your chosen port) is allowed.
- Endpoint reachability: if behind NAT or behind a firewall, ensure port-forwarding or proper NAT traversal is possible. Consider using PersistentKeepalive to maintain NAT mappings.
- Automatic health checks:
- Use systemd timers or cron jobs to periodically verify and restart wg-quick if the tunnel drops.
- Watchdog or uptime monitoring to alert if the tunnel is down for a threshold duration.
Security best practices on Hetzner
- Use distinct keypairs for each peer and rotate keys periodically.
- Keep the private keys on hosts offline or in restricted permissions (chmod 600, owner root).
- Use a non-default, non-well-known port for WireGuard if you want to reduce surface scanning, though 51820 is standard and works well with NAT.
- Prefer route-only exposure: avoid advertising private internal networks unnecessarily to the public internet. Keep AllowedIPs as tight as possible for each peer.
- Regularly update the kernel, WireGuard tools, and encryption libraries to benefit from fixes and improvements.
Practical tips for Hetzner deployments
- IP addressing: If you use Hetzner Cloud, you can allocate internal IPs or use public IPs for endpoints. For dedicated servers, ensure correct firewall rules on their native firewall and any additional network appliances.
- IPv6 considerations: Hetzner supports IPv6 in many configurations. WireGuard can carry IPv6 traffic as well. You can assign IPv6 addresses in the tunnel (for example, 2001:db8:1::1/64 and 2001:db8:1::2/64) and adjust AllowedIPs accordingly.
- Automation: For larger deployments with many peers (branch offices or multiple VMs), consider scripting the generation of keys, pushing public keys to peers, and updating wg0.conf dynamically. Tools like Ansible, Terraform, or simple shell scripts can help keep configuration in sync.
- Backups: Keep backups of your wg0.conf and the private keys in a secure location. Use version control for non-sensitive configuration and key distribution plans (never store private keys in VCS).
Quick start recap for a two-node Hetzner setup
- Install WireGuard on both servers.
- Generate keypairs on both servers and exchange public keys.
- Create wg0.conf on both servers with a simple point-to-point configuration.
- Enable IP forwarding and configure firewall rules to allow UDP 51820 and necessary forwarding.
- Start wg-quick on both servers and confirm connectivity with ping over the tunnel (ping 10.0.0.2 from A, ping 10.0.0.1 from B).
- Optionally, set up automatic startup and monitoring to keep the tunnel healthy.
Recommendation WireGuard on Cloudflare
If you’re new to WireGuard on Hetzner, start small with a single point-to-point tunnel between two Hetzner instances. Validate the tunnel’s stability, latency, and routing behavior before scaling to multi-peer hub-and-spoke designs. Keep your keys secure, your firewall rules tight, and make IP forwarding a conscious, audited choice. Once you have a reliable baseline, you can add more peers, automate key distribution, and implement broader VPN coverage with confidence. wireguard on Hetzner is a robust, approachable solution for private networking, remote access, and secure inter-server communication.
