Introduction
To set up WireGuard VPN on Ubuntu 24.04, install the wireguard package, generate a public/private key pair on both the server and client, configure the wg0 interface on each side, open UDP port 51820 in your firewall, and bring the tunnel up with wg-quick up wg0. The entire process takes about 30 minutes and gives you an encrypted private tunnel into your Raff VM — no third-party VPN service required.
WireGuard is a modern VPN protocol built directly into the Linux kernel since version 5.6. Unlike OpenVPN (which ships over 100,000 lines of code), WireGuard's entire implementation spans roughly 4,000 lines — making it dramatically easier to audit, faster to connect, and more resistant to vulnerabilities. On a Raff Tier 2 VM, we measured WireGuard throughput of approximately 940 Mbps with CPU usage under 10%, compared to OpenVPN peaking at 200–300 Mbps at full CPU on the same hardware. For teams who want secure, private access to their Raff infrastructure without exposing services to the public internet, WireGuard is the practical default in 2026.
In this tutorial, you will install and configure WireGuard on a Raff Ubuntu 24.04 VM acting as the VPN server, generate cryptographic key pairs for both server and client, configure the wg0 network interface, set up firewall and IP forwarding rules, configure a Linux or macOS client, and verify the encrypted tunnel is working end-to-end.
Note
This tutorial configures WireGuard in road warrior mode — one server, one or more remote clients. Each client gets a private IP in the 10.0.0.0/24 range and routes traffic to the server through an encrypted tunnel. This is the most common setup for securing admin access to cloud VMs.
Step 1 — Update the System and Install WireGuard
Start by updating your package index and installing WireGuard. On Ubuntu 24.04, WireGuard ships in the standard apt repository — no external PPA is needed.
bashsudo apt update && sudo apt upgrade -y
sudo apt install wireguard -y
WireGuard installs the wg command-line tool and the wg-quick helper that manages interface lifecycle. Verify the installation:
bashwg --version
Expected output:
wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/
The version number may differ slightly, but any v1.0.x build is correct. If the command is not found, run sudo modprobe wireguard to load the kernel module and retry.
Note
Ubuntu 24.04 ships with kernel 6.8, which includes WireGuard natively. You do not need to install any kernel modules separately.
Step 2 — Generate Server and Client Key Pairs
WireGuard uses asymmetric Curve25519 key pairs. Each peer (server and every client) needs its own private key and a derived public key. The private key never leaves the machine it was generated on.
On the server, generate the server's key pair:
bashwg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
Lock down the private key file so only root can read it:
bashsudo chmod 600 /etc/wireguard/server_private.key
Now generate the client key pair. You can do this on the server and then securely transfer the private key to the client, or generate it directly on the client machine. For simplicity, we generate both here and transfer later:
bashwg 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
Display the keys so you can reference them in the next steps:
bashsudo 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
Keep these values handy — you will paste them into the configuration files in Steps 3 and 4.
Warning
Never share or commit private keys. If a private key is exposed, regenerate the pair and update all peer configurations immediately.
Step 3 — Configure the WireGuard Server Interface
Create the server configuration file at /etc/wireguard/wg0.conf. Replace the placeholder values with your actual keys and server IP.
First, find your server's public-facing network interface name (usually eth0 or ens3):
baship route | grep default
Example output:
default via 203.0.113.1 dev eth0 proto dhcp
Note the interface name after dev — in this example, eth0. You will use it in the PostUp and PostDown rules below.
Create the config file:
bashsudo nano /etc/wireguard/wg0.conf
Paste the following, substituting your actual values:
ini[Interface]
# Server private key
PrivateKey = <paste-server-private-key-here>
# VPN IP address assigned to the server
Address = 10.0.0.1/24
# WireGuard listens on this UDP port
ListenPort = 51820
# Enable IP masquerading so VPN clients can reach the internet
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# Client public key
PublicKey = <paste-client-public-key-here>
# IP address assigned to this client inside the VPN
AllowedIPs = 10.0.0.2/32
Replace eth0 in the PostUp/PostDown lines with your actual interface name if it differs. Save and exit with Ctrl+O, then Ctrl+X.
Tip
If you have multiple clients, add a separate [Peer] block for each one, assigning each a unique AllowedIPs address (e.g., 10.0.0.3/32, 10.0.0.4/32).
Step 4 — Enable IP Forwarding
WireGuard needs the Linux kernel to forward packets between interfaces. Enable this permanently:
bashsudo nano /etc/sysctl.conf
Find the line #net.ipv4.ip_forward=1 and uncomment it (remove the #):
ininet.ipv4.ip_forward=1
Apply the change without rebooting:
bashsudo sysctl -p
Expected output:
net.ipv4.ip_forward = 1
Without this step, clients can connect to the VPN but cannot reach any network beyond the server itself — a common mistake that wastes troubleshooting time. We caught this during testing on a fresh Raff Tier 2 VM when pings to external IPs timed out despite the tunnel showing as active.
Step 5 — Open the Firewall for WireGuard
Allow UDP traffic on port 51820. If you are using UFW (the default on Ubuntu):
bashsudo ufw allow 51820/udp
sudo ufw status
Expected output (among other rules):
51820/udp ALLOW Anywhere
51820/udp (v6) ALLOW Anywhere (v6)
If you manage firewall rules through the Raff Cloud Panel firewall, add an inbound rule for UDP port 51820 from any source (or restrict to your client's IP range for tighter access control).
Tip
For production environments, restrict the allowed source IPs for port 51820 to your known client IP ranges. This reduces the exposure surface even further.
Step 6 — Start WireGuard and Enable Autostart
Bring the WireGuard interface up:
bashsudo wg-quick up wg0
Expected output:
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; ...
Enable WireGuard to start automatically on boot:
bashsudo systemctl enable wg-quick@wg0
Verify the interface is running:
bashsudo wg show
Expected output:
interface: wg0
public key: <your-server-public-key>
private key: (hidden)
listening port: 51820
No peers appear in handshake status yet — that changes once the client connects in the next step.
Step 7 — Configure the Client
On your client machine (Linux, macOS, or Windows with the WireGuard app installed), create the client configuration. If you generated the client keys on the server, securely copy the private key to your client machine now.
Create /etc/wireguard/wg0.conf on the client (Linux) or paste into the WireGuard app (macOS/Windows/iOS/Android):
ini[Interface]
# Client private key
PrivateKey = <paste-client-private-key-here>
# IP address assigned to this client inside the VPN
Address = 10.0.0.2/24
# Optional: use your server as DNS
DNS = 1.1.1.1
[Peer]
# Server public key
PublicKey = <paste-server-public-key-here>
# Server's public IP address and WireGuard port
Endpoint = <your-raff-vm-public-ip>:51820
# Route all traffic through the VPN (full tunnel)
AllowedIPs = 0.0.0.0/0
# Keep the tunnel alive through NAT (send keepalive every 25 seconds)
PersistentKeepalive = 25
Replace <your-raff-vm-public-ip> with your Raff VM's public IPv4 address. You can find this in the Raff Cloud Panel under your VM's details.
On a Linux client, bring the tunnel up:
bashsudo wg-quick up wg0
On macOS or Windows, import the configuration file into the WireGuard app and click "Activate."
Note
Setting AllowedIPs = 0.0.0.0/0 routes all client traffic through the VPN (full tunnel). To route only traffic destined for the VPN subnet (split tunnel — keeping your regular internet traffic on your local connection), set AllowedIPs = 10.0.0.0/24 instead.
Step 8 — Verify the Tunnel
Back on the server, check that the client has performed a handshake:
bashsudo wg show
After the client connects, you should see:
interface: wg0
public key: <server-public-key>
private key: (hidden)
listening port: 51820
peer: <client-public-key>
endpoint: <client-ip>:<ephemeral-port>
allowed ips: 10.0.0.2/32
latest handshake: X seconds ago
transfer: 1.23 KiB received, 4.56 KiB sent
The latest handshake line confirms an active, encrypted session. From the client, ping the server's VPN IP:
bashping 10.0.0.1
Expected output:
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=12.4 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=11.9 ms
If the ping succeeds, your WireGuard tunnel is fully operational. You can now SSH into your Raff VM using the private VPN IP (ssh user@10.0.0.1) rather than exposing SSH to the public internet.
Tip
Once the VPN is verified, consider removing the public SSH firewall rule and allowing SSH only over the wg0 interface. This eliminates SSH brute-force exposure entirely.
Conclusion
You now have a working WireGuard VPN server on your Raff Ubuntu 24.04 VM. All traffic between your client and server passes through an encrypted Curve25519 tunnel. Administrative access to your Raff infrastructure no longer requires exposing SSH, database ports, or internal dashboards to the public internet — everything routes privately through 10.0.0.x.
A few natural next steps from here:
- Add more clients: Copy the
[Peer]block pattern inwg0.conffor each new device, assigning uniqueAllowedIPsaddresses. Runsudo systemctl restart wg-quick@wg0to reload the config. - Harden SSH: After confirming VPN access works, restrict SSH to the VPN interface only by adding
ListenAddress 10.0.0.1in/etc/ssh/sshd_config. - Connect multiple Raff VMs: Add your other Raff VMs as peers to the same WireGuard server, enabling private inter-VM communication without traffic traversing the public internet. Pair this with Raff private networking for full network isolation.
This tutorial was tested by Aybars on a Raff Tier 2 VM (1 vCPU / 2 GB RAM) running Ubuntu 24.04 LTS. The full setup — from apt install to first successful ping — completed in under 25 minutes.

