👍 What we like
- ✓Lightweight with minimal code compared to OpenVPN
- ✓Integrated directly into the Linux kernel
- ✓Significantly faster performance
- ✓No third-party trust required for data privacy
👎 What to watch
- ✕Requires manual configuration of routing and NAT
- ✕Needs VPS hardening for optimal security
- ✕Must ensure UDP port 51820 is not blocked
📑 Contents ▾
- 01 Prerequisites
- 02 Step 1: Install WireGuard
- 03 Step 2: Enable IP routing on the server
- 04 Step 3: Generate server keys
- 05 Step 4: Identify the outgoing network interface
- 06 Step 5: Create the server configuration
- 07 Step 6: Open the port in the firewall
- 08 Step 7: Start the WireGuard server
- 09 Step 8: Configure a first client (smartphone)
- · Declare the client on the server
- · Create the client config file
- · Generate a QR code for the phone
- 13 Step 9: Connect a computer (Linux / Windows / macOS)
- 14 Verification
- 15 Best practices and security
- 16 FAQ
- · Is WireGuard really faster than OpenVPN?
- · Is my own VPN more anonymous than a commercial VPN?
- · What if the connection does not establish (no handshake)?
- · How many clients can I connect?
- · Can I access my home local network via this VPN?
- 22 Related topics
Commercial VPNs are convenient, but you pay a subscription to trust a third party with your data. Setting up your own WireGuard VPN on a VPS changes the game: you get a fixed IP you control, a modern encrypted tunnel, and the certainty that no connection logs are being sold, since you are the operator. It is ideal for securing your traffic on public Wi-Fi, accessing your homelab remotely, or simply having a clean Internet exit.
WireGuard has established itself as the standard in 2026: it consists of just a few thousand lines of code (compared to hundreds of thousands for OpenVPN), it is integrated into the Linux kernel, and it is significantly faster. In this guide, we install WireGuard on a VPS, generate server and client keys, configure routing and NAT to route all traffic, and connect a phone (via QR code) and a computer. By the end, you will have a functional and secure personal VPN.
Prerequisites
-
A Linux VPS (Ubuntu 24.04 or Debian 12) with a public IP. A small VPS is more than enough: WireGuard is extremely lightweight. Hosts like Hetzner (€4/month) or DigitalOcean are perfectly suitable. See our DigitalOcean vs Vultr vs Hetzner comparison.
-
root/sudoaccess on the VPS. Ideally, harden it first with our guide install and secure an Ubuntu VPS. -
A client to connect: smartphone (WireGuard iOS/Android app) and/or computer.
-
20 to 30 minutes.
WireGuard operates over UDP on port 51820 by default. Ensure your host does not block incoming UDP (rare, but worth checking).
Step 1: Install WireGuard
On Ubuntu/Debian, WireGuard is in the standard repositories:
sudo apt update
sudo apt install -y wireguard wireguard-tools
The kernel module has been included in Linux since version 5.6, so there is nothing else to compile. Verify the tools are available:
wg --version
Step 2: Enable IP routing on the server
For the VPS to route your clients’ traffic to the Internet, enable IP forwarding. Edit the sysctl configuration:
sudo nano /etc/sysctl.d/99-wireguard.conf
Add:
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
Apply without rebooting:
sudo sysctl --system
Verify:
sysctl net.ipv4.ip_forward
The output should display net.ipv4.ip_forward = 1.
Step 3: Generate server keys
WireGuard uses public/private key cryptography. Generate the server key pair in a protected directory:
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard
cd /etc/wireguard
umask 077
wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
The umask 077 command ensures that key files are readable only by root. Display both keys; you will need them:
echo "SERVER PRIVATE KEY: $(sudo cat /etc/wireguard/server_private.key)"
echo "SERVER PUBLIC KEY: $(sudo cat /etc/wireguard/server_public.key)"
Step 4: Identify the outgoing network interface
NAT needs to know which interface goes out to the Internet. Find it:
ip route get 1.1.1.1 | grep -oP 'dev \K\S+'
Note the returned name (often eth0, ens3, or enp1s0). We will use it in the config. In the following steps, we assume eth0; replace it with your own.
Step 5: Create the server configuration
Create the wg0 interface file:
sudo nano /etc/wireguard/wg0.conf
Paste the following configuration, replacing SERVER_PRIVATE_KEY with the server’s private key and eth0 with your outgoing interface:
[Interface]
# Server address in the private VPN network
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
# Enable NAT so clients can access the Internet via the VPS
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
# Client [Peer] blocks will be added below
We have chosen the private subnet 10.8.0.0/24 for the VPN. The server is 10.8.0.1, and clients will take 10.8.0.2, 10.8.0.3, etc.
Secure the file:
sudo chmod 600 /etc/wireguard/wg0.conf
Step 6: Open the port in the firewall
If you use UFW (recommended), allow the WireGuard port:
sudo ufw allow 51820/udp
sudo ufw reload
Verify that the rule is present:
sudo ufw status | grep 51820
Step 7: Start the WireGuard server
WireGuard integrates with systemd via wg-quick. Enable and start the interface:
sudo systemctl enable --now wg-quick@wg0
Verify that the interface is up:
sudo wg show
You should see the wg0 interface with its public key and listening port. No peers yet, which is normal.
Step 8: Configure a first client (smartphone)
Generate a key pair for the client (each client has its own). Still on the server, in /etc/wireguard:
cd /etc/wireguard
umask 077
wg genkey | sudo tee client_phone_private.key | wg pubkey | sudo tee client_phone_public.key
Declare the client on the server
Add a [Peer] block to the end of /etc/wireguard/wg0.conf:
sudo nano /etc/wireguard/wg0.conf
[Peer]
# Phone
PublicKey = CLIENT_PHONE_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
AllowedIPs = 10.8.0.2/32 tells the server that this peer is reachable at address 10.8.0.2. Reload the configuration without dropping existing connections:
sudo systemctl restart wg-quick@wg0
Create the client config file
On the server, prepare the client config content. First, retrieve the necessary values:
echo "CLIENT PRIVATE KEY: $(sudo cat /etc/wireguard/client_phone_private.key)"
echo "SERVER PUBLIC KEY: $(sudo cat /etc/wireguard/server_public.key)"
The client configuration looks like this (adapt as needed):
[Interface]
PrivateKey = CLIENT_PHONE_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = 203.0.113.10:51820
# All traffic goes through the VPN ("full tunnel")
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Replace 203.0.113.10 with your VPS’s public IP. The AllowedIPs = 0.0.0.0/0 on the client side means “route all traffic through the tunnel,” which makes this a full VPN. PersistentKeepalive = 25 keeps the tunnel open behind NATs, which is useful for mobility.
Generate a QR code for the phone
The easiest way to configure a mobile device is to display the config as a QR code to scan with the WireGuard app. Install the tool and generate the code (paste the client config into a temporary file first):
sudo apt install -y qrencode
# Create the client file then:
qrencode -t ansiutf8 < /tmp/client_phone.conf
Open the WireGuard app on your phone, choose “Add tunnel > Scan QR code,” scan, and activate the tunnel. Immediately delete the temporary file containing the private key:
shred -u /tmp/client_phone.conf
Step 9: Connect a computer (Linux / Windows / macOS)
For a computer, proceed similarly: a dedicated key pair, a [Peer] block on the server with AllowedIPs = 10.8.0.3/32, and a .conf file on the client identical to the phone’s (changing the private key and the 10.8.0.3/32 address).
On Linux, place the config in /etc/wireguard/wg0.conf and run:
sudo wg-quick up wg0
On Windows and macOS, install the official WireGuard application, import the .conf file, and activate the tunnel with one click.
Verification
Once the tunnel is active on a client, check on the server that the handshake has occurred:
sudo wg show
You should see a recent latest handshake line under the peer and rising transfer counters. On the client side, check your public IP: it should now be that of your VPS.
curl -s https://api.ipify.org && echo
Also test that DNS is not leaking (DNS queries must pass through the server configured in DNS =). Visit a DNS leak test site from the connected client.
Best practices and security
-
One key per device. Never share the same key pair between multiple clients: if a device is lost, you revoke only its peer without affecting others.
-
Revoking a client is done by removing its
[Peer]block fromwg0.confand then restarting the service. The key becomes useless instantly. -
Split tunnel. If you only want to route access to your homelab (and not all your traffic), replace
AllowedIPs = 0.0.0.0/0on the client side with the relevant subnet, e.g.,10.8.0.0/24, 192.168.1.0/24. -
Kill switch. The WireGuard mobile app offers a “Block traffic when VPN is off” option. On desktop,
wg-quickcan add firewall rules to prevent any leaks if the tunnel drops. -
Private DNS. To avoid relying on any public resolver, host an AdGuard Home or Pi-hole on the VPS and point
DNS = 10.8.0.1on the client side. -
Backup
/etc/wireguard. This folder contains all your keys; include it in your backup strategy (see encrypted backups with restic).
FAQ
Is WireGuard really faster than OpenVPN?
Yes, significantly. Thanks to its kernel integration and minimalist codebase, WireGuard offers higher throughput and lower latency than OpenVPN, especially on mobile where connection establishment is almost instantaneous. The trade-off: fewer esoteric configuration options, but for 99% of use cases, this is an advantage. See WireGuard vs OpenVPN vs Tailscale.
Is my own VPN more anonymous than a commercial VPN?
Different, not necessarily more anonymous. You have the guarantee that no logs are sold, and total control. But the exit IP is unique and associated with you (rented in your name at the host), so it is not suitable for mass anonymity. It is excellent for traffic privacy, remote access, and bypassing insecure Wi-Fi. For strong anonymity, a multi-user no-log VPN remains relevant: see our best VPN comparison.
What if the connection does not establish (no handshake)?
Check in order: port 51820/udp is open (sudo ufw status), the client-side Endpoint points to the correct public IP, IP forwarding is active (sysctl net.ipv4.ip_forward), and the client’s public key declared on the server matches. A sudo wg show without a handshake almost always indicates a network block or a key/endpoint error.
How many clients can I connect?
Dozens without problem on a small VPS: WireGuard is extremely lightweight in CPU and RAM. The practical limit is rather your VPS’s bandwidth and the monthly traffic quota of your plan. Each client just needs its [Peer] block and a unique address in the 10.8.0.0/24 subnet.
Can I access my home local network via this VPN?
Yes, this is a classic use case. If your homelab is on the same VPS or accessible from it, add the relevant subnet to the client’s AllowedIPs. To reach a network behind another machine, you need to configure that machine as a relay peer with appropriate routing.
Related topics
You now have an encrypted, fast, and fully controlled personal VPN. Add your devices over time and remember to back up your keys. To stay updated on self-hosting news and VPS deals, join our Telegram monitoring bot.