Skip to main content

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):

  1. 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 the customers pool.

  2. 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 wg0 on UDP 51820, and prints the gateway's public key.

  3. Route the VPN range on the Proxmox host to the gateway. In /etc/network/interfaces, in the vmbr0 section:

    post-up ip route add 10.101.0.0/16 via 192.168.1.110
    pre-down ip route del 10.101.0.0/16 via 192.168.1.110

    and apply it right away with ip route add 10.101.0.0/16 via 192.168.1.110.

  4. Forward UDP 51820 on your internet router to the gateway VM, and choose a DNS name (or use your public IP) for VPN_ENDPOINT.

  5. 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
  6. Enable it in the panel's .env and restart the panel:

    VPN_ENABLED=true
    VPN_GATEWAY_VMID=150
    VPN_ENDPOINT=vpn.example.com:51820

    The 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 run wg show.
  • Connected, but servers not reachable: on the gateway, tcpdump -ni wg0 should show the traffic arriving. On the Proxmox host, tcpdump -ni cu000N host 10.101.N.x should 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.