---
title: "Personal WireGuard VPN: set it up on your own VPS"
description: "How to run your own WireGuard VPN on an Ubuntu or Debian VPS: keys, the wg0.conf config, NAT and forwarding, port 51820/udp and a phone client via QR code."
url: https://tihost.io/en/blog/wireguard-vpn-on-vps
language: en
section: "Guides"
published: 2026-10-05
updated: 2026-10-05
publisher: Tihost (https://tihost.io)
---

# 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.

> Use a VPN in line with the laws of your country. Commands target Ubuntu 22.04/24.04 and Debian 12; do the [first server setup](https://tihost.io/en/blog/vps-first-setup) first and make sure SSH is allowed in UFW.

## 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](https://www.wireguard.com/).

## What server does WireGuard need?

WireGuard runs in the kernel and barely touches the CPU, so the smallest [Starter](https://tihost.io/en/blog/starter-vps) 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](https://tihost.io/en/blog/vps-location-choice).

## 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
```

> The QR code and `phone.conf` contain the client's private key. Do not show them or send them through messengers; once imported, the file can be deleted from the server.

## 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](https://tihost.io/login)

## 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.

---

Updated 2026-10-05 · https://tihost.io/en/blog/wireguard-vpn-on-vps
