Homelab Portfolio Project · VM 100 · Remote Access
A self-hosted WireGuard VPN server built to solve a real problem - remote access to the homelab that survives a second VPN running on top of it.
| IP Address | 192.168.86.51 |
| Hostname | ubuntu-server (VM 100) |
| OS | Ubuntu Server 24.04 LTS |
| VPN Port | UDP 51820 |
| VPN Subnet | 10.10.10.0/24 |
| Domain | vpn.munyakazi.org |
| Status | Live |
Tailscale worked perfectly at home but failed silently the moment Avast SecureLine activated on public WiFi. No error, no logs pointing at the cause - just a dead tunnel. With no split-tunneling option available to exempt Tailscale's traffic, and security policy ruling out disabling the public-WiFi VPN, Tailscale was no longer viable.
WireGuard's advantage: it runs on a single, predictable UDP port, independent of whatever else is active on the network stack - so it runs underneath another VPN instead of competing with it.
Internet
│
│ UDP 51820 (port forwarded)
▼
Telekom Speedport router
│
▼
Proxmox VE host (bare metal)
└── VM 100 — Ubuntu Server 24.04
├── WireGuard (wg0) — 10.10.10.1/24
├── UFW firewall — routed forwarding enabled, SSH VPN-only
└── cf-ddns.sh (cron every 10 min)
└── updates vpn.munyakazi.org → current public IP
| Component | Value |
|---|---|
| VM ID | 100 |
| OS | Ubuntu Server 24.04 LTS |
| CPU | 2 vCores |
| RAM | 4 GB |
| Disk | 50 GB |
| Network | vmbr0 |
| Static IP | 192.168.86.51 |
sudo apt install wireguard wireguard-tools
# Server keypair
wg genkey | tee server_private.key | wg pubkey > server_public.key
# Client keypair (repeat for each client)
wg genkey | tee client_private.key | wg pubkey > client_public.key
/etc/wireguard/wg0.conf[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# Windows client
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.10.10.2/32
/etc/sysctl.d/99-wireguard.confnet.ipv4.ip_forward = 1
Apply with: sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
# Critical fix — default is DROP which silently blocks routed traffic
sudo sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
# Allow WireGuard
sudo ufw allow 51820/udp
# Allow SSH only from VPN subnet (remove broad internet SSH after this)
sudo ufw allow from 10.10.10.0/24 to any port 22
sudo ufw delete allow 22
sudo ufw enable
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.10.10.2/32
DNS = 10.10.10.1
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = vpn.munyakazi.org:51820
# Split-tunnel — only route homelab traffic through the VPN
# NOT 0.0.0.0/0 (full tunnel breaks local reachability)
AllowedIPs = 10.10.10.0/24, 192.168.86.0/24
PersistentKeepalive = 25
sudo systemctl enable --now wg-quick@wg0
# cf-ddns.sh — checks public IP every 10 min, updates DNS only on change
# Cron entry (crontab -e):
*/10 * * * * /home/jcadmin/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1
The tunnel handshake succeeded but LAN devices were unreachable. UFW's default DEFAULT_FORWARD_POLICY="DROP" silently blocks traffic being routed through the server, even when the tunnel itself is working. Fix: set to ACCEPT in /etc/default/ufw.
Client set to AllowedIPs = 0.0.0.0/0 routes all traffic into the tunnel, which broke local reachability entirely. Fix: scope to 10.10.10.0/24, 192.168.86.0/24 (VPN subnet + home LAN only).
Both bugs found in order by running sudo wg show and checking for active handshake with real bidirectional data transfer.
# Check tunnel status and active peers
sudo wg show
# Confirm IP forwarding is active
sysctl net.ipv4.ip_forward
# Check UFW status and rules
sudo ufw status verbose
# Test from client — ping LAN device through tunnel
ping 192.168.86.1
# Check DDNS log
tail -20 /var/log/cf-ddns.log
10.10.10.0/24) - no internet-facing SSHContains sanitized config templates:
server/wg0.conf.exampleserver/ufw-rules.shserver/sysctl-forwarding.confclient/HomeVPN.conf.exampleddns/cf-ddns.shddns/crontab.txtFull story with screenshots and architecture diagram:
munyakazi.org - Self-Hosted WireGuard VPN
Part of the Homelab Project series.
← Back to Homelab Tracker · VM 101 — Windows Server →