How to Configure WireGuard VPN Server and Client Keys in Ubuntu

Legacy virtual private network protocols like OpenVPN and IPsec/IKEv2 rely on massive, multi-hundred-thousand-line codebases with complex cryptographic negotiation handshakes and high CPU overhead. In modern Linux kernel environments, WireGuard has emerged as the state-of-the-art secure tunneling protocol. Operating directly inside the Linux kernel with fewer than 4,000 lines of code, WireGuard utilizes modern cryptography (Noise protocol framework, Curve25519, ChaCha20-Poly1305, and BLAKE2s) to deliver instantaneous connection handshakes, high throughput, and seamless roaming across network interfaces.

Installing WireGuard and Enabling Kernel IP Forwarding

WireGuard is built natively into standard Ubuntu Linux kernels:

# Install WireGuard management tools
sudo apt update && sudo apt install -y wireguard qrencode

# Enable IPv4 packet forwarding in the Linux kernel
sudo tee /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF

# Apply sysctl changes immediately without rebooting
sudo sysctl --system

Generating Server Cryptographic Keypairs

WireGuard authenticates peers using asymmetric public-key cryptography similar to SSH keys:

  1. Navigate to the secured WireGuard configuration directory:
    cd /etc/wireguard
    umask 077
  2. Generate the server private key and derive its public key:
    wg genkey | tee server_private.key | wg pubkey > server_public.key
  3. Generate client keypairs for remote peers:
    wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Building the Server Interface Configuration (wg0.conf)

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

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <INSERT_SERVER_PRIVATE_KEY>
PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on eth0
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Client 1 Peer Definition
[Peer]
PublicKey = <INSERT_CLIENT1_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32

Note: Replace eth0 with your primary outward network interface name discovered via ip route show default.

Opening Firewall Ports and Starting the WireGuard Service

Allow incoming UDP traffic through UFW on the WireGuard listening port:

sudo ufw allow 51820/udp
sudo systemctl enable --now wg-quick@wg0

Configuring Client Profiles and Generating Mobile QR Codes

Create a client configuration profile (e.g., client1.conf):

[Interface]
PrivateKey = <INSERT_CLIENT1_PRIVATE_KEY>
Address = 10.8.0.2/24
DNS = 1.1.1.1, 8.8.8.8

[Peer]
PublicKey = <INSERT_SERVER_PUBLIC_KEY>
Endpoint = 203.0.113.50:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

For mobile phones, render an instant scannable terminal QR code:

qrencode -t ansiutf8 < client1.conf

Scan the QR code within the official iOS or Android WireGuard application to initialize encrypted, battery-efficient tunneling instantaneously.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.