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
Keep Private Keys Private

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 key
  • SERVER_PUBLIC_KEY — Server's public key (from publickey file)
  • YOUR_SERVER_PUBLIC_IP — Your server's public IP
AllowedIPs = 0.0.0.0/0

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/0 for full tunnel

Connection Drops

Add PersistentKeepalive to client config:

PersistentKeepalive = 25

Next Steps