Skip to content
Learni
View all tutorials
Sécurité

How to Set Up a Personal WireGuard VPN in 2026

Lire en français

Introduction

In 2026, a personal VPN is essential for protecting your privacy against mass surveillance, IP leaks, and MITM attacks on public networks. Unlike overloaded commercial VPNs (high latency, potential logs), WireGuard delivers ChaCha20-Poly1305 encryption that's ultra-fast (3x better than OpenVPN) with just 4,000 audited lines of code.

This beginner tutorial walks you through deploying a WireGuard server on an Ubuntu VPS (~$5/month). Picture your traffic routed through a secure tunnel, like a private highway dodging spy traffic jams. By the end, you'll connect any device (PC, mobile) in 15 minutes. Key benefits: zero logs, masked dynamic IPs, bypassed geo-blocks. Ready to take control? (128 words)

Prerequisites

  • An Ubuntu 24.04 LTS VPS (e.g., DigitalOcean droplet 1 vCPU/1GB RAM, ~$5/month)
  • Root access via SSH (public key recommended)
  • WireGuard client installed on your local device (download from wireguard.com/install)
  • Basic SSH knowledge: ssh root@VPS_IP

Update the system and install WireGuard

install-wireguard.sh
#!/bin/bash
apt update -y && apt upgrade -y
apt install wireguard wireguard-tools qrencode -y
systemctl enable wg-quick@wg0

# Check the installation
wg --version

This script updates Ubuntu, installs WireGuard and its tools (qrencode for client QR codes). It enables the systemd service for wg0 on boot. Pitfall: Skipping apt upgrade can break kernel modules with outdated packages; run as root with bash install-wireguard.sh.

Generate cryptographic keys

WireGuard uses Ed25519 key pairs (more secure than RSA). The server has a private key kept secret; its public key is shared with clients. Analogy: like a padlock (public) and its key (private). Store them offline to avoid leaks.

Generate server and client keys

generate-keys.sh
#!/bin/bash

# Server keys
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
chmod 600 /etc/wireguard/private.key

# Client keys (example for one client)
wg genkey | tee client-private.key | wg pubkey > client-public.key

# Display for verification (don't share private!)
echo "Server private: $(cat /etc/wireguard/private.key)"
echo "Server public: $(cat /etc/wireguard/public.key)"
echo "Client public: $(cat client-public.key)"

Generates and secures the keys (chmod 600 prevents non-root reads). Copy client-public.key into the server config. Pitfall: Leaks if public keys are exposed publicly; use qrencode later for mobile clients to avoid copy-paste.

WireGuard server configuration

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
PrivateKey = <INSERT_SERVER_PRIVATE_KEY_HERE>
ListenPort = 51820
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

# Example client
[Peer]
PublicKey = <INSERT_CLIENT_PUBLIC_KEY_HERE>
AllowedIPs = 10.0.0.2/32

Replace placeholders with your keys (e.g., nano /etc/wireguard/wg0.conf). PostUp/PostDown enables NAT to route client traffic via the VPS. Pitfall: eth0 might be ens3 on some VPS—check with ip a; open UDP port 51820.

Start the server and configure the firewall

Now launch the tunnel. UFW (Ubuntu's firewall) allows VPN access without exposing the server. Test connectivity with ping from the client.

Start WireGuard and secure with UFW

start-server.sh
#!/bin/bash
ufw allow 22/tcp
ufw allow 51820/udp
ufw --force enable
ufw status verbose

wg-quick up wg0
wg show

# Persist on reboot
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

Enables UFW (default deny), opens SSH and VPN UDP. wg-quick up applies the config. Pitfall: Forgetting UFW can block SSH—always allow 22/tcp first; wg show checks active peers/handshakes.

WireGuard client configuration (Linux example)

client.conf
[Interface]
Address = 10.0.0.2/24
PrivateKey = <INSERT_CLIENT_PRIVATE_KEY_HERE>
DNS = 1.1.1.1

[Peer]
PublicKey = <INSERT_SERVER_PUBLIC_KEY_HERE>
Endpoint = YOUR_VPS_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Copy to your local machine and import into the WireGuard app (wg-quick up client). AllowedIPs=0.0.0.0/0 routes all traffic via VPN; Keepalive maintains NAT tunnels. Pitfall: DNS leaks without DNS=1.1.1.1—test on ipleak.net.

Test the VPN connection

On client: wg-quick up client.conf then curl ifconfig.me (should show VPS IP). Check for leaks on dnsleaktest.com. For mobile, scan QR: qrencode -t ansiutf8 < client.conf.

Test and monitoring script

test-vpn.sh
#!/bin/bash
# On client
echo "IP before VPN: $(curl -s ifconfig.me)"
wg-quick up client.conf
sleep 5
echo "IP via VPN: $(curl -s ifconfig.me)"
wg show

# On server
wg show | grep handshake
tail -f /var/log/syslog | grep wireguard

Tests routing and handshake (>1min is valid). Monitors logs. Pitfall: No handshake means firewall block or bad key; use journalctl -u wg-quick@wg0 -f for debugging.

Best practices

  • Unique keys per client: Add one [Peer] per device in wg0.conf, restart wg-quick.
  • Fail2ban + monitoring: Install to ban SSH brute-force.
  • Regular updates: apt update && apt upgrade wireguard monthly.
  • Multi-clients: Use IPAM (10.0.0.2, .3...) and auto-gen scripts.
  • Backup configs: tar czf vpn-backup.tar.gz /etc/wireguard/.

Common errors to avoid

  • No NAT: Client traffic doesn't exit—add PostUp iptables.
  • Blocked port: Check ufw status and VPS security group (AWS/EC2).
  • Mismatched keys: Handshake=0—regenerate and compare hex.
  • IPv6 leaks: Add Address=fd00::2/64 and AllowedIPs=::/0.

Next steps