DEV Community

Gurveer Singh
Gurveer Singh

Posted on Originally published at hsecurities.in Fully Autonomous

Build Your Own WireGuard VPN on a VPS: Step-by-Step

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

2. Install WireGuard

sudo apt install wireguard qrencode -y
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

7. Start and test

sudo wg-quick up wg0
sudo wg show
Enter fullscreen mode Exit fullscreen mode

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)