Skip to content
+1 (813) 212-3723 support@layeronecloud.com
Self-hosting VPS guides

How to set up a WireGuard VPN on a VPS

Configure a WireGuard VPS exit node on Ubuntu with native packages, exact UFW and NAT rules, client keys, realistic sizing, and recovery steps.

8 min read

WireGuard is a small, modern VPN protocol implemented in the Linux kernel. A WireGuard VPS gives laptops and phones an encrypted route to a fixed public IPv4 address, useful on untrusted Wi-Fi or for reaching services that allowlist one address. It does not make a user anonymous, inspect malicious traffic, or replace endpoint security. LayerOne can see the VPS's network usage, and the sites you visit see the VPS address.

This guide creates an IPv4 full-tunnel exit node with native Ubuntu packages. There is no web administration panel, database, Docker socket, or reverse proxy to expose.

WireGuard VPS requirements and LayerOne cost

Item Practical starting point
Minimum RAM 512 MB for a minimal Ubuntu or Debian WireGuard gateway
Recommended RAM 1 GB for package updates, logging, and several personal peers
Expected CPU usage Essentially zero when idle; often 5–30% of one vCPU during light personal use, with sustained high throughput capable of using the full core
Storage requirement About 4 GB minimum for the OS; 10 GB is comfortable when logs are controlled
Exact LayerOne SKU gc.nano — catalog slug layerone-nano, 1 vCPU, 1 GB RAM, 20 GB disk
Expected monthly cost $3.00/month equivalent, metered at $0.0041/hour while the VPS exists

Encryption speed depends on packet size, peer count, CPU scheduling, client hardware, and the route between client and VPS. The figures above are workload estimates, not a throughput promise. Measure with top, wg show, and a test appropriate to your real traffic. Upgrade when the single vCPU remains busy or latency rises under load.

LayerOne charges hourly and transfer usage can vary. Check the current plan and bandwidth terms on Pricing. The 20 GB disk is far more than WireGuard itself needs; the recommended SKU is for RAM and operational headroom.

Before you install

The commands below assume Ubuntu 24.04 LTS and a public IPv4 address. Complete Your first hour on a new server, restrict SSH to a trusted source, and optionally point vpn.example.com to the VPS. These examples use:

  • WireGuard network 10.8.0.0/24;
  • server tunnel address 10.8.0.1;
  • first client address 10.8.0.2; and
  • UDP port 51820.

Choose a different private range if 10.8.0.0/24 overlaps the client's home, office, or another VPN network. LayerOne does not currently provide IPv6, so this guide deliberately configures an IPv4 tunnel only.

1. Install WireGuard and identify the WAN interface

WireGuard is in the Ubuntu package repository:

sudo apt update
sudo apt install -y wireguard qrencode ufw
ip route show default

The last command normally shows a line containing dev ens18, dev eth0, or a similar name. Record that interface. The examples below use ens18; replace it everywhere if your server reports a different name.

2. Generate the server key and a client key

Restrictive umask permissions matter because a WireGuard private key is the peer's identity:

sudo install -d -m 700 /etc/wireguard/keys
sudo sh -c 'umask 077; wg genkey | tee /etc/wireguard/keys/server.key | wg pubkey > /etc/wireguard/keys/server.pub'
sudo chmod 600 /etc/wireguard/keys/*.key
sudo chmod 644 /etc/wireguard/keys/*.pub

Generate each client key on that client whenever possible, so its private key never crosses the VPS. On a Linux client with wireguard-tools installed:

umask 077
wg genkey | tee client-laptop.key | wg pubkey > client-laptop.pub
cat client-laptop.pub

The final command prints a public key. Mobile and desktop WireGuard apps can also generate a key pair and show the public key. Keep every private-key file on its device; never paste it into a ticket, chat, or public terminal recording.

3. Enable IPv4 forwarding

sudo tee /etc/sysctl.d/99-wireguard-forwarding.conf >/dev/null <<'EOF'
net.ipv4.ip_forward=1
EOF
sudo sysctl --system
sysctl net.ipv4.ip_forward

The final value must be 1.

4. Create the server configuration

Build /etc/wireguard/wg0.conf while reading the generated keys directly. This avoids copying a private key through an editor:

SERVER_PRIVATE_KEY=$(sudo cat /etc/wireguard/keys/server.key)
read -r -p "Paste the client's public key: " CLIENT_PUBLIC_KEY
sudo tee /etc/wireguard/wg0.conf >/dev/null <<EOF
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = $SERVER_PRIVATE_KEY
PostUp = iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE

[Peer]
# laptop
PublicKey = $CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
EOF
unset SERVER_PRIVATE_KEY CLIENT_PUBLIC_KEY
sudo chmod 600 /etc/wireguard/wg0.conf
sudo wg-quick strip wg0 >/dev/null

Replace both occurrences of ens18 first if the default-route interface has a different name. The peer receives a single /32; do not give two clients the same tunnel address.

5. Configure the cloud firewall and UFW

In LayerOne's Networking tab, use inbound DROP, outbound ACCEPT, allow TCP 22 from your administration address, and allow UDP 51820 from 0.0.0.0/0. If every peer has a stable address, narrow the UDP rule to those sources. Do not open TCP 51820: WireGuard uses UDP. See The cloud firewall.

Mirror the policy in UFW and explicitly allow forwarded tunnel traffic:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from YOUR.ADMIN.IP.ADDRESS to any port 22 proto tcp
sudo ufw allow 51820/udp
sudo ufw route allow in on wg0 out on ens18
sudo ufw enable
sudo ufw status verbose

Again, substitute the real WAN interface for ens18. If the VPN should reach only specific private services rather than become an internet exit node, omit the MASQUERADE rules, use narrower AllowedIPs, and create only the forwarding rules that design requires.

6. Start WireGuard and enable it at boot

sudo systemctl enable --now wg-quick@wg0
sudo systemctl status wg-quick@wg0 --no-pager
sudo wg show
sudo ss -lunp | grep ':51820'

wg show lists configuration immediately, but a peer gets a latest handshake only after that client sends valid traffic.

7. Create the client profile

Read the server's public key:

sudo cat /etc/wireguard/keys/server.pub

Create this profile on the client that generated client-laptop.key, substituting that local private key, the server's public key, and your hostname:

[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0 makes this a full IPv4 tunnel. For split tunneling, list only networks that should traverse the VPN. PersistentKeepalive = 25 is useful for clients behind NAT; it is not normally needed on the server peer.

Import the configuration into the official WireGuard client. If you deliberately create a QR code from client.conf on a trusted local machine, it displays the private key to anyone who can see or record the terminal. Use it only in a private session and clear the screen:

qrencode -t ansiutf8 < client.conf
clear

8. Verify routing, DNS, and leaks

Bring the tunnel up on the client, then run:

ping -c 3 10.8.0.1
curl -4 https://icanhazip.com

The second command should return the VPS public IPv4. On the server:

sudo wg show
sudo journalctl -u wg-quick@wg0 -n 50 --no-pager
sudo iptables -t nat -S POSTROUTING

Confirm a recent handshake and increasing transfer counters. Also test DNS, ordinary HTTPS, and reconnect after moving the client between Wi-Fi and mobile data. Because this is IPv4-only, configure the client not to leak IPv6 through another interface or disable IPv6 for the tunnel session when its client platform requires that explicit choice.

Add or revoke peers

Generate a unique key pair and tunnel /32 for every device. Add a new [Peer] block to wg0.conf, validate, and reload without dropping active sessions:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'
sudo wg show

The syncconf command uses Bash process substitution and updates peers without taking the interface down. To revoke a lost device, remove its peer block and sync the configuration immediately. A shared key cannot identify or revoke one device independently.

Back up, restore, and update

Back up /etc/wireguard/wg0.conf and the server key to encrypted off-server storage. Client private keys should normally stay with their clients. Protect the archive as a live credential:

sudo tar -C /etc -czf "/root/wireguard-$(date -u +%Y%m%dT%H%M%SZ).tar.gz" wireguard

On restore, install WireGuard, restore the protected directory with mode 600 on private material, re-enable IP forwarding and firewall/NAT rules, then start wg-quick@wg0. If the endpoint IP or hostname changes, update every client. Read Backups and snapshots; LayerOne does not preserve this configuration for you.

WireGuard updates arrive through normal Ubuntu security updates:

sudo apt update
sudo apt full-upgrade -y
sudo wg show

Reboot if Ubuntu reports a required kernel restart, then confirm a fresh client handshake and public IP.

Security pitfalls

  • Never reuse a private key between clients or publish a client profile.
  • Restrict each server peer's AllowedIPs to its assigned /32 unless the peer is deliberately a router for another network.
  • Do not expose management dashboards or DNS resolvers merely because the VPN port is open.
  • A full tunnel can make the VPS address responsible for every client's abuse complaints and rate limits. Control who receives a profile.
  • WireGuard is quiet when a peer is idle. Absence of a continuous connection is normal; use the latest handshake and transfer counters for diagnosis.

Official and LayerOne references

Still stuck

Chat with us from the portal.

Ask the assistant from the Chat bar. During business hours you can ask for a person and a human joins live.