You SSH into your homelab from a coffee shop, manage Proxmox from your phone on cellular data, or need access to a dashboard while traveling. A WireGuard VPN is the simplest, fastest, and most secure way to reach your internal services without exposing them to the public internet.
WireGuard lives inside the Linux kernel. On Proxmox, you can run it in a lightweight LXC container that consumes ~64 MB of RAM and practically zero CPU when idle. No VM overhead. No heavyweight OpenSSL configuration. One UDP port, three config files, and you’re connected.
This guide covers the full deployment: creating a Debian 12 LXC, installing WireGuard, configuring the server with NAT for homelab routing, generating client configs, setting up persistence across reboots, and securing the stack with firewall rules and a MikroTik port forward.
Why WireGuard in an LXC Instead of a VM
WireGuard runs natively in the Linux kernel. An LXC container shares the host kernel, which means WireGuard kernel modules are available without any extra work. The resource profile is dramatically smaller than a VM:
| Approach | RAM | Disk | Boot time | Complexity |
|---|---|---|---|---|
| WireGuard in LXC | 64-128MB | 2 GB | ~3 sec | Low |
| WireGuard in VM | 512+ MB | 8+ GB | ~20 sec | Medium |
| WireGuard on host | 0 | 0 | Instant | High risk |
Running WireGuard directly on the Proxmox host is possible but frowned upon — it mixes host networking with VPN routing, and a configuration mistake can lock you out of the host entirely. The LXC approach isolates the VPN into its own network namespace, so a misconfigured WireGuard tunnel never touches the Proxmox host.
The only caveat: LXC containers need a privileged container with
the tun device and the wireguard kernel module available. We
configure this during the container creation step.
Step 1: Create the Debian 12 LXC Container
Create a new container in Proxmox or from the CLI. Privileged mode
is required because WireGuard needs access to create the tun
interface and set iptables rules.
|
|
What each flag does:
--unprivileged 0— Creates a privileged container, required for WireGuard to create kernel interfaces--features keyctl=1,nesting=1— Enables kernel key retention (used by WireGuard internally) and container nesting--memory 128 --swap 0— WireGuard needs almost no RAM; 128 MB is generousfirewall=1on the network interface enables Proxmox’s built-in firewall for this container
After entering the container, update the system:
|
|
Verify the WireGuard kernel module is available:
|
|
If modprobe wireguard fails, the module may need to be loaded
on the Proxmox host first. Exit the container (exit) and run:
|
|
Then re-enter and verify again.
Step 2: Server Configuration
Generate the server key pair inside the container:
|
|
Create the server config at /etc/wireguard/wg0.conf:
|
|
Enable IP forwarding on the container:
|
|
Explanation of the routing:
Address = 10.10.10.1/24— This is the VPN subnet. Clients get IPs in this range.- The
PostUpiptables rules forward VPN traffic to eth0 (your homelab network) and apply NAT masquerade so responses route back through the container. IPForward = yes— Required for the kernel to route traffic between wg0 and eth0.
Without the NAT masquerade, clients could reach the container but not other hosts on your homelab (10.0.20.0/24 in this example). The masquerade rewrites the source IP to the container’s eth0 address, making replies reachable.
Step 3: Add a Client
Client configs follow the same key generation pattern. Inside the container:
|
|
Append the client peer to the server config:
|
|
Now substitute the actual public key by writing it directly:
|
|
Repeat for each client. Use a new /32 address per client.
Keep a mapping file:
|
|
Generate the client config file to import on the client device:
|
|
Key details in the client config:
Endpoint— Your public-facing hostname or IP, plus the UDP port 51820AllowedIPs— Which networks route through the VPN. Include your homelab subnet (10.0.20.0/24) and the VPN subnet itself (10.10.10.0/24). Add0.0.0.0/0for full-tunnel (all traffic routes through home)PersistentKeepalive = 25— Sends a keepalive every 25 seconds, essential for NAT traversal if your client is behind a carrier-grade NAT
For quick client deployment, generate a QR code:
|
|
Scan this directly with the WireGuard mobile app — no file transfer needed.
Step 4: Enable and Start the Tunnel
|
|
Verify routing works:
|
|
Step 5: Firewall and Port Forwarding
WireGuard listens on UDP 51820. You need to forward this port from your edge router to the LXC container’s IP address.
MikroTik Port Forward
If your edge router is MikroTik (like the GnTech homelab):
|
|
UFW Inside the Container
If you use UFW inside the LXC:
|
|
Proxmox Firewall (if enabled)
|
|
Step 6: iptables Persistence
WireGuard’s wg-quick runs the PostUp/PostDown rules when the
interface comes up, but if the container reboots and iptables
rules get flushed before wg-quick starts, there’s a brief gap.
Install iptables-persistent to lock in the forwarding rules:
|
|
During installation it will prompt to save current rules. Answer yes, or save manually after:
|
|
This ensures the container can still forward packets even if wg-quick hasn’t started yet on boot.
Step 7: Managing Clients at Scale
For more than 3-4 clients, managing individual key files gets tedious. Two options:
Option A: wg-gen-web (Web UI)
Deploy wg-gen-web in a separate container or via Docker. It provides a clean web UI for adding/removing clients and generates QR codes.
|
|
Security note: Do not expose this to the internet. Access it through your WireGuard VPN or a Tailscale/ZeroTier connection.
Option B: Scripted Client Creation
A simple bash wrapper for client management:
|
|
Usage:
|
|
Step 8: Testing and Verification
From a connected client, run these checks:
|
|
Back on the server, monitor connections:
|
|
If a client can reach the container but not other LAN hosts:
|
|
Performance Tuning
WireGuard is already fast — kernel-mode encryption with ChaCha20 and Poly1305 is hardware-accelerated on modern x86_64 and ARM CPUs. But a few tweaks apply in the LXC context:
MTU
The default WireGuard MTU of 1420 is conservative. If your homelab has jumbo frame support (MTU 9000 on internal links), you can increase the tunnel MTU:
|
|
Calculate MTU as physical MTU minus 80 bytes (60 IP/UDP header
- 20 WireGuard overhead). For 9000 MTU internal networks, 8920 works.
CPU Pinning
If you have many simultaneous VPN clients or high-throughput transfers, pin the container to a specific core:
|
|
Or in the container config (/etc/pve/lxc/200.conf):
|
|
Kernel Module Verification
When WireGuard appears slow, verify you’re using the kernel module, not the userspace Go implementation:
|
|
Backing Up the WireGuard Config
The entire WireGuard state lives in /etc/wireguard/. On a
Proxmox host, back this up from the host side:
|
|
If you ever need to restore, just copy the configs back and restart:
|
|
Summary
WireGuard in a Proxmox LXC is the ideal VPN solution for homelab remote access:
- Create a privileged Debian 12 LXC with 128 MB RAM — smaller than any VM alternative
- Configure WireGuard with key-based authentication, NAT
masquerade, and the VPN subnet
10.10.10.0/24 - Set up clients with minimal config files or QR codes — no client software needed beyond the official WireGuard apps
- Forward UDP port 51820 from your edge router (MikroTik, OPNsense, or consumer router) to the LXC IP
- Enable IP forwarding and iptables persistence for reliable routing across reboots
The result: secure, wire-speed access to your entire homelab from any device, anywhere, with under 30 minutes of setup time. No public-facing dashboards, no VPN appliance VMs, no subscription fees — just a container, a config, and a fast UDP tunnel.