How to Set Up a WireGuard VPN on Your VPS

Written by the ApexVPS team • Last updated: July 2026 • 9 min read

This WireGuard VPS setup tutorial shows you how to build your own private, fast, and modern VPN on an Ubuntu or Debian server. WireGuard is a lightweight VPN protocol baked into the Linux kernel, so it is dramatically simpler than OpenVPN or IPsec while still delivering strong, up-to-date cryptography. By the end you will have a running server, at least one connected client, and full control over your own encrypted tunnel — no third-party VPN subscription required.

Running WireGuard on your own machine means the traffic terminates on hardware you rent, not on a crowded consumer VPN endpoint. If you want a deeper look at why a private box is the better base for this, read our guide on choosing a VPS for a personal VPN before you begin.

What you need before you start

A stable, uncontended endpoint matters for a VPN, which is why truly dedicated resources beat oversold shared hosting. A dedicated IPv4 is available on ApexVPS Business and Enterprise plans, giving your tunnel an address that is not shared with anyone else.

Step 1: Update the system and install WireGuard

Start by refreshing the package index and installing the WireGuard userspace tools. On a modern kernel this is the only package you need.

sudo apt update
sudo apt install wireguard -y

This installs wg and wg-quick, the two commands that manage keys, interfaces, and configuration. You can confirm the install with wg --version.

Step 2: Generate the server keys

WireGuard authenticates peers with a public/private key pair, much like SSH. Move into the config directory, tighten the file permissions with umask, and generate the keys in one step.

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

The umask 077 line ensures the private key is readable only by root. Print the two values so you can paste them into the config that follows.

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

Keep the private key secret. Anyone who holds it can impersonate your server.

Step 3: Create the server config (wg0.conf)

The server interface is described in a single file, /etc/wireguard/wg0.conf. Create it with your editor of choice:

sudo nano /etc/wireguard/wg0.conf

Paste the block below, replacing <SERVER_PRIVATE_KEY> with the private key from Step 2 and eth0 with your real interface name if it differs.

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>

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

Here 10.8.0.1/24 is the private VPN subnet, 51820/udp is the listening port, and the PostUp/PostDown rules add and remove NAT so client traffic is masqueraded out through the server's public interface. To find your interface name, run:

ip route list default

The word after dev in the output (often eth0, ens3, or enp1s0) is the interface to use in the two firewall lines above.

Step 4: Enable IP forwarding and NAT

By default Linux will not route packets between interfaces, so the kernel must be told to forward. Enable it persistently with a sysctl drop-in file.

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf

If you also route IPv6 through the tunnel, add net.ipv6.conf.all.forwarding = 1 to the same file. The MASQUERADE rule from Step 3 handles the NAT itself, so once forwarding is on the routing path is complete.

Open the firewall port

Allow the WireGuard UDP port. If you use ufw, run the following, and be sure to keep SSH open so you do not lock yourself out.

sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable

If you manage rules directly with iptables instead of ufw, the PostUp lines already add the forwarding and NAT rules; you only need to make sure inbound UDP 51820 is permitted by any host firewall or provider security group.

Step 5: Start WireGuard with systemd

wg-quick ships with a systemd service template, so you can start the tunnel now and have it come back automatically after a reboot.

sudo systemctl enable --now wg-quick@wg0
sudo systemctl status wg-quick@wg0

The enable --now flag both starts the interface and sets it to launch at boot. A quick sanity check confirms the interface is up:

sudo wg show

You should see a wg0 interface with your public key and listening port. There are no peers yet — that is the next step.

Step 6: Add a client (peer)

Each device that connects is a peer with its own key pair. Generate a key pair for your first client:

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

Now register the client on the server. Append a [Peer] block to /etc/wireguard/wg0.conf, using the client's public key and the next free address in the VPN subnet.

[Peer]
PublicKey = <CLIENT1_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32

Reload the interface so the new peer takes effect:

sudo systemctl restart wg-quick@wg0

Prefer not to drop the tunnel? You can hot-add the peer without a restart:

sudo wg set wg0 peer <CLIENT1_PUBLIC_KEY> allowed-ips 10.8.0.2/32

Step 7: Build the client config and a QR code

On the server, assemble the client configuration file. This is what the device — a laptop or phone — will load. Replace the placeholders with the client's private key and the server's public key and public IP.

[Interface]
PrivateKey = <CLIENT1_PRIVATE_KEY>
Address = 10.8.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP>:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Setting AllowedIPs = 0.0.0.0/0, ::/0 routes all of the client's traffic through the tunnel — the classic full-VPN behaviour. PersistentKeepalive = 25 keeps the connection alive through NAT and firewalls. Save this as client1.conf.

For a desktop, copy client1.conf to the machine and import it into the official WireGuard client. For a phone, render the file as a scannable QR code directly in the terminal:

sudo apt install qrencode -y
qrencode -t ansiutf8 < client1.conf

Open the WireGuard app on Android or iOS, choose "Add tunnel" then "Scan from QR code," and the tunnel imports in seconds. The official apps and clients are all linked from wireguard.com.

Step 8: Verify the tunnel

Activate the tunnel on the client, then confirm the handshake on the server. A healthy connection shows a recent handshake and rising transfer counters.

sudo wg show

Look for a latest handshake timestamp and non-zero transfer values under your peer. Finally, verify from the client that your public IP is now the server's IP:

curl ifconfig.me

If that returns the VPS address, your traffic is flowing through the tunnel and the WireGuard VPS setup is complete. To add more devices, repeat Steps 6 and 7 with a fresh key pair and the next address in the 10.8.0.0/24 range.

Troubleshooting a connection that won't come up

If wg show never reports a handshake, work through the usual suspects in order. First, confirm the port is actually open: from another machine run nc -uzv <SERVER_PUBLIC_IP> 51820, and check that your provider's security group or firewall permits inbound UDP 51820, not just TCP. Second, make sure IP forwarding is truly enabled with sysctl net.ipv4.ip_forward — it should return 1. Third, double-check that the interface name in the PostUp NAT rule matches the output of ip route list default; a mismatch is the most common reason traffic authenticates but never reaches the internet. Finally, verify the keys are not swapped: the server config holds the server's private key and the client's public key, while the client config mirrors that arrangement. A single crossed key silently blocks the handshake.

Choosing the right VPS for WireGuard

WireGuard itself is tiny — the protocol barely touches CPU — so even an entry-level plan runs a personal VPN comfortably. What actually shapes the experience is the network: bandwidth, latency to your region, and whether the IP is yours alone. ApexVPS runs on truly dedicated vCPU, RAM, and NVMe storage across 39 locations, with low latency in major regions, so throughput stays predictable instead of sagging under noisy neighbours.

If you want the tunnel to live on a stable, unshared address, a dedicated IPv4 is included on the Business and Enterprise plans. And because privacy tends to be the whole point of self-hosting a VPN, it is worth noting how you sign up: ApexVPS is a no-KYC VPS with email-only signup and crypto-only checkout through OxaPay, accepting Bitcoin, Ethereum, USDT, and 30+ cryptocurrencies — no name, address, credit card, or bank account required.

Frequently asked questions

Is WireGuard hard to set up on a VPS?

No. WireGuard uses a small, readable configuration file and a handful of standard commands. On a fresh Ubuntu or Debian VPS you can install it, generate keys, write wg0.conf, and connect your first client in roughly ten to fifteen minutes.

Do I need a dedicated IP for a WireGuard VPN?

A dedicated IP is not strictly required, but it gives your tunnel a stable endpoint that is not shared with other customers. At ApexVPS a dedicated IPv4 is included on the Business plan, with two on Enterprise.

Which Ubuntu and Debian versions support WireGuard?

WireGuard is built into the Linux kernel from version 5.6 onward, so Ubuntu 20.04 and later and Debian 11 and later include it out of the box. You only need to install the userspace tools with apt.

Can I use the same server on my phone?

Yes. Add a second peer for the phone, generate a client config, and render it as a QR code with qrencode. The official WireGuard apps for Android and iOS scan the code and connect instantly.

Can I pay for the VPS without a credit card?

Yes. ApexVPS checkout is crypto-only and accepts Bitcoin, Ethereum, USDT, and 30+ cryptocurrencies. Signup asks only for an email so we can send access details — no name, address, or ID.

Ready to host your own VPN? See why ApexVPS is built for private VPNs →