[ Skip to main content ]
1 3 3 7 4 2 0 6 6 6 1 3 3 7 4 2 0 6 9 6 6 6 1 3 3 7 4 2 0 6 6 6 4 2 0 1 3 3 7 6 9 6 6 6 4 2 0 1 3 3 7 6 9 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6 4 2 0 6 9 6 6 6 1 3 3 7 4 2 0 6 9 6 6 6 1 3 3 7 4 2 0 6 9 1 3 3 7 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6 6 9 4 2 0 1 3 3 7 6 6 6 6 9 4 2 0 1 3 3 7 6 6 6 4 2 0 1 3 3 7 6 6 6 6 9 4 2 0 1 3 3 7 6 6 6 6 9 4 2 0 6 9 1 3 3 7 4 2 0 6 6 6 6 9 1 3 3 7 4 2 0 6 6 6 6 9 1 3 3 7 6 6 6 6 9 4 2 0 1 3 3 7 6 6 6 6 9 4 2 0 1 3 3 7 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6 4 2 0 6 9 1 3 3 7 6 6 6
TUTORIALS / NETWORKING

SELF-HOSTED VPN WITH WIREGUARD

DIFFICULTY: INTERMEDIATE UPDATED: DECEMBER 2025

INTRODUCTION

Commercial VPNs log your data despite their "No Logs" claims. The only way to be sure is to host your own. WireGuard is a modern, high-performance VPN protocol that is much faster and easier to set up than OpenVPN.

PREREQUISITES

  • A VPS (Virtual Private Server) - DigitalOcean, Linode, or Vultr ($5/mo).
  • Ubuntu 22.04 LTS.
  • SSH Access.

INSTRUCTIONS

1. Install WireGuard

SSH into your VPS and install the package.

sudo apt update && sudo apt install wireguard

2. Generate Keys

Generate private and public keys for the server and client.

wg genkey | tee privatekey | wg pubkey > publickey

3. Configure Server

Edit /etc/wireguard/wg0.conf:

[Interface]
Address = 10.0.0.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = [SERVER_PRIVATE_KEY]

[Peer]
PublicKey = [CLIENT_PUBLIC_KEY]
AllowedIPs = 10.0.0.2/32

4. Enable IP Forwarding

Uncomment net.ipv4.ip_forward=1 in /etc/sysctl.conf and run sysctl -p.

CONCLUSION

Start the interface with wg-quick up wg0. You now have a private, encrypted tunnel. Use the client config on your phone or PC to connect.

FAQ / TROUBLESHOOTING

⚠️ Common issues and fixes

wg-quick up wg0 fails with "Permission denied"

Your config file is world-readable. WireGuard refuses to start if private keys are accessible. Fix it with:

sudo chmod 600 /etc/wireguard/wg0.conf
❌ Handshake completes, but no internet access

IP forwarding is not active or the firewall is blocking traffic. Verify:

sysctl net.ipv4.ip_forward # must be 1
sudo iptables -t nat -L # must show MASQUERADE rule

Add NAT if missing (replace eth0 with your interface):

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
❌ DNS leaks reveal my real ISP

Add a DNS entry to your client config and disable any plaintext DNS in /etc/resolv.conf. On the server side, set DNS = 1.1.1.1, 9.9.9.9 under [Interface] and restart the tunnel.

❌ Connection drops after a few minutes

Most often a keepalive problem with NAT/firewalls. Add to the client peer entry on the server:

PersistentKeepalive = 25
❌ How do I add a second client?

Generate a new keypair, add a [Peer] block on the server with a unique IP (e.g. 10.0.0.3/32), and import the matching client config. Never reuse IPs between peers.

❓ Still stuck?

→ Check wg show for handshake/transfer stats and journalctl -u wg-quick@wg0 for service logs.