All articles
Guides

Personal WireGuard VPN: set it up on your own VPS

In short

A personal WireGuard VPN takes 20-30 minutes to set up on a VPS: install the wireguard package, generate keys with wg genkey, describe the tunnel in /etc/wireguard/wg0.conf with address 10.8.0.1/24 and port 51820, enable packet forwarding and NAT, open 51820/udp and run systemctl enable --now wg-quick@wg0. A phone connects by scanning a QR code, and the smallest plan is enough for one or two people.

Key takeaways
  • WireGuard is a VPN protocol built into the Linux kernel since 5.6: on an Ubuntu or Debian VPS it installs with sudo apt install wireguard and is configured in a single file, /etc/wireguard/wg0.conf.
  • A WireGuard server listens on UDP port 51820 by default; that is the only port to open in the firewall - sudo ufw allow 51820/udp.
  • To route all of a client's traffic through the VPS, the server enables net.ipv4.ip_forward=1 and NAT (iptables MASQUERADE), and the client config sets AllowedIPs = 0.0.0.0/0.
  • A WireGuard config moves to a phone as a QR code: qrencode -t ansiutf8 < phone.conf draws it right in the terminal for the official WireGuard app to scan.
  • A personal VPN for one or two people fits a VPS with 1 vCPU and 2 GB of RAM - on Tihost such a server costs $4.00 a month.

Why run your own VPN on a VPS?

  • A secure connection on public Wi-Fi - in a cafe, hotel or airport all your traffic travels to your own server inside an encrypted tunnel;
  • access to your own services - admin panels, databases and monitoring can be closed to the internet and opened only to the VPN network 10.8.0.0/24;
  • access to your home network - a home router or mini server joins the same VPS as one more client, and you reach it from anywhere;
  • a fixed IP - work systems, panels and firewalls only need one public IPv4 address, the server's, in their allowlists.

WireGuard is simpler than OpenVPN and IPsec: the config is a dozen lines, keys are short strings much like SSH keys, and the connection recovers on its own when the network changes, for example when you move from Wi-Fi to mobile data. Protocol details are at wireguard.com.

What server does WireGuard need?

WireGuard runs in the kernel and barely touches the CPU, so the smallest Starter configuration - 1 vCPU and 2 GB of RAM for $4.00 a month - is enough for one or two people. What matters is that the VPS uses full KVM virtualization with its own kernel - on Tihost it does. Pick a location close to you: the lower the latency to the server, the less noticeable the VPN. Comparing Germany, Finland and Poland is covered in the guide to choosing a VPS location.

Step 1. Install WireGuard

The wireguard package installs the wg and wg-quick tools, qrencode is needed for the QR code, and iptables for NAT (a minimal Debian 12 install may not have it):

bash
sudo apt update
sudo apt install -y wireguard qrencode iptables

Step 2. Generate server and client keys

Each side of the tunnel has a key pair: the private key stays with its owner, and the public key goes to the other side. umask 077 makes new files readable by root only. The last command prints the keys - you will need them in the configs:

bash
sudo -i
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee phone.key | wg pubkey > phone.pub
cat server.key server.pub phone.key phone.pub

Step 3. Create the server config wg0.conf

First find the name of the external network interface - it follows the word dev in the default route. It is often eth0 or ens3:

bash
ip route list default
# default via 203.0.113.1 dev eth0 proto static

Create /etc/wireguard/wg0.conf and fill in the keys. If the interface is not called eth0, replace it in the PostUp and PostDown lines. PostUp allows packet forwarding and enables NAT (MASQUERADE) when the tunnel starts, so clients reach the internet with the server's IP; PostDown removes those rules when it stops:

/etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of server.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

[Peer]
# phone
PublicKey = <contents of phone.pub>
AllowedIPs = 10.8.0.2/32

Step 4. Enable packet forwarding

By default Linux does not forward packets between interfaces, so client traffic would stop at the server. net.ipv4.ip_forward=1 turns forwarding on, and the file in /etc/sysctl.d/ keeps it after a reboot:

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

Step 5. Open port 51820/udp

WireGuard runs over UDP, and the server only needs the ListenPort port open to the outside. WireGuard does not answer packets without a valid key, so a port scanner cannot tell a VPN is running on the server:

bash
sudo ufw allow 51820/udp
sudo ufw status

Step 6. Start the tunnel

wg-quick@wg0 is a systemd service that brings up the wg0 interface from the config and starts at boot. wg show should list the interface, port 51820 and one peer - the phone:

bash
sudo systemctl enable --now wg-quick@wg0
sudo wg show

Step 7. Prepare the client config

The client config mirrors the server's: its own private key, the server's public key and the server address in Endpoint (put in your VPS IP). AllowedIPs = 0.0.0.0/0 sends all IPv4 traffic into the tunnel, DNS sets the DNS server while connected, and PersistentKeepalive = 25 sends a packet every 25 seconds so the connection survives the NAT of a home router or mobile carrier:

phone.conf
[Interface]
PrivateKey = <contents of phone.key>
Address = 10.8.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <contents of server.pub>
Endpoint = 203.0.113.10:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

If the VPN is only for reaching your own services rather than all traffic, set AllowedIPs = 10.8.0.0/24 - then only VPN network addresses go through the tunnel.

Step 8. Move the config to your phone with a QR code

Save the client config on the server as /etc/wireguard/phone.conf and print it as a QR code right in the terminal. In the WireGuard app for Android or iOS tap the + button and choose to scan a QR code; on a computer, import the config as a file:

bash
sudo nano /etc/wireguard/phone.conf
sudo qrencode -t ansiutf8 < /etc/wireguard/phone.conf

Step 9. Check the connection

Turn the tunnel on in the app and run wg show on the server: the peer should now show a latest handshake line with the time of the last handshake and a transfer line with the traffic volume. Any IP-check service on the phone should show your VPS address:

bash
sudo wg show

If there is no handshake, check that port 51820/udp is open in UFW and that Endpoint has the right IP. If there is a handshake but websites do not load, check ip_forward and the interface name in PostUp.

How to add another device

Generate a separate key pair for each device, add a new [Peer] block to wg0.conf with the next address (10.8.0.3/32, 10.8.0.4/32 and so on) and restart the tunnel. Do not share one config between devices: two clients with the same key keep knocking each other off.

bash
sudo nano /etc/wireguard/wg0.conf
sudo systemctl restart wg-quick@wg0
Launch a server in 2 minutes

AMD Ryzen 9, NVMe and DDoS protection in Germany, Finland and Poland. Pay with crypto or card.

Order a Server

FAQ

Which port does WireGuard use?

WireGuard uses UDP port 51820 by default - it is set by ListenPort in the server config. That is the only port to open in the firewall: sudo ufw allow 51820/udp.

How many resources does a VPS need for WireGuard?

WireGuard runs in the Linux kernel and puts almost no load on the server: a personal VPN for several devices fits a VPS with 1 vCPU and 2 GB of RAM. On Tihost that configuration costs $4.00 a month.

How is WireGuard different from OpenVPN?

WireGuard is simpler to set up - a dozen-line config and SSH-style keys - runs in the Linux kernel and quickly recovers when the network changes. OpenVPN is older, runs in user space and is more flexible, but more complex.

Why does WireGuard connect but the internet does not work?

Most often packet forwarding is off on the server (net.ipv4.ip_forward=1) or the MASQUERADE rule names the wrong network interface. ip route list default shows the interface name - it follows the word dev.

How do I connect a phone to WireGuard?

Save the client config on the server and run qrencode -t ansiutf8 < phone.conf - a QR code appears in the terminal. In the WireGuard app for Android or iOS choose to add a tunnel by scanning a QR code.

Can WireGuard carry only part of my traffic?

Yes. Set AllowedIPs = 10.8.0.0/24 instead of 0.0.0.0/0 in the WireGuard client config - then only VPN network addresses go through the tunnel and everything else goes direct.