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_HEREfrom:
cat /etc/wireguard/client1_private.key
SERVER_PUBLIC_KEY_HEREfrom:
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 Tunnel → Create 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:
- Generate keys for a new client
- Assign next IP:
10.8.0.3,10.8.0.4, etc. - Add a new
[Peer]on the server - 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