Privacy Tools Guide

How to Use WireGuard for Self-Hosted VPN in 2026

WireGuard is the fastest, most modern VPN protocol available. Unlike OpenVPN or IPSec, WireGuard uses only 4,000 lines of code, making it easier to audit and maintain. This guide walks you through deploying a self-hosted WireGuard VPN on a Linux VPS—from server setup to client configuration.

Why WireGuard Over OpenVPN?

Feature WireGuard OpenVPN
Code Size ~4,000 lines ~100,000 lines
Performance 5-10 Gbps+ 0.5-2 Gbps
Modern Crypto ChaCha20, Poly1305 AES, SHA
Configuration ~15 lines 100+ lines
Setup Time 5 minutes 30+ minutes
Mobile Support Excellent Good
Audit Surface Minimal Large

In short: WireGuard is faster, leaner, and easier to understand. Perfect for self-hosted deployment.

Prerequisites

Server:

Recommended Providers (2026):

Client:

Step 1: Server Setup on VPS

Install WireGuard

# Ubuntu 22.04 LTS
sudo apt update
sudo apt install -y wireguard wireguard-tools

# Verify installation
wg --version
# Output: wg version 1.0.x

Fedora/CentOS:

sudo dnf install -y wireguard-tools

Debian:

sudo apt update
sudo apt install -y wireguard wireguard-dkms

Generate Server Keys

WireGuard uses public/private key pairs (similar to SSH, but for VPN traffic).

# Create WireGuard config directory
sudo mkdir -p /etc/wireguard
cd /etc/wireguard

# Generate server private and public keys
sudo wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey

# Verify keys (should be base64 strings, ~43 characters)
sudo cat privatekey
sudo cat publickey

# Restrict key file permissions (security best practice)
sudo chmod 600 privatekey publickey

Output Example:

privatekey: WBn...A0=
publickey:  5E4...8k=

Create Server Configuration

Create the WireGuard configuration file /etc/wireguard/wg0.conf:

sudo nano /etc/wireguard/wg0.conf

Paste this configuration:

[Interface]
# VPN server configuration
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = YOUR_SERVER_PRIVATEKEY_HERE
# Post-up/Post-down rules for routing
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Client configurations (we'll add peers below)

Replace YOUR_SERVER_PRIVATEKEY_HERE with the content of sudo cat /etc/wireguard/privatekey

Security Notes:

Enable IP Forwarding

For VPN clients to route traffic through the server, enable kernel IP forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

# Make permanent (survives reboot)
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configure Firewall

Allow WireGuard UDP traffic:

UFW Firewall:

sudo ufw allow 51820/udp
sudo ufw reload

iptables:

sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Cloud Provider Security Groups (AWS, Vultr, etc.):

Start WireGuard Server

# Enable and start WireGuard
sudo systemctl enable wg-quick@wg0.service
sudo systemctl start wg-quick@wg0.service

# Verify it's running
sudo systemctl status wg-quick@wg0.service
sudo wg show

Expected Output:

interface: wg0
  public key: 5E4...8k=
  private key: (hidden)
  listening port: 51820

Step 2: Generate Client Keys and Add Peers

For each device connecting to the VPN, generate a unique key pair.

Generate Client 1 Keys

# On server, generate keys for first client
cd /etc/wireguard
sudo wg genkey | sudo tee client1_privatekey | wg pubkey | sudo tee client1_publickey

# View keys
sudo cat client1_privatekey  # Copy this to client
sudo cat client1_publickey   # Add to server config

Output:

client1_privatekey: eEz...k1=
client1_publickey: rE9...cA=

Add Client Peer to Server Configuration

Edit /etc/wireguard/wg0.conf and add client peer:

sudo nano /etc/wireguard/wg0.conf

Add at end of file:

# Client 1 configuration
[Peer]
PublicKey = rE9...cA=
AllowedIPs = 10.0.0.2/32

Replace rE9...cA= with the output of sudo cat client1_publickey.

Breakdown:

Restart WireGuard to Apply Changes

sudo systemctl restart wg-quick@wg0.service
sudo wg show  # Verify peer was added

Step 3: Configure Client VPN Device

For Linux Client

Create client config file:

# On client machine
mkdir -p ~/.config/wireguard
sudo nano /etc/wireguard/wg-client.conf

Paste this configuration:

[Interface]
Address = 10.0.0.2/24
PrivateKey = eEz...k1=
DNS = 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = 5E4...8k=
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Replace:

Configuration explanation:

Connect to VPN

Linux (using wg-quick):

sudo wg-quick up /etc/wireguard/wg-client.conf
# Output: [#] ip link add wg-client type wireguard
#         [#] wg set wg-client listen-port 12345 private-key ...
#         [#] ip address add 10.0.0.2/24 dev wg-client
#         [#] ip route add 0.0.0.0/0 dev wg-client

Verify connection:

wg show  # Should show established peer
curl https://ipinfo.io/ip  # Should show server's IP

Disconnect from VPN:

sudo wg-quick down /etc/wireguard/wg-client.conf

For macOS Client

  1. Install WireGuard from App Store or brew install wireguard-go

  2. Create config file (same format as Linux): ```bash cat > wg-client.conf « ‘EOF’ [Interface] Address = 10.0.0.2/24 PrivateKey = eEz…k1= DNS = 1.1.1.1, 1.0.0.1

[Peer] PublicKey = 5E4…8k= Endpoint = YOUR_SERVER_IP:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 EOF


3. Import into WireGuard app: Cmd+N → Select file → Activate

---

### For iOS/Android Client

1. Install **WireGuard** app (official)

2. On server, generate QR code:
```bash
# Requires qrencode package
sudo apt install -y qrencode

# Generate QR code for client1
sudo cat /etc/wireguard/wg-client.conf | qrencode -o client1.png
# Or text version:
qrencode -t ansiutf8 < /etc/wireguard/wg-client.conf
  1. In WireGuard app:
    • Tap + → Scan from camera → Point at QR code
    • Connection activates immediately

For Windows Client

  1. Download WireGuard installer: wireguard.com/install

  2. Create config file (wg-client.conf): ```ini [Interface] Address = 10.0.0.2/24 PrivateKey = eEz…k1= DNS = 1.1.1.1, 1.0.0.1

[Peer] PublicKey = 5E4…8k= Endpoint = YOUR_SERVER_IP:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25


3. In WireGuard app: Import tunnel → Select `.conf` file → Activate

## Step 4: Add Multiple Clients (Scaling)

Repeat Steps 2-3 for each device:


```bash
# Server: Generate client 2
sudo wg genkey | sudo tee client2_privatekey | wg pubkey | sudo tee client2_publickey

# Server: Add to wg0.conf
sudo nano /etc/wireguard/wg0.conf
# Add:
[Peer]
PublicKey = client2_publickey
AllowedIPs = 10.0.0.3/32

# Server: Restart WireGuard
sudo systemctl restart wg-quick@wg0.service

# Client 2: Create config
# Address = 10.0.0.3/24 (unique IP per client)
# PrivateKey = client2_privatekey
# Same peer config as before

Server Config with 3 Clients:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = YOUR_SERVER_PRIVATEKEY_HERE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = CLIENT1_PUBLICKEY
AllowedIPs = 10.0.0.2/32

[Peer]
PublicKey = CLIENT2_PUBLICKEY
AllowedIPs = 10.0.0.3/32

[Peer]
PublicKey = CLIENT3_PUBLICKEY
AllowedIPs = 10.0.0.4/32

Step 5: Security Hardening

Firewall: Restrict SSH Access

# Allow SSH only from your home IP
sudo ufw allow from 203.0.113.10 to any port 22

# Allow WireGuard from anywhere
sudo ufw allow 51820/udp

# Deny all other incoming
sudo ufw default deny incoming
sudo ufw enable

Disable Password Authentication

# Generate SSH key on client (if not already done)
ssh-keygen -t ed25519 -C "vpn-admin"

# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@YOUR_SERVER_IP

# Disable password auth
sudo nano /etc/ssh/sshd_config
# Find and change:
# PasswordAuthentication no
# PubkeyAuthentication yes

# Restart SSH
sudo systemctl restart ssh

Enable UFW Logging

sudo ufw logging on
sudo tail -f /var/log/ufw.log

Monitor WireGuard Traffic

# Real-time monitoring
sudo watch -n 1 'wg show'

# See current connections
sudo wg show all dump

# Check server bandwidth usage
nethogs  # If installed: apt install nethogs
# Server: Generate new key
sudo wg genkey | sudo tee /etc/wireguard/privatekey.new | wg pubkey | sudo tee /etc/wireguard/publickey.new

# Server: Update config and restart
# (Update [Interface] PrivateKey with new key)
sudo systemctl restart wg-quick@wg0.service

# Notify all clients to update their peer public key

Troubleshooting

Client Can’t Connect

Check 1: Server is running

sudo systemctl status wg-quick@wg0.service
sudo wg show

Check 2: Port 51820 is open

# From client:
nc -u -zv YOUR_SERVER_IP 51820
# Expected: succeeded (or connection timeout = firewalled)

Check 3: Client config is correct

# Verify on client:
- PrivateKey matches client1_privatekey
- Peer PublicKey matches server's public key
- Endpoint is correct IP:port
- AllowedIPs format correct (0.0.0.0/0 for all traffic)

Check 4: Check server logs

sudo journalctl -u wg-quick@wg0.service -n 20

Slow Speed

Possible causes:

  1. MTU issue: Test with ping -M do -s 1472 YOUR_SERVER_IP
  2. Server CPU bottleneck: Check top, htop
  3. Network path issue: Run mtr or traceroute to server
  4. UDP packet loss: Use iperf3 for bandwidth test

Fix MTU issue:

# Adjust MTU in client config
[Interface]
MTU = 1280

# Restart connection
sudo wg-quick down wg-client.conf
sudo wg-quick up wg-client.conf

DNS Leaks

Your DNS queries might leak outside the VPN. Test at dnsleaktest.com:

# Ensure DNS in client config points to VPN or privacy-friendly servers
[Interface]
DNS = 1.1.1.1, 1.0.0.1  # Cloudflare
# Or: 9.9.9.9, 149.112.112.112  # Quad9
# Or: Run local DNS resolver on VPN server

Advanced: Self-hosted DNS on VPS

sudo apt install -y unbound

# Edit /etc/unbound/unbound.conf
# Set as recursive resolver

# Update client config:
[Interface]
DNS = 10.0.0.1  # VPN server's internal IP

Connection Drops on Mobile

# Add PersistentKeepalive in client config:
[Peer]
PersistentKeepalive = 25  # Keep alive every 25 seconds

# This prevents NAT timeout on mobile networks

Performance Benchmarks (2026)

Tested with 1Gbps VPS connection:

Metric WireGuard OpenVPN
Throughput 900+ Mbps 200-400 Mbps
Latency +2-5ms +10-20ms
CPU Usage ~5% ~25%
Memory ~10 MB ~100 MB

WireGuard is 2-3x faster with lower resource usage.

Privacy & Security Considerations

What WireGuard Logs:

What WireGuard Doesn’t Log:

Privacy Best Practices:

  1. Use privacy-friendly VPS provider (check privacy policy)
  2. Disable access logs on server: PostUp rules don’t log
  3. Use privacy DNS (Cloudflare, Quad9, Mullvad)
  4. Rotate keys every 6-12 months
  5. Restrict SSH access to specific IPs

Automated Setup Script

For faster deployment, use this script:

#!/bin/bash
# WireGuard Server Setup (Ubuntu 22.04)

set -e

echo "Installing WireGuard..."
sudo apt update && sudo apt install -y wireguard wireguard-tools

echo "Generating server keys..."
cd /etc/wireguard
sudo wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey
sudo chmod 600 privatekey publickey

SERVER_PRIVKEY=$(sudo cat privatekey)
SERVER_PUBKEY=$(sudo cat publickey)

echo "Server Public Key: $SERVER_PUBKEY"
echo "Enter VPS public IP address:"
read SERVER_IP

# Create wg0.conf
sudo tee /etc/wireguard/wg0.conf > /dev/null <<EOF
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = $SERVER_PRIVKEY
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
EOF

echo "Enabling IP forwarding..."
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

echo "Starting WireGuard..."
sudo systemctl enable wg-quick@wg0.service
sudo systemctl start wg-quick@wg0.service

echo "Done! Server is running."
echo "Server IP: $SERVER_IP"
echo "Server Public Key: $SERVER_PUBKEY"
echo "Next: Generate client keys and add peers."

Save as wg-setup.sh, then run:

chmod +x wg-setup.sh
sudo ./wg-setup.sh

Advanced: Site-to-Site VPN (Office Network)

Connect two office networks via WireGuard:

# Office A Server
[Interface]
Address = 10.0.0.1/24
PrivateKey = OFFICE_A_PRIVKEY

[Peer]
PublicKey = OFFICE_B_PUBKEY
Endpoint = OFFICE_B_PUBLIC_IP:51820
AllowedIPs = 10.0.1.0/24  # Office B's subnet
# Office B Server
[Interface]
Address = 10.0.1.1/24
PrivateKey = OFFICE_B_PRIVKEY

[Peer]
PublicKey = OFFICE_A_PUBKEY
Endpoint = OFFICE_A_PUBLIC_IP:51820
AllowedIPs = 10.0.0.0/24  # Office A's subnet

Now all devices in Office A can reach Office B’s internal IPs (10.0.1.x).

Built by theluckystrike — More at zovo.one