How to Install WireGuard on VPS (2025) — Step-by-Step Guide
Why Choose WireGuard Over OpenVPN and Other VPN Protocols
WireGuard has become the standard for modern VPN. For choosing a location, see VPS for WireGuard deployments because it addresses the fundamental problems that plagued older protocols. OpenVPN, while battle-tested, relies on a complex codebase with over 100,000 lines of code. WireGuard achieves the same in roughly 4,000 lines. For privacy hosting, consider Estonia VPS or Finland VPS. This smaller attack surface translates directly to better security and fewer vulnerabilities.
Performance is where WireGuard truly separates itself. Benchmarks consistently show WireGuard achieving 3-5x the throughput of OpenVPN on identical hardware. On a VPS with a 1Gbps connection, OpenVPN typically maxes out between 150-300Mbps due to TLS handshake overhead and cryptographic inefficiency. WireGuard routinely saturates the link. The protocol uses modern cryptography exclusively: Curve25519 for key exchange, ChaCha20 for symmetric encryption, and Poly1305 for message authentication. There are no cipher suite negotiation phases, no legacy compatibility layers, and no algorithm agility that could be exploited.
WireGuard is also stateless in a way that benefits mobile users. If your connection drops, WireGuard silently reconnects without re-establishing tunnels from scratch. Roaming between Wi-Fi and cellular networks works seamlessly because the protocol is designed around the concept of cryptographic keys rather than connection state. Each peer has a static public key, and packets are authenticated against that key regardless of which IP address they arrive from.
For VPS users, WireGuard is lightweight enough to run on the smallest instances. It consumes minimal RAM (typically under 5MB) and negligible CPU at idle. This makes it ideal for budget VPS plans where resources are constrained. WireGuard is also included in the Linux kernel since version 5.6, meaning there is no userspace daemon overhead on modern distributions.
Prerequisites
Before you begin this guide, make sure your environment meets the following requirements:
| Requirement | Details |
|---|---|
| Operating System | Ubuntu 22.04 LTS or 24.04 LTS (clean install recommended) |
| Root Access | SSH access with root privileges or a sudo user |
| RAM | Minimum 512MB (WireGuard uses under 5MB at idle) |
| Network | Public IPv4 address, TCP/UDP 51820 port open |
| Client | WireGuard client app for your device (Windows, macOS, Linux, iOS, Android) |
Important: If your VPS provider uses NAT (some budget providers share IPv4 addresses), you will need a dedicated IPv4 address for WireGuard. Check with your provider if your IP is reachable on port 51820/UDP.
Step 1: Update Your System and Install WireGuard
Start by connecting to your VPS via SSH and updating all installed packages. This ensures you have the latest security patches and kernel modules.
ssh root@your-vps-ip
apt update && apt upgrade -y
Once the system is updated, install the WireGuard package. On Ubuntu 22.04 and later, WireGuard is available directly from the standard repositories and includes the kernel module.
apt install wireguard -y

wg --version
Step 2: Generate Server Keys
WireGuard uses public-key cryptography. Every peer (server and each client) needs a unique key pair. The server needs its own pair, and you will generate additional pairs for each client device.
Create the WireGuard configuration directory if it does not already exist, then generate the server private key. The private key must never be shared or transmitted. Redirect the output directly to the private key file to avoid it appearing in shell history or logs.
mkdir -p /etc/wireguard
chmod 700 /etc/wireguard
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
Display the server public key so you can reference it when configuring clients.
cat /etc/wireguard/server_public.key
Security Warning: The private key in /etc/wireguard/server_private.key is the single most sensitive file in your VPN setup. If this key is compromised, anyone with it can impersonate your server. Never copy it to unencrypted storage, never share it in chat logs, and never commit it to version control.
Step 3: Create the Server Configuration File
Create the WireGuard server configuration file at /etc/wireguard/wg0.conf. This file defines the virtual network interface, the IP address range for the VPN tunnel, and rules for routing traffic.
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = SERVER_PRIVATE_KEY
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 51820
SaveConfig = true
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
# Client 1: Laptop
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.66.66.2/32,fd42:42:42::2/128
EOF
Replace SERVER_PRIVATE_KEY with the content of your server private key (the output of cat /etc/wireguard/server_private.key). Replace CLIENT1_PUBLIC_KEY with the client public key you will generate in Step 7. The AllowedIPs field for each peer specifies which IP addresses that peer is allowed to use and which traffic will be routed through the tunnel.
Understanding the Configuration
The [Interface] section defines the server side. Address assigns the tunnel IP addresses (both IPv4 and IPv6). ListenPort sets the UDP port for incoming connections. SaveConfig automatically saves peer additions made with the wg command back to this file.
The PostUp and PostDown rules manage iptables. When the interface comes up, they create forwarding rules and a NAT masquerade rule so that client traffic exits through your VPS public IP. When the interface goes down, the rules are removed to prevent traffic leaks. Replace eth0 with your actual network interface name if it differs (check with ip a).
Step 4: Enable IP Forwarding
By default, Linux does not forward packets between interfaces. For your VPS to act as a VPN gateway, you must enable IP forwarding. Open the sysctl configuration file and modify the forwarding parameter.
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/99-wireguard.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.d/99-wireguard.conf
sysctl --system
Verify that forwarding is enabled.
sysctl net.ipv4.ip_forward
The output should show net.ipv4.ip_forward = 1. If it shows 0, the configuration file was not applied correctly.
Step 5: Configure Firewall Rules
If your VPS uses UFW (Uncomplicated Firewall), you need to allow WireGuard traffic and configure forwarding. If you use raw iptables or another firewall, adjust the rules accordingly.
ufw allow 51820/udp
ufw route allow in on wg0 out on eth0
ufw reload
For iptables without UFW, the PostUp and PostDown rules in your wg0.conf already handle the NAT and forwarding. If you have additional iptables rules, make sure they do not block traffic on the wg0 interface.
Check your network interface name. Many VPS providers use ens3, ens192, or enp1s0 instead of eth0.
ip -o -4 route show to default | awk '{print $5}'
Use the interface name returned by this command in your wg0.conf PostUp/PostDown rules.
Step 6: Start the WireGuard Server
Bring up the WireGuard interface and enable it to start automatically on boot.
wg-quick up wg0
systemctl enable wg-quick@wg0
Check the interface status to confirm it is running.
wg show

Step 7: Generate Client Configuration
Each device that connects to your WireGuard VPN needs its own key pair and configuration file. Repeat this process for every client device.
Generate Client Keys
cd /etc/wireguard
wg genkey | tee client1_private.key | wg pubkey > client1_public.key
chmod 600 client1_private.key
Create Client Configuration File
cat > client1.conf << 'EOF'
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.66.66.2/24,fd42:42:42::2/64
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_VPS_IP:51820
AllowedIPs = 0.0.0.0/0,::/0
PersistentKeepalive = 25
EOF
Replace CLIENT1_PRIVATE_KEY with the output of cat /etc/wireguard/client1_private.key. Replace SERVER_PUBLIC_KEY with the output of cat /etc/wireguard/server_public.key. Replace YOUR_VPS_IP with your actual VPS public IP address or hostname.
Understanding Client Settings
The DNS directive sets the DNS resolver that the client will use while connected to the VPN. Using 1.1.1.1 (Cloudflare) or 9.9.9.9 (Quad9) prevents DNS leaks. If you want all DNS queries to go through your VPS, you can set up a DNS resolver on the server and point this to 10.66.66.1.
The AllowedIPs = 0.0.0.0/0,::/0 setting routes all traffic (both IPv4 and IPv6) through the VPN tunnel. If you only want VPN access for specific subnets (split tunneling), list those subnets instead. For example, AllowedIPs = 10.66.66.0/24 would only route traffic destined for the VPN network.
PersistentKeepalive = 25 sends a keepalive packet every 25 seconds. This is essential for clients behind NAT (home routers, mobile networks) because it prevents the NAT mapping from timing out and breaking the connection. The 25-second interval is recommended by the WireGuard documentation.
Step 8: Add the Client Peer to the Server
The client configuration file references the server, but the server also needs to know about the client. Add the client public key to the server configuration.
SERVER_PUB=$(cat /etc/wireguard/server_public.key)
CLIENT_PUB=$(cat /etc/wireguard/client1_public.key)
wg set wg0 peer $CLIENT_PUB allowed-ips 10.66.66.2/32,fd42:42:42::2/128
If you set SaveConfig = true in the server configuration, the peer is automatically saved to wg0.conf when the interface is brought down or when you run wg-quick save wg0.
wg-quick save wg0
Step 9: Import Configuration on Client Devices
To connect from a client device, you need to transfer the client configuration file securely. Use SCP or copy the file contents directly.
scp root@your-vps-ip:/etc/wireguard/client1.conf ~/client1.conf
Linux Clients
cp client1.conf /etc/wireguard/wg0.conf
wg-quick up wg0
Windows Clients
Download the WireGuard client from wireguard.com, launch the application, click "Import tunnel(s) from file," and select the .conf file. Click "Activate" to connect.
macOS Clients
Install WireGuard from the App Store or with brew install wireguard-tools. Import the configuration file through the WireGuard menu bar icon or use the command line with wg-quick up ./client1.conf.
Mobile Clients (iOS and Android)
Install the WireGuard app from the App Store or Google Play. Create a QR code from the configuration file to scan it with your phone camera.
apt install qrencode -y
qrencode -t ansiutf8 < /etc/wireguard/client1.conf
Open the WireGuard app, tap the plus icon, and select "Scan from QR code." Point your camera at the terminal output to add the tunnel.
Setting Up DNS Resolution Through the VPN
By default, the client configuration uses public DNS servers. If you want DNS queries to resolve through your VPS IP (useful for bypassing DNS-based censorship or accessing internal services), install a DNS resolver on the server.
apt install unbound -y
systemctl enable unbound
systemctl start unbound
Edit the Unbound configuration to listen on the WireGuard interface and allow queries from VPN clients.
cat >> /etc/unbound/unbound.conf.d/wireguard.conf << 'EOF'
server:
interface: 10.66.66.1
access-control: 10.66.66.0/24 allow
do-not-query-localhost: no
EOF
systemctl restart unbound
Update the client configuration to use the VPS as the DNS resolver. Change the DNS line to:
DNS = 10.66.66.1
Implementing a Kill Switch
A kill switch prevents traffic from leaking outside the VPN tunnel if the connection drops. On Linux clients, you can implement this with iptables rules that block all non-VPN traffic.
iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
On Windows and macOS, the WireGuard client handles this through the AllowedIPs setting. Setting AllowedIPs = 0.0.0.0/0,::/0 effectively acts as a kill switch because the operating system will only route traffic through the WireGuard interface. If the interface goes down, traffic has no route and is dropped.
For a stronger kill switch on Linux, add the following to your client [Interface] section:
PostUp = iptables -I OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j REJECT; ip6tables -I OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j REJECT
PostDown = iptables -D OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j REJECT; ip6tables -D OUTPUT ! -o %i -m addrtype ! --dst-type LOCAL -j REJECT
Adding Multiple Clients
To add more devices to your WireGuard VPN, generate a new key pair for each device and assign a unique tunnel IP address.
# Generate keys for client 2
wg genkey | tee /etc/wireguard/client2_private.key | wg pubkey > /etc/wireguard/client2_public.key
chmod 600 /etc/wireguard/client2_private.key
# Add peer to server
CLIENT2_PUB=$(cat /etc/wireguard/client2_public.key)
wg set wg0 peer $CLIENT2_PUB allowed-ips 10.66.66.3/32,fd42:42:42::3/128
wg-quick save wg0
Create a new client configuration file with address 10.66.66.3/24 and the client2 private key. Each client must have a unique IP address within the 10.66.66.0/24 subnet.
Performance Tuning
MSS Clamping
WireGuard packets have additional overhead from encryption headers. If you experience slow speeds or connection timeouts, MSS clamping may help. This adjusts the maximum segment size of TCP packets to account for the extra bytes added by the tunnel encapsulation.
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --clamp-mss-to-pmtu
MTU Configuration
The default MTU for WireGuard is 1420 bytes (standard 1500 minus 80 bytes for overhead). If you experience connectivity issues, try lowering the MTU further. Add this to both the server and client [Interface] sections:
[Interface]
MTU = 1280
An MTU of 1280 is the minimum allowed by IPv6 and works reliably across all network paths, including those with additional encapsulation layers.
Kernel Ring Buffer
On high-throughput connections (1Gbps+), you may benefit from increasing the network ring buffer size. This prevents packet drops under heavy load.
echo "net.core.rmem_max = 2500000" >> /etc/sysctl.d/99-wireguard.conf
echo "net.core.wmem_max = 2500000" >> /etc/sysctl.d/99-wireguard.conf
sysctl --system
Endpoint Hostname with Dynamic DNS
If your VPS IP changes (uncommon but possible), use a DNS hostname as the Endpoint in client configurations. Point a DNS A record to your VPS IP and use the hostname instead of the raw IP. WireGuard will resolve the hostname each time it needs to establish a connection.
Troubleshooting Common Issues
1. Handshake Failure — No Response from Peer
Symptom: The client shows "Handshake did not complete" and the last handshake timestamp never updates.
Solution: Verify that UDP port 51820 is open and reachable. Check your VPS firewall and security group settings. Many cloud providers block all ports by default. Test connectivity with:
nc -zuv YOUR_VPS_IP 51820
If the connection times out, the port is blocked at the firewall or provider level. Also verify that the server public key in the client config matches the actual server public key exactly.
2. Connected But No Internet Access
Symptom: The handshake completes successfully, but you cannot access websites or external resources.
Solution: IP forwarding is likely not enabled, or the NAT masquerade rule is missing or using the wrong interface name. Verify forwarding is active with sysctl net.ipv4.ip_forward. Check your PostUp rule in wg0.conf to confirm the interface name matches your actual public interface.
3. DNS Not Working Through VPN
Symptom: You can access websites by IP address but domain names do not resolve.
Solution: The DNS setting in the client configuration may be unreachable. Test with nslookup google.com 1.1.1.1 from the client. If that works, the VPN tunnel is functional but the configured DNS server may be blocked. Try changing the DNS to 9.9.9.9 (Quad9) or 8.8.8.8.
4. Speed Significantly Slower Than Expected
Symptom: Throughput is well below what your VPS connection should support.
Solution: Check the CPU usage on your VPS with htop. Encryption is CPU-bound, and budget VPS instances with shared CPU may throttle under sustained load. Try switching to a VPS with AES-NI instruction set support. Also test different MTU values and ensure MSS clamping is configured.
5. WireGuard Service Fails to Start
Symptom: systemctl start wg-quick@wg0 fails with an error about the interface.
Solution: Check the journal logs for the specific error. Common causes include: syntax errors in wg0.conf, incorrect private key, or a missing WireGuard kernel module. On some minimal VPS images, the kernel module may not be loaded.
journalctl -u wg-quick@wg0 --no-pager -n 30
If the kernel module is missing, try installing the wireguard-dkms package or update your kernel to version 5.6 or later.
Managing WireGuard with wg Command
The wg command provides real-time interface management. Here are the most useful commands for day-to-day administration.
Show all active interfaces and peers:
wg show
Show a specific interface:
wg show wg0
Remove a peer immediately without modifying the config file:
wg set wg0 peer CLIENT_PUBLIC_KEY remove
Change the endpoint for an existing peer (useful if a client has a dynamic IP):
wg set wg0 peer CLIENT_PUBLIC_KEY endpoint 203.0.113.45:51820
Automated WireGuard Management with wg-quick
The wg-quick utility simplifies common operations. Bring the interface up and down, strip or save the configuration.
# Bring the interface up
wg-quick up wg0
# Bring the interface down
wg-quick down wg0
# Save the current runtime configuration to the config file
wg-quick save wg0
# Strip private keys from a config file (for sharing or debugging)
wg-quick strip wg0
Security Best Practices
While WireGuard is secure by design, proper operational practices are essential. Rotate your keys periodically. WireGuard makes this straightforward because you can update a peer key without restarting the interface.
# Generate new server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
wg set wg0 private-key /etc/wireguard/server_private.key
wg-quick save wg0
After rotating the server key, every client must be updated with the new server public key. Limit the number of peers to devices you actively use. Remove old or unused peers from the configuration.
Disable the WireGuard interface when you are not using it to reduce the attack surface.
wg-quick down wg0
Consider using a non-standard port for WireGuard if you face active port scanning. Change the ListenPort in both the server and client configurations.
Frequently Asked Questions
Is WireGuard free to use on a VPS?
Yes. WireGuard is open-source software released under the GPLv2 license. There are no licensing fees. You can install it on any VPS without cost beyond the VPS hosting itself.
Can I use WireGuard and OpenVPN on the same VPS?
Yes, but they must use different ports. WireGuard defaults to UDP 51820, while OpenVPN typically uses UDP 1194 or TCP 443. Make sure your iptables and firewall rules do not conflict between the two services.
How many clients can connect to a single WireGuard server?
WireGuard itself has no hard limit on the number of peers. In practice, performance depends on your VPS CPU and bandwidth. For typical use cases, a single VPS can handle 50-100 concurrent connections without issues. High-throughput scenarios with many active peers will benefit from a multi-core VPS.
Does WireGuard work through corporate firewalls?
It depends on the firewall configuration. WireGuard uses UDP, which some restrictive firewalls block. If UDP is blocked, you can use a UDP-over-TCP wrapper like udp2raw to encapsulate WireGuard traffic in TCP packets, though this adds complexity and latency.
How do I check if my traffic is actually going through the VPN?
After connecting, check your external IP address. It should show your VPS IP instead of your real IP. Use a service like curl ifconfig.me or visit whatismyipaddress.com in your browser.
Can I assign static IP addresses to each client?
Yes. The IP address for each client is determined by the Address field in the client configuration file and the corresponding AllowedIPs field in the server peer entry. As long as these match and are unique per client, the IP assignment is effectively static.
How do I update WireGuard to the latest version?
On Ubuntu, run apt update && apt upgrade -y. WireGuard is part of the kernel since 5.6, so the kernel module updates with your system kernel. The userspace tools update with the wireguard package.
What happens if I lose the server private key?
You need to generate a new key pair, update the server configuration, and redistribute new client configuration files with the new server public key. All existing clients will need to reconnect with updated configs. This is a disruptive but straightforward process.