WireGuard VPN for admin access

Once your VPS is in production, you don’t want to expose admin UIs (Grafana, Netdata, internal tools) to the public internet. WireGuard gives you a private tunnel to your VPS — only clients with the right keys can reach those services.

Server setup

apt install -y wireguard

# Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key

# Server config
cat > /etc/wireguard/wg0.conf <<EOF
[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = $(cat /etc/wireguard/server_private.key)
# Forward traffic from VPN clients
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]
# admin-laptop
PublicKey = <client_public_key>
AllowedIPs = 10.10.10.2/32
EOF

# Enable IP forwarding
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p

systemctl enable --now wg-quick@wg0

# Open firewall
ufw allow 51820/udp comment 'WireGuard'

Client setup (macOS, Linux, iOS, Android)

For each client:

  1. Generate keys: wg genkey | tee private.key | wg pubkey > public.key
  2. Add the client’s public key to /etc/wireguard/wg0.conf under a new [Peer] block
  3. Restart: systemctl restart wg-quick@wg0
  4. Give the client the config:
[Interface]
PrivateKey = <client_private_key>
Address = 10.10.10.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = <server_public_key>
Endpoint = <server_public_ip>:51820
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 10.10.10.0/24
PersistentKeepalive = 25

AllowedIPs controls which traffic goes through the VPN. The ranges above route only private network traffic — your regular browsing stays direct.

Restrict admin UIs to VPN

Now lock down the admin ports. Edit Caddyfile or your reverse proxy to only listen on 10.10.10.0/24:

netdata.internal {
  bind 10.10.10.1
  reverse_proxy localhost:19999
}

Or simpler with iptables:

# Block Netdata from public internet
iptables -A INPUT -p tcp --dport 19999 ! -s 10.10.10.0/24 -j DROP

Why WireGuard (not OpenVPN)?

  • Faster: ~3× throughput on the same hardware
  • Simpler: ~4,000 lines of kernel code vs OpenVPN’s ~100,000
  • Modern crypto: Curve25519, ChaCha20, Poly1305
  • Stealthier: No response to unauthenticated packets — invisible to port scans

The one tradeoff: no built-in dynamic IP support. For that, you need wireguard-dynamic or a small script.