WireGuard is a few hundred lines of kernel code and two small config files, and the whole setup takes about fifteen minutes once you know which port to open. The part that actually trips people up on a budget VPS is not WireGuard at all — it is that the port you tell WireGuard to listen on has to be one the provider already forwards to you.
What WireGuard actually is
WireGuard is not a service you install and forget about; it is a network interface. The kernel module has shipped in mainline Linux since version 5.6, so on Ubuntu 24.04 it is already part of the kernel you booted — there is no dkms build, no compiling against headers, nothing to break on a kernel update. What you install is wireguard-tools, which gives you two commands: wg, for keys and status, and wg-quick, which reads a config file and brings the interface up or down as a single unit.
That simplicity is also the constraint. There is no built-in dashboard, no user accounts, and no bandwidth graph. Every peer, on either end, is one public key and one line of config. Getting comfortable editing a text file by hand is the whole job.
Read this before you buy: the NAT IPv4 port catch
Cheap VPS plans very commonly give you NAT IPv4 — one shared public address with a small, fixed set of forwarded ports — rather than an address that is yours alone. That is fine for outbound connections, which is all a WireGuard client ever makes. It matters the moment your VPS is the WireGuard server, because a server has to accept an inbound connection on a specific UDP port, and behind NAT you cannot just pick 51820 because a guide told you to.
The rule is simple once you know it: ListenPort in your server config must be set to one of the ports your provider actually forwards to your machine, and the client's Endpoint must use that same port. Pick a random port instead and the tunnel will look correctly configured on both ends and simply never connect, because the packets never reach your VPS in the first place.
Two ways through it:
-
Use one of the forwarded ports you already have. WireGuard does not care what number it runs on, so point
ListenPortat whichever forwarded port is free and move on. - Get a dedicated IPv4. With an address of your own, any port is yours to open, including the WireGuard default. On our plans a dedicated IPv4 is available on request by e-mail, not as a self-service add-on.
Read NAT IPv4 vs a dedicated IP and NAT IPv4, ports and forwarding before you order if you are not sure which situation you are in.
Step 1: a clean machine
Deploy an Ubuntu 24.04 LTS VPS, then do the boring security work before anything is exposed to the internet: a non-root user, your SSH key on it, password login switched off, and a firewall that defaults to deny. We walk through that in connect to your VPS over SSH and secure your VPS.
Note the forwarded UDP port range or list from your provider's panel before you go further — you need an actual number for the next step, not a placeholder.
Step 2: install WireGuard and generate keys
sudo apt update
sudo apt install -y wireguard
That pulls in wireguard-tools; the kernel side is already present. Installing it also creates /etc/wireguard owned by root with mode 0700, so your regular sudo user cannot cd into it or write a key there — generate the server's key pair as root, with a strict umask so the private key is never briefly world-readable:
sudo -i
cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
exit
Do the whole block in one root shell rather than prefixing each line with sudo — sudo does not inherit the umask 077 you just set, so a command like sudo tee can still create the key file with its own default, more permissive mode even though the umask line ran.
Generate a second pair for the client the same way, on whichever machine will hold it — it does not have to be the server. Keep the two private keys apart; only the matching public key ever leaves its own side.
Step 3: the server config, routing and NAT
Create /etc/wireguard/wg0.conf, using one of your forwarded ports for ListenPort:
[Interface]
PrivateKey = <server_private.key contents>
Address = 10.66.66.1/24
ListenPort = 41194
PostUp = iptables -t nat -A POSTROUTING -o <WAN_INTERFACE> -j MASQUERADE; iptables -A FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o <WAN_INTERFACE> -j MASQUERADE; iptables -D FORWARD -i wg0 -j ACCEPT
[Peer]
PublicKey = <client public key>
AllowedIPs = 10.66.66.2/32
Replace <WAN_INTERFACE> with your real outbound interface name, not eth0. Find it first:
ip -brief link
This is the thing that bites later: most published examples hardcode eth0, but plenty of KVM images come up as ens3, enp1s0 or similar. Get the name wrong and the tunnel connects fine, wg show looks healthy, and the client still has no internet through it, because the MASQUERADE rule silently applies to an interface that does not exist.
Turn on IP forwarding and make it survive a reboot:
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
Step 4: firewall, and the port that has to match
Open the same forwarded port, over UDP, and nothing else new:
sudo ufw allow 41194/udp
WireGuard is UDP end to end. A rule that opens the port as TCP by mistake produces the same symptom as picking a non-forwarded port: everything looks configured and nothing arrives. If you change the listen port later, update it in three places at once — the config file, the firewall rule, and every client's Endpoint — or you will spend ten minutes debugging a mismatch you made yourself five minutes earlier.
If you followed Step 1's advice and have ufw running, there is a second gate to check: ufw ships with DEFAULT_FORWARD_POLICY="DROP" in /etc/default/ufw, which blocks exactly the routed, NAT'd traffic this tunnel exists to move, regardless of the port being open. Edit that file, set DEFAULT_FORWARD_POLICY="ACCEPT", and run sudo ufw reload before you test a client — leave it on DROP and the handshake still completes and wg show still looks healthy, but the client has no internet through the tunnel.
Step 5: one client config
This is the entire client side, for the official WireGuard app on any platform or for wg-quick on another Linux box:
[Interface]
PrivateKey = <client private key>
Address = 10.66.66.2/32
DNS = 1.1.1.1
[Peer]
PublicKey = <server_public.key contents>
Endpoint = 203.0.113.10:41194
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Replace 203.0.113.10 with your VPS's public NAT IPv4 address and 41194 with the forwarded port from Step 3. AllowedIPs = 0.0.0.0/0 routes all of the client's traffic through the tunnel, which is what most people mean by "my own VPN" — narrow it to specific subnets if you only want the tunnel for part of your traffic. PersistentKeepalive = 25 matters specifically because the client usually sits behind its own NAT (a home router, a phone on mobile data); without it, that NAT's connection tracking entry expires during idle periods and the server cannot reach the client until it sends something first.
Keeping it running
Bring the interface up and enable it for every future boot in one command:
sudo systemctl enable --now wg-quick@wg0
Check it with sudo wg show, which lists the peer, the last handshake time and the bytes moved in each direction — a peer with no handshake ever recorded means the packets are not arriving, which sends you back to Step 3's interface name or Step 4's port. sudo systemctl status wg-quick@wg0 and journalctl -u wg-quick@wg0 cover the rest.
There is no key rotation schedule to maintain and no update service running that needs restarting on a cadence — WireGuard's attack surface is deliberately small. The two things actually worth a recurring check: that wireguard-tools picks up routine security updates with the rest of the system (sudo apt update && sudo apt upgrade), and that nothing in your provider's panel changes which ports are forwarded to you, since that is the one setting this whole guide hangs off.
What a VPN in Dallas or Charlotte does and does not hide
Our machines run in Dallas, TX and Charlotte, NC, so a WireGuard server there gives you a US exit address — sites you visit see that VPS's IP, not your home or mobile connection's. Inside the tunnel, your local network operator, your ISP and anyone else between you and the VPS sees only encrypted WireGuard packets to one UDP port; they cannot read what is inside them or which sites you are actually visiting.
What it does not do is anonymise you. Any site you log into still recognises you as you, regardless of which IP address you arrive from. Browser fingerprinting is unaffected — cookies, canvas fingerprinting and account sessions do not care what your network path looks like. Your traffic's final destination is also visible to the operator of that VPS, because unlike a multi-hop system such as Tor, this is a single hop: your ISP no longer sees your browsing, but something has to terminate the tunnel and see the traffic in cleartext before it goes onward, and that something is your own VPS. Geolocation-wise, expect exactly one change: sites that check IP location will place you in Texas or North Carolina, and a few services that treat datacentre address ranges differently from residential ones may notice that too.
On overnight.host
Full disclosure: this is what we sell. A 1 vCPU, 1 GiB Starter runs a personal WireGuard tunnel without noticing it; move up a tier only once you are pushing serious throughput or running several always-on tunnels off the same box.
Linux KVM VPS — EUR 4.99 to EUR 59.99 a month, on our own single-tenant bare metal in Dallas, TX and Charlotte, NC. Full hardware virtualisation (KVM), your own kernel, full root. Six tiers, vps-starter to vps-ultra. Starter is 1 vCPU, 1 GiB RAM, 25 GB disk.
You order in the shop, pay by card (Stripe) or SEPA bank transfer, and your login details are e-mailed to you once the service is set up. Support is e-mail, run by one person, with no guaranteed response time. All prices are final totals under the German small-business rule (§19 UStG); no VAT is added or shown.
Order vps-starter → · Linux KVM VPS overview
FAQ
Do I need a dedicated IPv4 to run WireGuard?
No. NAT IPv4 works fine as a WireGuard server as long as ListenPort in your config is one of the ports your provider forwards to you, and every client's Endpoint uses that same port. A dedicated IPv4 only becomes useful if you want to run more services than you have forwarded ports for, or want the default port specifically.
Why does my tunnel show as configured but nothing connects?
The two most common causes are a ListenPort that is not actually forwarded to your VPS, and a firewall rule opened as TCP instead of UDP. Check sudo wg show for a peer with no recorded handshake — that confirms packets are not arriving at all, which points at the port rather than at routing or keys.
Can I run more than one client?
Yes. Add one [Peer] block per client to the server config, each with its own public key and its own /32 address inside your chosen subnet, then reload with sudo wg syncconf wg0 <(wg-quick strip wg0) or a restart of the service. Every client keeps its own private key; only public keys go on the server.
Does WireGuard hide what I do from my VPS provider?
No. The VPS is where your tunnel ends and your traffic goes back onto the open internet in cleartext, so whoever controls that machine could, in principle, see it — the same is true of any VPS you use for anything. What the tunnel does hide is your traffic from your local network and your ISP between your device and that VPS.
How much does WireGuard cost to run?
Nothing beyond the VPS itself. It is a kernel feature and a command-line tool, both free, with no license and no per-peer fee. A personal tunnel for one or two people idles well inside a 1 GiB Starter; sizing up only matters once you are pushing meaningful throughput through it continuously.
Written by the person who runs overnight.host: a small, honest hosting company on dedicated bare metal — Linux VPS, game servers, web hosting. Live status at up.overnight.host.
Originally published at overnight.host — the canonical, kept-current version of this guide.
Top comments (0)