Quick take: WireGuard is the fastest, simplest VPN protocol available today. It was merged into the Linux kernel in 2020 and has a codebase of roughly 4,000 lines — compared to OpenVPN's 400,000. On Ubuntu, a working VPN server takes about 20 minutes to configure from scratch.

Introduction

VPNs are no longer just for enterprise networks. A self-hosted VPN on a cheap VPS gives you a fixed, trusted IP to whitelist on firewalls, secures your traffic on untrusted hotel and cafe networks, and lets you connect securely to home or office servers from anywhere. WireGuard makes this setup fast, maintainable, and cryptographically modern.

I run WireGuard on a Hetzner VPS for my own use and recommend it to clients across Saudi Arabia, Europe, and the US who need secure remote access without paying for enterprise VPN licences. A 2 EUR/month VPS handles the personal and small-team use case perfectly.

Why WireGuard Over OpenVPN or IPsec

OpenVPN has served the industry well, but its complexity is a liability. The configuration involves certificates, cipher suite negotiation, TLS setup, and configuration files that span hundreds of lines. WireGuard uses a single set of modern cryptographic primitives — ChaCha20 for encryption, Poly1305 for authentication, Curve25519 for key exchange — chosen once by experts. You do not configure cipher suites. There is nothing to negotiate.

The performance difference is measurable. WireGuard operates at the kernel level and its handshake is faster than OpenVPN's TLS handshake by an order of magnitude. On mobile devices where networks change constantly (switching between WiFi and mobile data), WireGuard reconnects almost instantly because it maintains no persistent connections — it is stateless at the protocol level.

IPsec is powerful but even more complex to configure correctly. WireGuard's simplicity also makes it auditable — a security researcher can read the entire protocol implementation in a sitting, something impossible with OpenVPN or IPsec.

Installing WireGuard on Ubuntu

WireGuard is in Ubuntu's official repositories since 20.04:

sudo apt update
sudo apt install wireguard -y

Verify the installation and check the available tools:

wg --version
which wg-quick

Generating Cryptographic Keys

WireGuard uses public/private key pairs — one per peer. Generate the server keys first. The umask 077 ensures the private key file is created with 600 permissions:

cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key

View the keys — you will need both values for the configuration:

cat /etc/wireguard/server_private.key
cat /etc/wireguard/server_public.key

Generate a key pair for your first client:

wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Each client must have its own key pair. Never reuse keys between clients. If one client is compromised, you remove only its public key from the server config and generate a new pair — without disrupting any other client.

Configuring the WireGuard Server

Create the server configuration file. Replace the placeholder key values with your actual keys from the files above:

sudo nano /etc/wireguard/wg0.conf
[Interface]
PrivateKey = PASTE_SERVER_PRIVATE_KEY_HERE
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Client 1 — Laptop
PublicKey = PASTE_CLIENT1_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32

Important notes on this configuration:

  • Address 10.0.0.1/24 gives the server the first IP in a private subnet. Clients get subsequent IPs (10.0.0.2, 10.0.0.3, and so on).
  • ListenPort 51820 is the default WireGuard UDP port. You can change this — update the firewall and client configs to match.
  • Replace eth0 in PostUp/PostDown with your server's actual network interface. Find it with: ip route | grep default
  • AllowedIPs = 10.0.0.2/32 means only traffic from that exact IP will be accepted from this peer.

Set correct permissions on the config file:

sudo chmod 600 /etc/wireguard/wg0.conf

Firewall Rules and IP Forwarding

Enable IP forwarding so the server can route traffic between peers and the internet:

sudo nano /etc/sysctl.conf

Find and uncomment, or add:

net.ipv4.ip_forward = 1

Apply the change immediately without rebooting:

sudo sysctl -p

Open the WireGuard port in UFW and confirm SSH is still allowed:

sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw status

Start WireGuard and enable it on boot:

sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

Verify the interface is up and the server key is shown:

sudo wg show

Setting Up a Client

Install WireGuard on the client depending on the operating system:

# Ubuntu / Debian client
sudo apt install wireguard -y

# macOS: install the WireGuard app from the Mac App Store
# Windows: download from wireguard.com/install/
# iOS / Android: install the WireGuard app from the App Store or Google Play

Create the client config. On Linux this lives at /etc/wireguard/wg0.conf. On mobile, you can scan a QR code or import the file:

[Interface]
PrivateKey = PASTE_CLIENT1_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = PASTE_SERVER_PUBLIC_KEY_HERE
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Key settings to understand:

  • DNS = 1.1.1.1 routes DNS queries through the VPN, preventing DNS leaks.
  • AllowedIPs = 0.0.0.0/0 routes all traffic through the VPN (full tunnel). To route only VPN subnet traffic, use 10.0.0.0/24 instead (split tunnel).
  • PersistentKeepalive = 25 sends a keepalive packet every 25 seconds to maintain the connection through NAT firewalls and mobile network changes.

To generate a QR code for mobile import, install qrencode and run:

sudo apt install qrencode
qrencode -t ansiutf8 < /etc/wireguard/client1.conf

Connecting and Testing

Start the VPN on the Linux client:

sudo wg-quick up wg0

Test connectivity to the server's VPN IP:

ping 10.0.0.1

Verify all traffic is routing through the VPN by checking your public IP — it should now show the server's IP:

curl ifconfig.me

On the server, confirm the peer handshake was successful:

sudo wg show

You should see a recent "latest handshake" timestamp for the peer. Disconnect when done:

sudo wg-quick down wg0

Adding More Peers

Adding a second client does not require restarting WireGuard. Generate keys for the new client:

cd /etc/wireguard
wg genkey | tee client2_private.key | wg pubkey > client2_public.key

Add a new peer block to the server config:

sudo nano /etc/wireguard/wg0.conf
[Peer]
# Client 2 — Phone
PublicKey = PASTE_CLIENT2_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.3/32

Reload WireGuard without disconnecting existing peers:

sudo wg syncconf wg0 <(sudo wg-quick strip wg0)

This is preferable to bringing the interface down and up again, which would briefly disconnect all connected clients.

Troubleshooting

No handshake / cannot connect: Check that port 51820/UDP is open. Test from the client with:

nc -u -z -v YOUR_SERVER_IP 51820

Also check your cloud provider's security group or firewall — AWS, DigitalOcean, and Hetzner all have separate firewall rules outside the OS that may block the port.

Traffic routing but no internet access: IP forwarding is not enabled or the iptables rules are not applied. Verify:

cat /proc/sys/net/ipv4/ip_forward    # should be 1
sudo iptables -t nat -L POSTROUTING  # should show MASQUERADE rule

DNS leaks: Add DNS = 1.1.1.1 to the client config and confirm AllowedIPs = 0.0.0.0/0 to route all traffic including DNS through the tunnel. Test at dnsleaktest.com.

Final Thoughts

WireGuard is the VPN I recommend without reservation for any use case where you control the server. Its simplicity is a security property — there is less code to have bugs in, less configuration to misconfigure, and less to audit. Once you have set it up once, the operational overhead is minimal: adding a new peer takes a minute, revoking one takes seconds.

For personal use, a 2-4 EUR/month VPS runs WireGuard comfortably alongside other services. For a team of 10 people, the same setup scales without any additional infrastructure. The moment you need more than basic routing — site-to-site tunnels, hub-and-spoke topologies, enterprise key management — tools like Tailscale (which runs WireGuard underneath) add orchestration without changing the underlying protocol.

FAQ: How to Set Up WireGuard VPN Server on Ubuntu

Is WireGuard more secure than OpenVPN?+

WireGuard uses a small, modern, auditable codebase with fixed cryptographic primitives — no cipher negotiation, no legacy options. OpenVPN is battle-tested but has a much larger attack surface. For most use cases WireGuard is the more secure choice in 2026, assuming it is configured correctly.

What port does WireGuard use?+

WireGuard defaults to UDP port 51820. You can change this in the server config with ListenPort. Remember to update your firewall rules and all client configs to match the new port.

Can I run WireGuard on a cheap VPS?+

Yes — WireGuard is extremely lightweight. A 1 vCPU, 512MB RAM VPS handles dozens of personal-use clients without any performance issues. Hetzner, DigitalOcean, Vultr, and Linode all work well. Make sure your provider allows custom UDP ports.

How do I revoke access for a specific client?+

Remove the [Peer] block containing that client's public key from /etc/wireguard/wg0.conf, then reload without restarting: sudo wg syncconf wg0 $(wg-quick strip wg0). The client is disconnected immediately and cannot reconnect.

Does WireGuard work on mobile devices?+

Yes — WireGuard has official apps on the App Store and Google Play. You can import the client config by scanning a QR code generated on the server, or by transferring the config file directly. The mobile app reconnects automatically when the network changes.

Need help with your Linux server or infrastructure?

Work directly with Muhammad Irfan Aslam for Linux, Docker, Nginx, DevOps, cloud, and server support.

Hire Me for Support