WireGuard is a modern VPN protocol that's faster, simpler, and more secure than OpenVPN. It uses state-of-the-art cryptography and has a minimal codebase. This guide sets up a WireGuard server on Ubuntu for secure remote access.
Why WireGuard?
- Faster — Smaller codebase, simpler handshake, lower latency
- Simpler — Easy configuration, no complex certificate management
- More secure — Modern cryptography (ChaCha20, Poly1305, Curve25519)
- Better battery — Mobile clients use less power
- Kernel-level — Built into Linux kernel for performance
Prerequisites
- Ubuntu 20.04+ server with public IP
- Root or sudo access
- UDP port 51820 open in firewall
Step 1: Install WireGuard
WireGuard is included in modern Linux kernels. Install the tools:
sudo apt update
sudo apt install wireguard
Step 2: Generate Keys
Create a directory for configuration and generate key pairs:
mkdir -p ~/wireguard && cd ~/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
Set restrictive permissions:
chmod 600 privatekey
The private key never leaves the server. Only share the public key with clients.
Step 3: Create Server Configuration
Create /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = YOUR_SERVER_PRIVATE_KEY
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t NAT -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
Replace YOUR_SERVER_PRIVATE_KEY with the contents of privatekey.
The AllowedIPs setting for each client assigns it a unique IP in the VPN subnet.
Step 4: Enable IP Forwarding
Allow the server to route traffic between VPN clients and the internet:
sudo sysctl -w net.ipv4.ip_forward=1
Make it permanent:
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Step 5: Open Firewall Port
Allow WireGuard traffic through the firewall:
sudo ufw allow 51820/udp
sudo ufw reload
Step 6: Start WireGuard
Bring up the interface:
sudo wg-quick up wg0
Enable at boot:
sudo systemctl enable wg-quick@wg0
Verify it's running:
sudo wg show
Step 7: Create Client Configuration
On the server, generate keys for the client:
cd ~/wireguard
wg genkey | tee client_privatekey | wg pubkey > client_publickey
Create a client config file (e.g., client.conf):
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Replace:
CLIENT_PRIVATE_KEY— Client's private keySERVER_PUBLIC_KEY— Server's public key (frompublickeyfile)YOUR_SERVER_PUBLIC_IP— Your server's public IP
This routes all client traffic through the VPN. Use a more specific range (e.g., 10.0.0.0/24) to only route traffic to the VPN subnet.
Step 8: Add Client to Server
Add the client's public key to the server configuration:
sudo wg set wg0 peer CLIENT_PUBLIC_KEY allowed-ips 10.0.0.2
Or add a new [Peer] section to /etc/wireguard/wg0.conf:
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
Restart WireGuard:
sudo wg-quick down wg0
sudo wg-quick up wg0
Step 9: Connect from Client
Linux
sudo apt install wireguard
sudo wg-quick up ./client.conf
macOS
Install WireGuard from the App Store or use Homebrew:
brew install wireguard-tools
Windows
Download from wireguard.com/install and import the configuration file.
iOS/Android
Install WireGuard from App Store or Play Store. Import the configuration via QR code:
qrencode -t ansiutf8 client.conf
Step 10: Verify Connection
From the client, check your public IP:
curl ifconfig.me
It should show your server's IP, not your original one.
Ping the server's VPN IP:
ping 10.0.0.1
Managing Multiple Clients
Each client needs:
- Unique private/public key pair
- Unique IP address (10.0.0.2, 10.0.0.3, etc.)
- Entry in server's
[Peer]sections
To add another client:
# Generate new keys
wg genkey | tee client2_privatekey | wg pubkey > client2_publickey
# Add to server
sudo wg set wg0 peer $(cat client2_publickey) allowed-ips 10.0.0.3
Troubleshooting
Client Can't Connect
- Verify firewall allows UDP 51820
- Check that server's public key matches in client config
- Ensure ListenPort matches in both configs
No Internet Access
- Verify IP forwarding is enabled
- Check iptables MASQUERADE rule
- Try
AllowedIPs = 0.0.0.0/0for full tunnel
Connection Drops
Add PersistentKeepalive to client config:
PersistentKeepalive = 25
Next Steps
- Set up OpenVPN for clients that need it
- Configure reverse proxy for web services
- Add SSL certificates for your services