WireGuard VPN between VPS and PC
Generate keys, wg0.conf on both sides, firewall, and forwarding only if you want to reach the internet through it.
5 min read
On this page
WireGuard connects your PC and your VPS through an encrypted tunnel. You can then reach services on the server that should not be open to the internet (database, admin interfaces) via a private address.
Covers Debian 12 and 13, Ubuntu 22.04 and 24.04, AlmaLinux 9 and Rocky Linux 9 on the server. On the PC, use the official WireGuard app from https://www.wireguard.com/install/ (Windows, macOS, Linux, Android, iOS). Server commands run as root.
We use this small network:
| Device | Tunnel address |
|---|---|
| VPS | 10.8.0.1 |
| PC | 10.8.0.2 |
Install
Debian and Ubuntu:
apt update
apt install -y wireguard-toolsAlmaLinux and Rocky Linux:
dnf install -y wireguard-toolsThe kernel module is already included on all these systems.
Generate keys
On the server:
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub
cat server.pubserver.key is secret and stays on the server. server.pub is the public key; the PC gets that one.
On the PC: in the WireGuard app, Add Tunnel → Add empty tunnel (Windows) or "Create from scratch". The app generates the private key itself and shows the public key. On Linux, use the same commands as on the server (client.key, client.pub).
Server: wg0.conf
Create /etc/wireguard/wg0.conf. PrivateKey is the content of server.key, PublicKey is the PC's public key:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = CONTENT-OF-server.key
[Peer]
# My PC
PublicKey = PUBLIC-KEY-OF-THE-PC
AllowedIPs = 10.8.0.2/32PC: tunnel configuration
In the app (or on Linux in /etc/wireguard/wg0.conf). The app has already filled in PrivateKey. Endpoint is your VPS's IPv4 from the dashboard (Network tab):
[Interface]
PrivateKey = PRIVATE-KEY-OF-THE-PC
Address = 10.8.0.2/24
[Peer]
PublicKey = CONTENT-OF-server.pub
Endpoint = YOUR-SERVER-IP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25AllowedIPs = 10.8.0.0/24 means only traffic to the tunnel network goes through the tunnel; everything else goes straight to the internet as usual. PersistentKeepalive keeps the connection open when your PC sits behind a router with NAT.
Firewall and start
Open UDP 51820 on the server.
Debian and Ubuntu with ufw:
ufw allow 51820/udpAlmaLinux and Rocky Linux with firewalld:
firewall-cmd --permanent --add-port=51820/udp
firewall-cmd --reloadStart the tunnel on the server and bring it up on boot:
systemctl enable --now wg-quick@wg0On the PC, click Activate in the app (Linux: wg-quick up wg0).
Check that it worked
On the server:
wg showThe peer should show a latest handshake a few seconds ago and transfer data in both directions.
From the PC:
ping 10.8.0.1If the ping works, the tunnel is up. Services that listen only on 10.8.0.1 on the server can now only be reached through the tunnel.
Only if needed: route all traffic through the VPS
If you want your PC to reach the internet via the VPS (e.g. on public Wi-Fi), the server needs forwarding and NAT. For simple access to the server you do not need this; skip it then.
-
Enable forwarding:
bashecho 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-wireguard.conf sysctl --system -
Find the name of the network interface the server uses for the internet (after
dev):baship route show default -
Set up NAT.
Debian and Ubuntu: add this under
[Interface]in/etc/wireguard/wg0.conf, replacingeth0with your interface name:iniPostUp = nft add table ip wg-nat; nft add chain ip wg-nat post '{ type nat hook postrouting priority 100; }'; nft add rule ip wg-nat post oifname "eth0" ip saddr 10.8.0.0/24 masquerade PostDown = nft delete table ip wg-natIf the
nftcommand is missing, install it withapt install -y nftables.If you use
ufw, also allow forwarding:ufw route allow in on wg0 out on eth0.AlmaLinux and Rocky Linux with
firewalld:bashfirewall-cmd --permanent --zone=public --add-masquerade firewall-cmd --permanent --zone=trusted --add-interface=wg0 firewall-cmd --reload -
On the PC, set
AllowedIPs = 0.0.0.0/0and add a DNS server, e.g.DNS = 1.1.1.1under[Interface]. -
On the server run
systemctl restart wg-quick@wg0, on the PC reactivate the tunnel.
Check: on the PC, a page like https://ifconfig.co now shows your VPS's IPv4.
Common errors
- No handshake. UDP 51820 is closed, the server IP in
Endpointis wrong, or the public keys are swapped. Each side enters the public key of the other side under its peer. - Handshake yes, ping no. The addresses do not match
AllowedIPs. The server needs10.8.0.2/32for the peer, the PC10.8.0.0/24. wg-quickreports "Line unrecognized". A typo inwg0.conf, often a missing=.- With
0.0.0.0/0nothing reaches the internet. Forwarding or NAT is missing on the server, or the interface name in thePostUpline is wrong. - The tunnel is gone after a server reboot. You forgot
systemctl enable wg-quick@wg0.
What next
- Each additional device gets its own
[Peer]block with its own address, e.g.10.8.0.3/32. - Make the database reachable only through the tunnel: Set up MariaDB.
If you get stuck, open a ticket.