WireGuard Setup
WireGuard is a modern VPN protocol built into the Linux kernel since 5.6. It uses state-of-the-art cryptography (Curve25519, ChaCha20, Poly1305), has a tiny attack surface compared to OpenVPN or IPsec, and is significantly faster in benchmarks. Configuration is done through simple key pairs and interface files — there’s no certificate authority, no complex PKI.
This guide sets up a WireGuard server on Ubuntu/Debian and connects a Linux client to it. The server needs a public IP address. The client can be anywhere.
Install WireGuard
On both server and client:
sudo apt update
sudo apt install -y wireguard
Generate key pairs
WireGuard uses asymmetric key pairs. Each peer has a private key and a public key. Generate them on each machine — never share private keys.
On the server:
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
sudo chmod 600 /etc/wireguard/server_private.key
On the client:
wg genkey | sudo tee /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key
sudo chmod 600 /etc/wireguard/client_private.key
View the keys so you can copy them into configs:
sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key
sudo cat /etc/wireguard/client_private.key
sudo cat /etc/wireguard/client_public.key
Enable IP forwarding on the server
The server needs to forward packets between the VPN interface and the internet. Add this to /etc/sysctl.conf:
sudo nano /etc/sysctl.conf
Add or uncomment this line:
net.ipv4.ip_forward=1
Apply it immediately without rebooting:
sudo sysctl -p
Server configuration
Create /etc/wireguard/wg0.conf on the server. Replace the placeholder values with your actual keys and your server’s public IP address.
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
# Replace eth0 with your actual network interface (check with: ip link show)
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
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
Set correct permissions:
sudo chmod 600 /etc/wireguard/wg0.conf
Client configuration
Create /etc/wireguard/wg0.conf on the client. Replace SERVER_PUBLIC_IP with the actual IP address of your server.
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
AllowedIPs = 0.0.0.0/0 routes all traffic through the VPN. To route only the VPN subnet (split tunnel), use 10.0.0.0/24 instead.
PersistentKeepalive = 25 sends a keepalive packet every 25 seconds to maintain the connection through NAT.
Start and enable WireGuard
On both server and client:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Check status:
sudo wg show
Open the firewall port
On the server, allow UDP traffic on port 51820:
sudo ufw allow 51820/udp
sudo ufw reload
Test the connection
From the client, ping the server’s WireGuard interface:
ping 10.0.0.1
Check your public IP to confirm traffic is going through the VPN:
curl ifconfig.me
It should return the server’s public IP if AllowedIPs = 0.0.0.0/0 is set.
Adding more clients
For each additional client, generate a new key pair on that client, then add a new [Peer] block to the server config with a unique AllowedIPs address (e.g. 10.0.0.3/32). Reload the server config without dropping existing connections:
sudo wg syncconf wg0 <(sudo wg-quick strip wg0)
Useful commands
sudo wg show # show interface status and peer info
sudo wg showconf wg0 # show the running config
sudo systemctl restart wg-quick@wg0
sudo journalctl -u wg-quick@wg0 -f # live logs