Site-to-Site VPN Between Two Proxmox VE Clusters via WireGuard: Fast, Lightweight, and Rock-Solid

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

The Context: When It’s 2 AM and Your Site-to-Site Backup System Crashes

It was 2 AM, and my phone started vibrating uncontrollably. The monitoring system delivered bad news: The Proxmox cluster at the branch office (Site B) couldn’t push backups to the main server (Site A). A quick check revealed that the old OpenVPN link was frozen. Latency had spiked to over 1,500ms, causing constant connection timeouts.

At that moment, I realized that maintaining a bulky, complex VPN system was a mistake. I needed something lighter, faster, and truly stable. That’s why I migrated the entire infrastructure to WireGuard.

In a lab environment with 12 VMs, I ran some tests, and the results were astounding. Transfer speeds jumped from 45Mbps (OpenVPN) to the line’s maximum capacity of 300Mbps. Meanwhile, CPU usage dropped from 15% to less than 2%. Here is how I set it up so that both Proxmox local networks can communicate seamlessly.

Step 1: Preparation and Installation

To make it easier to visualize, I’ll use actual parameters from my deployment scenario:

  • Site A (Headquarters): WAN IP: 1.2.3.4 | Local Network: 192.168.10.0/24 | WireGuard IP: 10.0.0.1
  • Site B (Branch Office): WAN IP: 5.6.7.8 | Local Network: 192.168.20.0/24 | WireGuard IP: 10.0.0.2

Since Proxmox is based on Debian, installation is straightforward. Run the following command on both nodes:

apt update && apt install wireguard -y

Next, enable IP Forwarding. This step allows Proxmox to act as a router, forwarding packets between the VPN interface and the local network. Without it, the internal Virtual Machines (VMs) won’t be able to see each other.

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p

Step 2: Generating Key Pairs

WireGuard uses public-key cryptography for security. On each node, generate a key pair and store them securely. Never share your Private Key with anyone.

mkdir -p /etc/wireguard && cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

After running these commands, each Site will have its own unique privatekey and publickey files.

Step 3: Practical Site-to-Site Configuration

Configuration at Site A (Main Server)

Create the file /etc/wireguard/wg0.conf with the following content:

[Interface]
PrivateKey = <Private_Key_Site_A>
Address = 10.0.0.1/24
ListenPort = 51820

# Routing so Site B VMs can see Site A VMs
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o vmbr0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o vmbr0 -j MASQUERADE

[Peer]
PublicKey = <Public_Key_Site_B>
AllowedIPs = 10.0.0.2/32, 192.168.20.0/24
Endpoint = 5.6.7.8:51820
PersistentKeepalive = 25

Configuration at Site B (Branch Office)

Similarly for Site B:

[Interface]
PrivateKey = <Private_Key_Site_B>
Address = 10.0.0.2/24
ListenPort = 51820

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o vmbr0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o vmbr0 -j MASQUERADE

[Peer]
PublicKey = <Public_Key_Site_A>
AllowedIPs = 10.0.0.1/32, 192.168.10.0/24
Endpoint = 1.2.3.4:51820
PersistentKeepalive = 25

Key point: The AllowedIPs line must contain the IP range of the peer network. This is how WireGuard knows which packets should be routed through the VPN tunnel.

Step 4: Activation and Verification

It’s time to fire up the system. Run the following commands on both machines:

systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

To check the status, I usually use the standard command:

wg show

If you see a latest handshake entry along with data transfer statistics, the connection is established. Finally, try pinging from a VM at Site A (192.168.10.50) to a VM at Site B (192.168.20.100). If the response is under 10ms (depending on geographic distance), you’ve succeeded.

Step 5: Real-world Troubleshooting Tips

Sometimes the tunnel shows as “up” but data doesn’t flow. In my experience, you should immediately check pve-firewall. Proxmox has a fairly strict default firewall that can sometimes block packets from unfamiliar IP ranges.

Ensure you have opened port 51820/UDP on both routers. Additionally, check the routing table using the command:

ip route show

You should see a line like 192.168.x.0/24 dev wg0. If it’s missing, WireGuard hasn’t loaded the AllowedIPs configuration. A small tip for those using dynamic IPs: Use DDNS and enter the domain in the Endpoint section. WireGuard will automatically update the new IP whenever it reconnects.

Implementing WireGuard didn’t just save me from late-night stress; it also significantly optimized server resources. If you’re managing multiple branches, this is undoubtedly the most stable and efficient solution available today.

Share: