WireGuard VPN
Customers connect their laptops and phones to their private network with WireGuard, for example to use Remote Desktop or SSH. One central gateway VM serves all customers; the panel manages it.
laptop ──WireGuard──▶ your public IP : UDP 51820 ──▶ gateway VM (LAN)
│ customer N's devices: 10.101.N.x
│ may only reach 10.100.N.0/24
▼
Proxmox host ──▶ customer N's VNet
In the customer panel, VPN access lets customers add devices (up to
VPN_MAX_DEVICES), download the configuration or scan it as a QR code with the
WireGuard phone app, see when each device last connected, and remove devices.
The device's private key is generated by the panel, shown once and never
stored; the panel keeps only the public key. The VPN is split tunnel: only
traffic to the customer's own network goes through it.
Isolation is enforced three times: WireGuard only accepts traffic from each
device's own address; the gateway's firewall lets customer N's devices reach only
10.100.N.0/24 (and not the gateway itself); and every customer server only
accepts its own customer's VPN range.
The panel talks to the gateway through the QEMU guest agent, so the gateway needs no management port or SSH access for the panel. After every change the panel writes the complete peer list and firewall rules to the gateway and applies them at once; it also re-applies everything when the panel starts, and admins can trigger it in the admin interface (VPN tab, "Re-apply configuration").
Setup (once):
-
Create the gateway VM: a small Debian 12 or 13 VM (1 core, 512 MB, 8 GB) on your LAN bridge (
vmbr0) with a fixed LAN IP (static, or a DHCP reservation), e.g.192.168.1.110. Enable Options → QEMU Guest Agent. Don't put it into thecustomerspool. -
Run the setup script on it as root, with the Proxmox host's LAN IP:
bash setup-gateway.sh 192.168.1.105 # [port] [customer prefix] [vpn prefix]It installs WireGuard, nftables and the guest agent, creates the server key, starts
wg0on UDP 51820, and prints the gateway's public key. -
Route the VPN range on the Proxmox host to the gateway. In
/etc/network/interfaces, in thevmbr0section:post-up ip route add 10.101.0.0/16 via 192.168.1.110pre-down ip route del 10.101.0.0/16 via 192.168.1.110and apply it right away with
ip route add 10.101.0.0/16 via 192.168.1.110. -
Forward UDP 51820 on your internet router to the gateway VM, and choose a DNS name (or use your public IP) for
VPN_ENDPOINT. -
Let the panel's token manage the gateway (replace 150 with its VMID):
pveum role add PanelGateway --privs "VM.Audit VM.GuestAgent.Unrestricted"pveum acl modify /vms/150 --users panel@pve --roles PanelGateway -
Enable it in the panel's
.envand restart the panel:VPN_ENABLED=trueVPN_GATEWAY_VMID=150VPN_ENDPOINT=vpn.example.com:51820The admin interface's VPN tab should now show the gateway as running with its public key.
Servers created before the VPN was enabled get their VPN firewall rules automatically when their customer adds the first device.
Test once: as a test customer, add a device, connect with the WireGuard app
from outside your network, and open RDP or SSH to one of the customer's servers
(10.100.N.x). Then check that a server of another customer can't be reached.
Windows blocks ping by default, so test with RDP rather than ping.
If a device doesn't connect:
- "Last connected: Never" means the device never reached the gateway. Check
the router port forward and
VPN_ENDPOINT, and on the gateway runwg show. - Connected, but servers not reachable: on the gateway,
tcpdump -ni wg0should show the traffic arriving. On the Proxmox host,tcpdump -ni cu000N host 10.101.N.xshould show it reaching the customer's network; if not, the route from step 3 is missing. Also check the server's own firewall (Windows Firewall,ufw) allows the service.