WireGuard on a VPS: a private tunnel to your server
WireGuard on a VPS does two useful things. It gives you a private tunnel to your server, so admin panels and dashboards don't need to be on the public internet at all. And if you want, it works as your own VPN when you're on hotel or café Wi-Fi.
The setup is two small config files. This is for Debian or Ubuntu, and assumes you've done the basic hardening already.
Install and make keys
sudo -i apt install wireguard cd /etc/wireguard umask 077 wg genkey | tee server.key | wg pubkey > server.pub cat server.key server.pub
On your laptop, install WireGuard (there are apps for every OS) and generate a key pair there too. The app does it for you when you add an empty tunnel. You only ever copy public keys between machines.
Find your network interface
ip route | grep default
The word after dev is your public interface. It's often eth0, but some images use names like ens3. Use whatever yours says in the config below.
Server config
/etc/wireguard/wg0.conf:
[Interface] Address = 10.8.0.1/24 ListenPort = 51820 PrivateKey = CONTENTS_OF_server.key PostUp = iptables -I FORWARD -i wg0 -j ACCEPT; iptables -I FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # laptop PublicKey = LAPTOP_PUBLIC_KEY AllowedIPs = 10.8.0.2/32
Let the kernel forward traffic, and open the port:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf sysctl --system ufw allow 51820/udp systemctl enable --now wg-quick@wg0 wg show
Laptop config
[Interface] PrivateKey = LAPTOP_PRIVATE_KEY Address = 10.8.0.2/32 DNS = 1.1.1.1 [Peer] PublicKey = CONTENTS_OF_server.pub Endpoint = YOUR_SERVER_IP:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25
Turn it on and check your IP on any "what's my IP" site. It should show the server's address.
Full VPN or just the server?
AllowedIPs = 0.0.0.0/0 sends all your traffic through the server. If you only want to reach the server itself, change it to:
AllowedIPs = 10.8.0.0/24
Now only traffic for the tunnel goes through WireGuard, and normal browsing stays on your own connection. This is the mode I use day to day.
The real win: private admin panels
Once the tunnel is up, you can bind things to the WireGuard address instead of the public one. In Docker Compose:
ports: - "10.8.0.1:3001:3001"
That port only exists inside the tunnel. No login page facing the internet, no bots hammering it. I do this for Uptime Kuma, Portainer and every database UI.
One catch: WireGuard has to be running before Docker starts, or Docker can't bind to 10.8.0.1. Enabling wg-quick@wg0 as above handles that on boot. If a container still fails to start after a reboot, restart it once by hand.
More devices
Each phone or laptop gets its own key pair, its own [Peer] block on the server, and the next address: 10.8.0.3, 10.8.0.4 and so on. Restart the tunnel after editing:
sudo systemctl restart wg-quick@wg0