How to Set Up Your Own WireGuard VPN on a VPS (Step by Step)

Difficulty: Beginner 9 min read Updated: 18.07.2026 21
How to Set Up Your Own WireGuard VPN on a VPS (Step by Step)
Renting a cheap VPS and turning it into your own WireGuard VPN gives you a private tunnel that nobody else shares - no monthly subscription, no company logging your traffic. This guide walks through the whole process on a fresh Ubuntu server, step by step, with every command you need to copy and paste. No prior server experience required.

What you need before you start

This is the whole shopping list. There is nothing exotic here, and the total cost is a few dollars a month:

  • A cheap VPS (virtual server). The smallest tier - 1 vCPU and 1 GB of RAM - is more than enough for personal use. Choose Ubuntu 22.04 or 24.04 when you create it.
  • The server's public IP address and root (or sudo) SSH access. Your provider emails these right after you pay.
  • An SSH client. On Windows use the built-in ssh in PowerShell or PuTTY, on macOS and Linux just open a terminal.
  • A KVM-based VPS. Almost all plans are, but avoid the very cheapest OpenVZ ones - they share the host kernel and cannot load WireGuard, so this setup will not work there. If in doubt, ask the provider or pick a plan that says "KVM".
  • About 15 minutes.
Why WireGuard: it is the modern VPN protocol - a few hundred lines of code, very fast, and simple to configure. Compared with OpenVPN it connects quicker, drains less battery on mobile, and is far easier to read and audit. That simplicity is exactly why we start here.

Step 1: Connect and update the server

Open your terminal and log in, replacing the address with your server's IP:

ssh root@YOUR_SERVER_IP

The first thing on any fresh server is to install the latest security updates:

apt update && apt upgrade -y

Step 2: Install WireGuard

One command installs WireGuard and qrencode, a small tool we will use later to move the config to your phone as a QR code:

apt install wireguard qrencode -y

Step 3: Generate the server keys

WireGuard uses a private and public key on each side. Create the server pair inside its config directory. The umask 077 makes sure the private key is not readable by other users:

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

Print both keys and keep them handy for the next steps:

cat server_private.key
cat server_public.key

Step 4: Find your network interface

To route your traffic out to the internet, the server needs to know the name of its public network card. Run:

ip route list default

Look at the word right after dev in the output - it is usually eth0 or ens3. Note it down; we will need it in the next step.

Step 5: Create the server config

Create the file /etc/wireguard/wg0.conf (for example with nano /etc/wireguard/wg0.conf) and paste the block below. Replace SERVER_PRIVATE_KEY with the private key from Step 3, and replace eth0 with the interface name from Step 4:

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

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

In plain words: the server takes the address 10.8.0.1 inside a private VPN network, listens on UDP port 51820, and the two iptables lines switch on the masquerading that lets your devices reach the wider internet through it.

Step 6: Turn on IP forwarding

By default Linux does not pass traffic from one interface to another. Turn it on with its own small config file - a clean, repeatable way that will not clash with other settings or pile up if you run it twice:

echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-wireguard.conf
sysctl --system

Step 7: Create a client and add it as a peer

Now generate a key pair for your first device (your laptop or phone):

wg genkey | tee client_private.key | wg pubkey > client_public.key
cat client_private.key
cat client_public.key

Tell the server about this client by adding a [Peer] block to the bottom of /etc/wireguard/wg0.conf. Use the client's public key here:

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

Step 8: Open the firewall and start WireGuard

Allow SSH (so you do not lock yourself out) and the WireGuard port, then enable the firewall:

ufw allow 22/tcp
ufw allow 51820/udp
ufw enable
Check your SSH port first. If your provider put SSH on a non-standard port (not 22), allow that port instead - for example ufw allow 2222/tcp - before you run ufw enable, otherwise the firewall will lock you out of your own server.

Start the tunnel and set it to launch automatically on every reboot:

systemctl enable --now wg-quick@wg0

Check that it is running - you should see the interface and your listening port:

wg show

Step 9: Create the client config

Every device that connects needs a small config file. On the server, create a file named client.conf and fill in CLIENT_PRIVATE_KEY (from Step 7), SERVER_PUBLIC_KEY (from Step 3) and your server's public IP:

[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1

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

The line AllowedIPs = 0.0.0.0/0, ::/0 is what sends all of your traffic through the tunnel. Setting DNS = 1.1.1.1 stops your queries leaking to your local provider. This same client.conf is what you load onto each device below.

Step 10: Install the WireGuard app and connect

WireGuard has a free official app for every platform. There are two ways to load your client.conf: scan a QR code (easiest on phones) or import the file (easiest on computers). To make a QR code, run this on the server and keep the terminal window wide so the code is not distorted:

qrencode -t ansiutf8 < client.conf

Android: install the WireGuard app from Google Play. Open the app, tap the + button, choose Scan from QR code, point the camera at the code in your terminal, give the tunnel a name, then flip the switch to connect.

iPhone and iPad: install the WireGuard app from the App Store. Tap +, choose Create from QR code, scan the code, name the tunnel and toggle it on. Allow the VPN configuration when iOS asks.

Windows: download the app from wireguard.com/install. Copy your client.conf to the PC, open the app, click Import tunnel(s) from file, pick client.conf, then click Activate.

macOS: install the WireGuard app from the Mac App Store. Click Import tunnel(s) from file, select your client.conf, allow the VPN configuration, then click Activate.

Linux desktop: install the package with apt install wireguard (or your distro's equivalent; see wireguard.com/install), copy client.conf to /etc/wireguard/, and bring it up with wg-quick up client. Disconnect with wg-quick down client.

Adding another device? Repeat Step 7 for each new phone or laptop: generate a fresh key pair, give the device the next free address (10.8.0.3/32, then 10.8.0.4/32, and so on), add its own [Peer] block to wg0.conf, and apply the change with systemctl restart wg-quick@wg0. Give every device its own key - never load one config onto two devices at once.

Step 11: Verify the tunnel actually works

Turn the connection on, then confirm two things using our own Network tools page. First, that the internet sees your server's IP and not your home one - the page shows your current IP and country right at the top. Second, open its DNS Leak Test tab and run the check: every resolver it lists should belong to your DNS provider, never your home ISP. If both look right, you have a working private VPN.

Common mistakes

  • Wrong interface name. If eth0 in the config does not match what Step 4 showed, traffic will connect but never reach the internet. This is the number one cause of a "connected but no internet" tunnel.
  • Forgot IP forwarding. Skipping Step 6 produces the same dead-end symptom. Re-run sysctl --system and check cat /proc/sys/net/ipv4/ip_forward returns 1.
  • Provider firewall. Some hosts have their own firewall in a control panel on top of ufw. Make sure UDP 51820 is open there too.
  • Mixed up keys. The server config holds the client's public key; the client config holds the server's public key. Private keys never leave the machine they were made on.
  • IPv6 slipping past. This guide sends IPv6 into the tunnel (::/0) but sets the server up for IPv4 only, so some IPv6-only sites may load slowly or not at all. If that happens, the simplest fix is to turn off IPv6 on the client device, or add IPv6 support on the server later.
  • Clock drift. WireGuard is fine, but if the server clock is badly wrong, TLS to websites breaks. Run timedatectl and enable NTP if needed.

When plain WireGuard is not enough

A self-hosted WireGuard tunnel is excellent for privacy - your traffic is encrypted and tied to a server only you use. But in countries with aggressive censorship it has a weakness: deep packet inspection (DPI) systems can recognise WireGuard traffic by its fingerprint and throttle or drop it, even though they cannot read what is inside. Russia's operators, for instance, have moved to blocking VPNs at the TSPU boxes installed on every network, and regulators there have openly pushed toward total blocking of VPN traffic. If your goal is bypassing that kind of DPI rather than everyday privacy, a protocol that disguises itself as ordinary HTTPS - such as VLESS with Reality - is the better tool. We will cover that setup in a separate guide in this section.

In most of the world, renting a server and running your own VPN on it is completely legal - it is the same technology companies use for remote work. You are, however, responsible for what you do through it: a VPN changes where your traffic appears to come from, it does not put you above the law. A handful of countries restrict or license VPN use, so check the rules where you actually live. And remember the honest limits of self-hosting: your traffic is private from your local network and your ISP, but the company that rents you the VPS can still see that a server at that IP exists and how much data it moves. For most people that trade is well worth it - you get a tunnel nobody else shares, on your terms.

Keep it yours: back up /etc/wireguard/ somewhere safe, never share a private key, and create a separate [Peer] block with its own key pair for each new device instead of reusing one. If a device is lost, you can then revoke just that peer. Once a device is set up, delete the leftover client files from the server so its private key does not sit around: rm client.conf client_private.key.
Going further: want your server to keep no records at all? See our companion guide How to make your VPS keep no logs.
Tags: wireguard vpn vps self-hosted privacy tutorial linux