Public Wi-Fi, hotel networks, and even your home ISP can see more of your traffic than you'd like. A self-hosted WireGuard VPN on a cheap VPS gives you an encrypted tunnel you control, without handing your data to a commercial VPN provider.
WireGuard is a good fit for this: it is small, fast, and uses modern cryptography (Curve25519 for key exchange, ChaCha20 for encryption). The whole server config is a few lines.
This guide walks through a basic full-tunnel setup on a Debian/Ubuntu VPS. It is a starting point, not a hardened production design — the closing section covers what to add before you rely on it.
1. Prepare the VPS
Start from a clean Debian or Ubuntu Server LTS instance with root access. Before installing anything:
sudo apt update && sudo apt upgrade -y
Then create a non-root user for daily work, and set a firewall that denies everything except SSH:
sudo ufw allow OpenSSH
sudo ufw enable
2. Install WireGuard
sudo apt install wireguard qrencode -y
qrencode is optional but makes mobile client setup much easier — it renders a QR code from a client config.
3. Generate keys
WireGuard authenticates peers with public/private key pairs. Generate one pair for the server and one for each client:
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genkey | tee client_private.key | wg pubkey > client_public.key
Keep the private keys on their respective devices and never commit them to a repository.
4. Configure the server
Create /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = <SERVER_PRIVATE_KEY>
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
Add one [Peer] block per client. AllowedIPs on the server side is the VPN IP you assign to that client.
5. Configure the client
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/32
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = YOUR_VPS_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
AllowedIPs = 0.0.0.0/0 on the client routes all traffic through the tunnel (full tunnel). PersistentKeepalive = 25 keeps NAT mappings alive on mobile connections.
6. Enable forwarding and open the firewall
The VPS must forward traffic between the VPN interface and the internet:
# Enable IP forwarding
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
# Open the WireGuard port
sudo ufw allow 51820/udp
7. Start and test
sudo wg-quick up wg0
sudo wg show
On the client, bring up the tunnel and check that your public IP is now the VPS's address. Test from a device that is not on the same local network as the server.
8. Harden it before you rely on it
- Keep the firewall default-deny; allow only SSH and 51820/udp.
- Use SSH keys, not passwords, and consider fail2ban.
- Rotate keys periodically.
- Restrict the VPS's own attack surface — disable password auth, keep the base image updated.
- Add IPv6 forwarding rules if your VPS has IPv6.
What this does not cover
This is a single-server, full-tunnel setup. It does not cover split tunneling, multi-server routing, dynamic peer management, or high availability. For anything beyond a personal VPN, plan for key distribution and monitoring before you deploy.
This guide is adapted from the full WireGuard walkthrough on hSECURITIES, which goes deeper into firewall rules and client setup.
Top comments (0)