WireGuard is a VPN protocol that is faster, simpler, and more auditable than OpenVPN or IPSec. A personal WireGuard VPN on a $5/month VPS costs less than any commercial VPN subscription, and you own the server — no logging policy to trust.
This guide builds a complete WireGuard server from scratch with clients for every platform.
Choose a VPS
Any low-end VPS with a public IP works. Options under $5/month:
- Hetzner Cloud (CX11) — €3.29/month, multiple EU/US datacenters
- Vultr (Cloud Compute) — $3.50/month
- DigitalOcean (Basic) — $4/month
- Oracle Cloud Free Tier — free, but limited bandwidth
Pick a datacenter location that gives you the exit geography you want. An Amsterdam server makes your traffic appear to come from the Netherlands.
Choose Ubuntu 22.04 or Debian 12 as the OS.
Server Setup
SSH into your new VPS and update it:
sudo apt update && sudo apt upgrade -y
sudo apt install wireguard wireguard-tools -y
Generate Server Keys
# Generate the server's private and public key pair
wg genkey | sudo tee /etc/wireguard/server-private.key | wg pubkey | sudo tee /etc/wireguard/server-public.key
# Set restrictive permissions
sudo chmod 600 /etc/wireguard/server-private.key
# View the keys (you'll need these)
cat /etc/wireguard/server-private.key
cat /etc/wireguard/server-public.key
Generate Client Keys
Generate a key pair for each client (do this now for all clients you plan to add):
# Client 1: laptop
wg genkey | tee /tmp/laptop-private.key | wg pubkey > /tmp/laptop-public.key
# Client 2: phone
wg genkey | tee /tmp/phone-private.key | wg pubkey > /tmp/phone-public.key
# Client 3: tablet
wg genkey | tee /tmp/tablet-private.key | wg pubkey > /tmp/tablet-public.key
Find Your Server’s Network Interface
ip route | grep default
# Example: default via 95.216.1.1 dev eth0 proto dhcp src 95.216.1.234 metric 100
# Interface name is eth0 in this example
Your interface may be eth0, ens3, enp1s0 — check and use the correct one below.
Create the Server Configuration
sudo nano /etc/wireguard/wg0.conf
[Interface]
# The WireGuard server's IP on the VPN network
Address = 10.0.0.1/24
# Port WireGuard listens on (can be any UDP port; 51820 is conventional)
ListenPort = 51820
# Your server's private key
PrivateKey = <contents of /etc/wireguard/server-private.key>
# Enable NAT so VPN traffic gets forwarded to the internet
# Replace eth0 with your actual network interface
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
# If using IPv6, also add:
# PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# --- Client 1: Laptop ---
[Peer]
PublicKey = <contents of /tmp/laptop-public.key>
# Assign this client the .2 address on the VPN network
AllowedIPs = 10.0.0.2/32
# --- Client 2: Phone ---
[Peer]
PublicKey = <contents of /tmp/phone-public.key>
AllowedIPs = 10.0.0.3/32
# --- Client 3: Tablet ---
[Peer]
PublicKey = <contents of /tmp/tablet-public.key>
AllowedIPs = 10.0.0.4/32
Enable IP Forwarding
# Enable now
sudo sysctl -w net.ipv4.ip_forward=1
# Persist across reboots
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
Start the WireGuard Interface
# Start WireGuard
sudo wg-quick up wg0
# Enable on boot
sudo systemctl enable wg-quick@wg0
# Check status
sudo wg show
Expected output:
interface: wg0
public key: <server-public-key>
private key: (hidden)
listening port: 51820
Open the Firewall Port
# UFW
sudo ufw allow 51820/udp
sudo ufw reload
# iptables directly
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
Client Configuration
Create a config for each client. Replace variables with your actual keys and server IP.
Linux Client
[Interface]
# Client's private key
PrivateKey = <contents of /tmp/laptop-private.key>
# Client's VPN IP
Address = 10.0.0.2/24
# Use the VPN server as DNS (optional: use Cloudflare or your own)
DNS = 1.1.1.1
[Peer]
# Server's public key
PublicKey = <contents of /etc/wireguard/server-public.key>
# Route all traffic through VPN (0.0.0.0/0 = full tunnel)
AllowedIPs = 0.0.0.0/0, ::/0
# Server's public IP and port
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
# Keep connection alive through NAT
PersistentKeepalive = 25
Save as ~/wireguard-laptop.conf and connect:
# Install WireGuard
sudo apt install wireguard
# Copy config
sudo cp ~/wireguard-laptop.conf /etc/wireguard/wg0.conf
# Connect
sudo wg-quick up wg0
# Verify traffic is going through VPN
curl ifconfig.me # Should show your VPS IP, not your home IP
macOS Client
Install the WireGuard app from the Mac App Store, or via Homebrew:
brew install wireguard-tools
Create the config file at ~/wireguard-laptop.conf with the same content as the Linux config above, then:
sudo wg-quick up ~/wireguard-laptop.conf
Or use the WireGuard GUI app: File > Import tunnel from file.
Windows Client
- Download WireGuard from
https://www.wireguard.com/install/ - Click “Add Tunnel” > “Add empty tunnel” or import a
.conffile - Paste the client configuration
- Click “Activate”
iOS and Android
Generate a QR code from the client config file to scan with the WireGuard mobile app:
# Install qrencode
sudo apt install qrencode
# Generate QR from config
qrencode -t ansiutf8 < /tmp/phone-wireguard.conf
On mobile:
- Install WireGuard from App Store / Google Play
- Tap “+” > “Scan from QR code”
- Scan the QR code
- Toggle the tunnel on
Verify the VPN Is Working
From a connected client:
# Check your public IP — should show the VPS IP
curl https://ifconfig.me
# Check for DNS leaks
# Visit https://dnsleaktest.com — should show your VPN server's DNS
# Verify WireGuard connection
sudo wg show
# Should show handshake timestamp and data transfer for active peers
Check handshake timestamps on the server:
sudo wg show wg0
# latest handshake: 2 minutes, 15 seconds ago
# transfer: 1.23 MiB received, 4.56 MiB sent
Add a New Client Without Downtime
You can add peers without restarting WireGuard:
# Generate new client keys
wg genkey | tee /tmp/newclient-private.key | wg pubkey > /tmp/newclient-public.key
# Add the peer to the running interface
sudo wg set wg0 peer <newclient-public-key> allowed-ips 10.0.0.5/32
# Persist to config file
echo -e "\n[Peer]\nPublicKey = $(cat /tmp/newclient-public.key)\nAllowedIPs = 10.0.0.5/32" | sudo tee -a /etc/wireguard/wg0.conf
Related Articles
- How to Set Up WireGuard on VPS for Personal VPN
- How to Set Up WireGuard VPN on iPhone for Always-On Privacy
- Wireguard Container Setup Docker Network Namespace Isolation
- How To Set Up Mobile Device Management Profile For Personal
- Privacy Setup for Celebrity: Protecting Personal Address.
Built by theluckystrike — More at zovo.one