WireGuard is the modern VPN protocol that replaced OpenVPN and IPsec in most new deployments. It's faster (kernel-resident), simpler (less than 4,000 lines of code), and cryptographically more conservative (modern primitives, no negotiated cipher suites). This guide takes you from a fresh Ubuntu VPS to a working WireGuard server with multiple clients in about 30 minutes.
What you need
- A Linux VPS (we'll use Ubuntu 24.04 LTS — instructions are nearly identical for Debian 12)
- Root SSH access
- A public IPv4 address (every FranceVPS plan includes one)
- A few minutes
Step 1: Install WireGuard
WireGuard has been in the mainline Linux kernel since 5.6, so on any modern distro the install is trivial:
sudo apt update
sudo apt install -y wireguard wireguard-tools
Verify the kernel module is available:
sudo modprobe wireguard
lsmod | grep wireguard
Step 2: Generate server keys
WireGuard uses public-key cryptography. Each peer (server and client) has a key pair. Generate the server's pair:
cd /etc/wireguard
sudo umask 077
sudo wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
The umask command ensures private key files aren't world-readable. Always preserve this — leaked private keys mean your VPN is compromised.
Step 3: Create the server config
Create /etc/wireguard/wg0.conf with the following:
[Interface]
Address = 10.66.66.1/24
ListenPort = 51820
PrivateKey = <paste contents of server_private.key>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
The PostUp/PostDown rules enable IP forwarding and NAT — necessary if you want clients to reach the public internet through the VPN.
Replace eth0 with your actual primary interface (ip route | grep default tells you).
Step 4: Enable IP forwarding
sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
sudo sysctl -p
Step 5: Start the server
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
Verify it's running:
sudo wg show
You should see the wg0 interface with your public key and listening port. No peers yet.
Step 6: Configure your VPS firewall
Open UDP port 51820:
sudo ufw allow 51820/udp
sudo ufw allow ssh
sudo ufw enable
Step 7: Generate a client config
For each device that will connect, generate a key pair on the server (you'll send the private key to the client securely, or generate it on the client device — both are valid):
wg genkey | tee client1_private.key | wg pubkey > client1_public.key
Add the client to the server config (/etc/wireguard/wg0.conf):
[Peer]
PublicKey = <client1 public key>
AllowedIPs = 10.66.66.2/32
Reload the interface:
sudo wg syncconf wg0 <(wg-quick strip wg0)
Then create the client's wg0.conf file (give this to the client device):
[Interface]
Address = 10.66.66.2/24
PrivateKey = <client1 private key>
DNS = 1.1.1.1, 9.9.9.9
[Peer]
PublicKey = <server public key>
Endpoint = <your VPS public IP>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Setting AllowedIPs = 0.0.0.0/0 in the client config means all traffic is routed through the VPN. If you only want certain subnets routed (split tunneling), specify those instead (e.g., 10.66.66.0/24 for VPN-internal only).
Step 8: Connect from the client
On Linux: sudo wg-quick up <config-file>
On macOS/Windows: install the WireGuard app, import the config file.
On iOS/Android: install the WireGuard app, scan a QR code generated from the config (use qrencode -t ansiutf8 < client1.conf on the server).
Hardening checklist
- Disable SSH password auth. If you're running a VPN, you definitely want SSH key-only on the underlying server. Edit
/etc/ssh/sshd_config:PasswordAuthentication no - Run unattended-upgrades.
sudo apt install unattended-upgrades+ enable security-only auto-updates. - Limit AllowedIPs strictly. Each peer's AllowedIPs should be the smallest possible set. Don't use 0.0.0.0/0 server-side or peers can spoof source addresses.
- Rotate keys quarterly. Set a calendar reminder. Key rotation is fast (regenerate, update peer entries, redistribute configs).
- Monitor for connection anomalies.
wg showdisplays last handshake time. Unexpected handshakes from new IPs are worth investigating.
Common pitfalls
Mismatched AllowedIPs. The most common WireGuard misconfiguration. Server's peer AllowedIPs and client's interface Address must match. If client is at 10.66.66.2/24, server peer entry must be 10.66.66.2/32 (single IP) — not /24, which would route the entire subnet to that one client.
NAT not working. Check iptables -t nat -L POSTROUTING -n -v shows the MASQUERADE rule. If it's missing, the PostUp didn't run — restart wg0.
DNS leaks. Set DNS in client config explicitly. Otherwise the client will use its local DNS resolver, which might bypass the tunnel and leak query info.
MTU issues. WireGuard's overhead is 60 bytes for IPv4. If you see large packets timing out, set MTU = 1420 in the client interface section.
Going further
Once the basic setup works, consider:
- Web UI for client management: wg-easy or wireguard-ui give you a dashboard to add/remove clients without SSH'ing.
- Multiple servers: WireGuard supports multi-server failover via DNS rotation or a smart client.
- Mesh topology: instead of hub-and-spoke, every peer can have direct tunnels to every other peer. Tools like Tailscale and Headscale automate this.
For most personal and small-team use cases, the single-server hub-and-spoke setup we just built is more than sufficient. It handles a few dozen clients with negligible CPU on even our €2.48 Starter VPS — WireGuard is genuinely that lightweight.