How to Set Up Your Own VPN on a VPS (WireGuard): A Complete Step-by-Step Guide

How to Set Up Your Own VPN on a VPS (WireGuard): A Complete Step-by-Step Guide

This guide shows how to deploy a private, full-featured VPN on your own VPS so you can route internet traffic from multiple devices (phone, laptop, PC, router) through your server. You’ll pay only for the VPS and avoid ongoing VPN subscriptions.

We’ll focus on WireGuard, the modern VPN standard known for speed, stability, and simplicity. By the end, you’ll have a working VPN with client profiles for iOS/Android/Windows/macOS/Linux.

What You Will Get

  • A private VPN server running on your VPS
  • Client profiles for all common devices
  • Full-tunnel VPN routing (all traffic exits via your VPS IP)
  • Easy onboarding via QR codes for mobile devices
  • A clean approach that doesn’t require extra paid services

Option Overview

  • Option A (Recommended): WireGuard — fastest, modern, lightweight.
  • Option B (Alternative): OpenVPN — widely compatible, but typically slower and heavier.

If you want maximum performance and minimal cost, choose WireGuard.


1) Choose a VPS (Minimum Requirements)

WireGuard runs on even a basic VPS:

  • CPU: 1 vCPU
  • RAM: 1 GB recommended (512 MB may work)
  • Disk: 10 GB is enough
  • OS: Ubuntu 22.04 LTS or Debian 12
  • Network: Ensure UDP is allowed (we’ll use port 51820/UDP)

For best speed, pick a VPS location geographically close to where you usually connect from.

2) Connect to Your Server and Update the System

Step 2.1 — SSH into the VPS

Replace YOUR_SERVER_IP with your VPS public IP address.

ssh root@YOUR_SERVER_IP

Step 2.2 — Update packages

apt update && apt upgrade -y

Step 2.3 — Install useful utilities

apt install -y curl wget nano qrencode ufw

3) Enable IP Forwarding (Required)

The VPS must forward packets between the VPN interface and the public internet.

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p

Verify forwarding is enabled:

sysctl net.ipv4.ip_forward

You should see:

net.ipv4.ip_forward = 1

4) Install WireGuard

apt install -y wireguard

Verify installation:

wg --version

5) Generate WireGuard Server Keys

WireGuard uses public-key cryptography. We’ll generate keys under /etc/wireguard.

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

View the keys:

cat server_private.key
cat server_public.key

6) Create the WireGuard Server Config (wg0)

We’ll create an interface named wg0 with a private subnet 10.8.0.0/24.

nano /etc/wireguard/wg0.conf

Paste the following configuration, then replace the placeholders.

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

# NAT + forwarding rules (adjust interface name if needed)
PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT

PostDown = ufw route delete allow in on wg0 out on eth0
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT

Replace SERVER_PRIVATE_KEY_HERE with:

cat /etc/wireguard/server_private.key

Important: Detect your actual public interface name

Many VPS use eth0, but yours could be ens3, ens160, etc.
Find the default route:

ip route | grep default

Example output:

default via 192.168.1.1 dev ens3

If your interface is ens3, replace eth0 with ens3 in the config.


7) Configure Firewall (UFW) and Open WireGuard Port

Allow SSH and the WireGuard UDP port. Then enable UFW.

ufw allow OpenSSH
ufw allow 51820/udp
ufw enable

Check status:

ufw status

8) Start and Enable WireGuard

systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

Check the service status:

systemctl status wg-quick@wg0 --no-pager

Show WireGuard runtime info:

wg show

9) Create Your First Client (client1)

Each device gets a unique key pair and a unique VPN IP.
We’ll use 10.8.0.2 for client1.

Step 9.1 — Generate client keys

cd /etc/wireguard
wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Step 9.2 — Add client peer to the server

Get the client public key:

cat /etc/wireguard/client1_public.key

Edit server config:

nano /etc/wireguard/wg0.conf

Add this to the bottom:

[Peer]
PublicKey = CLIENT1_PUBLIC_KEY_HERE
AllowedIPs = 10.8.0.2/32

Apply changes without downtime:

wg syncconf wg0 <(wg-quick strip wg0)

Step 9.3 — Create the client config file

nano /etc/wireguard/client1.conf

Paste and replace placeholders:

[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY_HERE
Address = 10.8.0.2/24
DNS = 1.1.1.1, 8.8.8.8

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

Fill values:

  • CLIENT1_PRIVATE_KEY_HERE from:
cat /etc/wireguard/client1_private.key
  • SERVER_PUBLIC_KEY_HERE from:
cat /etc/wireguard/server_public.key
  • YOUR_SERVER_IP = your VPS public IP

10) Add the VPN Profile to Your Devices

Mobile (iOS / Android) via QR code

Generate a QR code from the client config:

qrencode -t ansiutf8 < /etc/wireguard/client1.conf

Open the WireGuard app → Add TunnelCreate from QR code → scan.

Windows / macOS

Install WireGuard, then import the client1.conf file:
you can copy it via SSH or use SCP.

Example SCP (from your local machine):

scp root@YOUR_SERVER_IP:/etc/wireguard/client1.conf .

Linux

Install and bring up the tunnel:

sudo apt install -y wireguard
sudo wg-quick up ./client1.conf

11) Verify the VPN Works

After connecting, check your public IP address:

  • Open a site like ipinfo.io or whatismyipaddress.com
  • Your IP should match your VPS IP

On the server, you can also watch peers:

wg show

12) Add More Devices (client2, client3, …)

Repeat the same process:

  1. Generate keys for a new client
  2. Assign next IP: 10.8.0.3, 10.8.0.4, etc.
  3. Add a new [Peer] on the server
  4. Create a new client config and import it on the device

Example IP mapping:

  • client2: 10.8.0.3/32
  • client3: 10.8.0.4/32
  • client4: 10.8.0.5/32

13) Security Hardening (Highly Recommended)

Use SSH keys (disable password login)

On your local machine:

ssh-keygen

Copy key to server:

ssh-copy-id root@YOUR_SERVER_IP

Edit SSH configuration:

nano /etc/ssh/sshd_config

Set:

PasswordAuthentication no

Restart SSH:

systemctl restart ssh

This blocks password brute-force attacks and is one of the best security improvements you can make.


14) Common Problems and Fixes

Problem: VPN connects, but there is no internet access

Check IP forwarding:

sysctl net.ipv4.ip_forward

Ensure NAT exists:

iptables -t nat -L -n -v

Also verify you used the correct public interface name in the server config (eth0 vs ens3, etc.).

Problem: WireGuard service fails to start

Bring the interface up manually to see errors:

wg-quick up wg0

Problem: Mobile connects, but websites don’t load

Try changing DNS in the client config:

DNS = 1.1.1.1

Or:

DNS = 9.9.9.9

Problem: VPS provider blocks UDP

Some providers restrict UDP. You can try using a different UDP port like 443:

# In /etc/wireguard/wg0.conf
ListenPort = 443

Then allow it in firewall:

ufw allow 443/udp

15) Optional Improvements

Use a Domain Instead of an IP

Point a domain (e.g., vpn.example.com) to your VPS IP and update the client endpoint:

Endpoint = vpn.example.com:51820

Split Tunneling (Advanced)

If you don’t want all traffic through VPN, change the client AllowedIPs.
Full tunnel:

AllowedIPs = 0.0.0.0/0, ::/0

Split tunnel (only access VPN subnet):

AllowedIPs = 10.8.0.0/24

Running your own VPN on a VPS using WireGuard is one of the most cost-effective and reliable ways
to get a private VPN for all your devices. You’ll avoid recurring VPN subscriptions and keep full control
of your traffic and IP.

Next steps you may want:

  • Set up a web UI like wg-easy (client creation in 1 click)
  • Deploy multiple VPN servers in different countries and switch between them
  • Route only specific apps/devices through VPN
© All Right Reserved 2019-2020 futuredesktop.org