Set Up Your Own WireGuard VPN Server in Under 10 Minutes
WireGuard is a modern VPN protocol that’s faster, simpler, and more secure than OpenVPN or IPSec. Its codebase is roughly 4,000 lines of code (compared to OpenVPN’s 100,000+), making it easier to audit and less prone to vulnerabilities. It’s now built into the Linux kernel and works on every major platform.
This guide walks you through setting up your own WireGuard VPN server and connecting clients.
Why Run Your Own VPN?
- Privacy — Your internet traffic is encrypted between your device and your server
- Security on public Wi-Fi — All traffic is tunneled through your server
- Access home network remotely — Reach devices on your LAN from anywhere
- No subscription fees — A $5/month VPS gives you unlimited VPN usage
- No logging — You control the server, so there are no third-party logs
Prerequisites
- A Linux server (VPS) with a public IP — providers like Vultr, DigitalOcean, Linode, or Hetzner offer servers from $4-5/month
- Ubuntu 22.04+ or Debian 12+ (this guide uses Ubuntu)
- Root or sudo access
Step 1: Install WireGuard
SSH into your server and install WireGuard:
sudo apt update
sudo apt install -y wireguard
WireGuard is included in the Linux kernel since version 5.6. On older kernels, the package installs the kernel module automatically.
Step 2: Generate Server Keys
# Generate private and public keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
# Set secure permissions
chmod 600 /etc/wireguard/server_private.key
View the keys (you’ll need them for configuration):
cat /etc/wireguard/server_private.key
cat /etc/wireguard/server_public.key
Step 3: Configure the Server
Create the WireGuard interface configuration:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# Enable IP forwarding and NAT
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
# Client 1
[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
Replace <SERVER_PRIVATE_KEY> with the output from server_private.key. Replace eth0 with your server’s actual network interface (check with ip route | grep default).
Step 4: Enable IP Forwarding
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Step 5: Start WireGuard
# Start the interface
sudo wg-quick up wg0
# Enable at boot
sudo systemctl enable wg-quick@wg0
Verify it’s running:
sudo wg show
You should see the interface details, listening port, and any connected peers.
Step 6: Open the Firewall
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable
Step 7: Generate Client Keys
On the server (or on the client machine):
wg genkey | tee client1_private.key | wg pubkey > client1_public.key
cat client1_private.key
cat client1_public.key
Step 8: Add Client to Server
Add the client’s public key to the server config. Edit /etc/wireguard/wg0.conf and add the [Peer] section shown in Step 3, using the client’s public key.
Then reload WireGuard:
sudo wg-quick down wg0 && sudo wg-quick up wg0
Or add peers without restarting:
sudo wg set wg0 peer <CLIENT_PUBLIC_KEY> allowed-ips 10.0.0.2/32
Step 9: Configure Clients
Client Configuration File
Create a configuration file for the client:
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
AllowedIPs = 0.0.0.0/0routes all traffic through the VPN (full tunnel)AllowedIPs = 10.0.0.0/24routes only VPN network traffic (split tunnel)PersistentKeepalive = 25keeps the connection alive behind NAT
Linux Client
sudo apt install -y wireguard
sudo nano /etc/wireguard/wg0.conf
# Paste the client configuration above
sudo wg-quick up wg0
macOS Client
- Install from the App Store: WireGuard for macOS
- Click Import Tunnel(s) from File or Add Empty Tunnel
- Paste the client configuration
- Click Activate
Windows Client
- Download from wireguard.com/install
- Click Add Tunnel → Add empty tunnel
- Paste the client configuration
- Click Activate
iOS / Android
- Install the WireGuard app from App Store or Google Play
- You can either:
- Scan a QR code (easiest — generate on server)
- Import a .conf file
- Create from scratch
Generate a QR Code for Mobile
On the server, install qrencode:
sudo apt install -y qrencode
qrencode -t ansiutf8 < /etc/wireguard/client1.conf
This prints a QR code directly in your terminal. Open the WireGuard mobile app, tap +, select Create from QR code, and scan.
Adding More Clients
For each new client:
- Generate a new key pair
- Assign a new IP (10.0.0.3, 10.0.0.4, etc.)
- Add a
[Peer]section to the server’swg0.conf - Create a client
.conffile - Reload:
sudo wg-quick down wg0 && sudo wg-quick up wg0
Quick Setup with wg-easy (Docker)
If you want a web UI for managing WireGuard, use wg-easy:
docker run -d \
--name wg-easy \
--restart unless-stopped \
-e WG_HOST=YOUR_SERVER_IP \
-e PASSWORD=your-admin-password \
-v ~/.wg-easy:/etc/wireguard \
-p 51820:51820/udp \
-p 51821:51821/tcp \
--cap-add NET_ADMIN \
--cap-add SYS_MODULE \
--sysctl net.ipv4.ip_forward=1 \
--sysctl net.ipv4.conf.all.src_valid_mark=1 \
ghcr.io/wg-easy/wg-easy
Access the web UI at http://YOUR_SERVER_IP:51821. You can create clients, download configs, and generate QR codes all from the browser.
Verifying the VPN Works
Once connected, verify your traffic is going through the VPN:
# Check your public IP (should show server IP)
curl ifconfig.me
# Check WireGuard status
sudo wg show
# Ping the server through the tunnel
ping 10.0.0.1
Visit ipleak.net or whatismyipaddress.com in a browser to confirm your IP has changed.
Performance Comparison
| Protocol | Throughput | Latency | Code Size |
|---|---|---|---|
| WireGuard | ~800-900 Mbps | Low | ~4,000 lines |
| OpenVPN | ~400-500 Mbps | Medium | ~100,000 lines |
| IPSec/IKEv2 | ~600-700 Mbps | Medium | ~400,000 lines |
WireGuard’s performance advantage comes from running in the kernel and using modern cryptographic primitives (ChaCha20, Poly1305, Curve25519, BLAKE2s).
Troubleshooting
Can’t connect to VPN
- Verify port 51820/udp is open:
sudo ss -ulnp | grep 51820 - Check firewall:
sudo ufw status - Verify keys match (server has client’s public key, client has server’s public key)
- Check the endpoint IP is correct in client config
Connected but no internet
- Verify IP forwarding:
cat /proc/sys/net/ipv4/ip_forward(should be1) - Check iptables NAT rule:
sudo iptables -t nat -L POSTROUTING - Make sure
PostUp/PostDownrules use the correct interface name
View connection details
# Server side
sudo wg show wg0
# Shows each peer, last handshake, data transferred
Security Considerations
- Protect private keys —
chmod 600on all key files - Use a firewall — Only expose port 51820/udp
- Update regularly —
sudo apt update && sudo apt upgrade - Rotate keys periodically — Generate new key pairs every few months
- Limit peer access — Use specific
AllowedIPsrather than broad ranges - DNS privacy — Use encrypted DNS (1.1.1.1 or 9.9.9.9) in client configs
Conclusion
WireGuard is the easiest VPN to set up and the fastest to use. With just a few commands, you have a fully encrypted tunnel between your devices and your server. Whether you’re securing public Wi-Fi, accessing your home network remotely, or just want privacy from your ISP, a self-hosted WireGuard VPN gives you complete control over your network traffic.