Proxmox WireGuard VPN: Secure Remote Access Setup

Set up WireGuard VPN on Proxmox VE for encrypted remote access to your homelab or server. Step-by-step guide with firewall rules and client config.

Proxmox Pulse Proxmox Pulse
9 min read
wireguard vpn remote access proxmox networking security
Glowing encrypted VPN tunnel connecting a home server rack to a remote laptop securely.

Exposing your Proxmox web UI directly to the internet is a bad idea — even with strong passwords and 2FA. A better approach is to put everything behind a VPN and only allow access to your homelab through an encrypted tunnel. WireGuard is the ideal tool for this: it's fast, lean, and dead simple to configure compared to OpenVPN or IPSec.

In this guide you'll set up WireGuard to run either directly on the Proxmox host or inside a dedicated LXC container, configure firewall rules to protect the tunnel, and connect from any device — Windows, macOS, Linux, or mobile.

Why WireGuard Over OpenVPN

WireGuard is a modern VPN protocol built into the Linux kernel since 5.6. It has roughly 4,000 lines of code versus OpenVPN's 100,000+, making audits and maintenance far more tractable.

For Proxmox homelabs, the practical benefits are:

  • Performance: WireGuard saturates gigabit links on a Raspberry Pi 4. OpenVPN struggles on anything without AES-NI.
  • Latency: Handshakes complete in a single round trip. Reconnects after sleep/wake are nearly instant.
  • Simplicity: One config file per peer. No certificate authority, no TLS PKI, no complex daemon config.

Deployment Options: Host vs LXC

You have two sensible approaches:

Option A — Run WireGuard on the Proxmox host itself. This is the simplest path. The WireGuard interface gets created directly in the host network namespace, and once connected, VPN clients can reach any VM or LXC on any bridge. The downside is you're adding an internet-facing service to your hypervisor.

Option B — Dedicated LXC container acting as a VPN gateway. Cleaner from a security standpoint. Traffic flows: VPN client → WireGuard LXC → Proxmox internal network. The LXC needs net.ipv4.ip_forward=1 and a masquerade rule. Slightly more moving parts, but the hypervisor itself isn't exposed.

This guide covers both. Start with Option A if you just want to get running, then migrate to Option B if your security posture demands it.

Option A: WireGuard on the Proxmox Host

Install WireGuard

Proxmox VE 7+ ships on Debian Bullseye or Bookworm. WireGuard is in the kernel already — you just need the userspace tools:

apt update && apt install -y wireguard wireguard-tools

Verify the kernel module loads:

modprobe wireguard && lsmod | grep wireguard

Generate Server Keys

cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
cat server_private.key server_public.key

Keep server_private.key secret. You'll reference it in the config.

Create the WireGuard Interface Config

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <paste server_private.key here>

Enable IP forwarding so VPN clients reach your VMs

PostUp = sysctl -w net.ipv4.ip_forward=1 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT PostUp = iptables -t nat -A POSTROUTING -o vmbr0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT PostDown = iptables -t nat -D POSTROUTING -o vmbr0 -j MASQUERADE

Client peer — add one [Peer] block per device

[Peer] PublicKey = <client_public.key> AllowedIPs = 10.10.0.2/32

Replace vmbr0 with your actual Proxmox bridge name if different. The 10.10.0.0/24 subnet is the WireGuard tunnel network — keep it separate from your LAN (typically 192.168.x.x).

Enable and Start

systemctl enable --now wg-quick@wg0
wg show

You should see the interface listed with your configured listen port and the peer's allowed IPs.

Persist IP Forwarding

The PostUp sysctl works but doesn't survive reboots on its own. Add to /etc/sysctl.conf:

net.ipv4.ip_forward = 1

Apply immediately:

sysctl -p

Option B: WireGuard in a Dedicated LXC Container

This approach isolates the VPN daemon from the hypervisor.

Create the LXC

In the Proxmox web UI, create a new LXC container:

  • Template: Debian 12 or Ubuntu 22.04
  • CPU: 1 core
  • RAM: 128 MB (WireGuard is lean)
  • Disk: 4 GB is plenty
  • Network: One interface on vmbr0, static IP (e.g., 192.168.1.5/24)

The container must be unprivileged with a specific tweak — WireGuard needs the tun device. After creating the container, edit its config on the Proxmox host:

nano /etc/pve/lxc/<CTID>.conf

Add these lines:

lxc.cgroup2.devices.allow: c 10:200 rwm lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Start the container, then install WireGuard inside it:

pct exec <CTID> -- bash -c "apt update && apt install -y wireguard"

Configure the LXC Gateway

Inside the container, create /etc/wireguard/wg0.conf exactly as shown in Option A, but adjust the PostUp/PostDown masquerade interface to match the container's LAN interface (usually eth0):

PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Enable the service inside the container:

pct exec <CTID> -- systemctl enable --now wg-quick@wg0

Port Forward on Your Router

Regardless of which option you chose, you need to forward UDP port 51820 from your router to either:

  • The Proxmox host IP (Option A)
  • The WireGuard LXC IP (Option B)

On most home routers this is under NAT / Port Forwarding. Use your external IP or a dynamic DNS hostname as the WireGuard endpoint in client configs.

Generating Client Configs

For each device (laptop, phone, etc.), generate a key pair:

wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Add a [Peer] block to the server's wg0.conf with the client's public key:

[Peer]
PublicKey = <client1_public.key>
AllowedIPs = 10.10.0.2/32

Reload WireGuard without dropping existing connections:

wg syncconf wg0 <(wg-quick strip wg0)

The client config file (client1.conf) looks like:

[Interface]
Address = 10.10.0.2/24
PrivateKey = <client1_private.key>
DNS = 192.168.1.1

[Peer] PublicKey = <server_public.key> Endpoint = your-ddns-hostname.duckdns.org:51820 AllowedIPs = 192.168.1.0/24, 10.10.0.0/24 PersistentKeepalive = 25

The AllowedIPs field controls split tunneling. The config above routes only your homelab subnets through the VPN — your general internet traffic stays on the client's local connection. For full tunnel routing, use AllowedIPs = 0.0.0.0/0 instead.

PersistentKeepalive = 25 keeps the NAT mapping alive on home routers that aggressively expire UDP sessions.

Import on Mobile

The WireGuard app (iOS/Android) can scan a QR code. Generate one from the client config:

apt install -y qrencode
qrencode -t ansiutf8 < client1.conf

Scan the terminal QR code with the app to import the config instantly.

Proxmox Firewall Rules

If you're using the Proxmox built-in firewall, you need to explicitly allow WireGuard traffic on the host. In the Proxmox web UI:

  1. Go to Datacenter → Firewall → Add
  2. Direction: in, Protocol: udp, Destination port: 51820, Action: ACCEPT
  3. Enable the datacenter firewall if it isn't already

Alternatively, via the CLI on the Proxmox host:

# /etc/pve/firewall/cluster.fw
[RULES]
IN ACCEPT -p udp --dport 51820 # WireGuard VPN

If the host firewall is disabled and you rely on your router/edge firewall, skip this step — but make sure only UDP 51820 is forwarded inbound, not the Proxmox web UI port (8006).

Access the Proxmox Web UI Over VPN

Once the VPN tunnel is up, you can reach the Proxmox UI at https://192.168.1.x:8006 (your host's LAN IP) from any connected client. No need to expose port 8006 to the internet at all.

This is the main security win. Your Proxmox UI, IPMI, and every VM/LXC management interface stay completely off the public internet — they're only reachable after authenticating through WireGuard.

Troubleshooting Common Issues

Handshake Never Completes

Run wg show on the server and check the latest handshake timestamp for your peer. If it never updates:

  • Verify the UDP port is actually reachable: nc -zvu <server-ip> 51820 from the client side
  • Check that your router is forwarding UDP 51820 (not TCP)
  • Confirm the server's public key in the client config matches cat /etc/wireguard/server_public.key

Connected But Can't Reach VMs

If the tunnel handshake succeeds but you can't ping anything on your LAN:

# On the Proxmox host or WireGuard LXC:
iptables -L FORWARD -n -v
iptables -t nat -L POSTROUTING -n -v

Look for the MASQUERADE rule. If it's missing, the PostUp commands didn't run — check the WireGuard logs with journalctl -u wg-quick@wg0.

Also verify forwarding is active:

cat /proc/sys/net/ipv4/ip_forward
# Should return 1

DNS Leaks

If you set a DNS value in the client config and it isn't being used, check that your WireGuard client app applies DNS settings. On Linux clients, wg-quick uses resolvconf — install it if missing:

apt install -y openresolv

Managing Multiple Peers

For a homelab with several devices, a small shell script to generate peer configs keeps things tidy:

#!/bin/bash
NAME=$1
IP=$2  # e.g. 10.10.0.3

cd /etc/wireguard/peers wg genkey | tee ${NAME}_private.key | wg pubkey > ${NAME}_public.key

cat > ${NAME}.conf <<EOF [Interface] Address = ${IP}/24 PrivateKey = $(cat ${NAME}_private.key) DNS = 192.168.1.1

[Peer] PublicKey = $(cat /etc/wireguard/server_public.key) Endpoint = your-server.duckdns.org:51820 AllowedIPs = 192.168.1.0/24, 10.10.0.0/24 PersistentKeepalive = 25 EOF

Print the [Peer] block to add to server wg0.conf

echo "Add to server wg0.conf:" echo "[Peer]" echo "# ${NAME}" echo "PublicKey = $(cat ${NAME}_public.key)" echo "AllowedIPs = ${IP}/32"

Run it as bash add-peer.sh laptop 10.10.0.3 and copy the output block into your server config.

Conclusion

WireGuard gives you a fast, auditable VPN tunnel that makes remote Proxmox access significantly safer without adding much complexity. The core trade-off is simple: running WireGuard on the host is easier to set up, while the dedicated LXC approach keeps your hypervisor's attack surface smaller.

Either way, once the tunnel is up you can stop worrying about firewall rules for the Proxmox UI, Cockpit, or any other management service — they're all unreachable from the public internet. Connect through WireGuard first, then access whatever you need over your LAN addresses. That single architectural decision eliminates an entire class of exposure that no amount of fail2ban tuning can fully compensate for.

Share
Proxmox Pulse

Written by

Proxmox Pulse

Sysadmin-driven guides for getting the most out of Proxmox VE in production and homelab environments.

Related Articles

View all →