Before you start: choose a VPS for WireGuard
A WireGuard VPN server connects your laptop or phone to a VPS, then routes internet traffic through that server. This manual setup suits someone comfortable editing Linux configuration files. Windows, macOS, iPhone and Android devices can connect; the server itself runs Ubuntu 24.04 or Debian 12/13.
- Use a fresh, dedicated VPS with sudo access, a public IPv4 address, WireGuard kernel support and permitted UDP traffic. Check the plan’s transfer allowance and acceptable-use terms.
- Keep your SSH session open and confirm that the provider’s recovery console works. Record the real SSH port; it may not be 22.
- Do not apply this standalone firewall to a server already using UFW, firewalld, Docker or another firewall manager. Integrate rules into that existing policy instead.
- Use a VPN subnet that does not overlap your home, office or VPS networks. Change every occurrence below if 10.66.66.0/24 or fd42:66:66::/64 overlaps.
1. Install WireGuard and generate the server key
Run these commands on the VPS. Generate the key once; rerunning the key-generation command replaces it and disconnects existing clients. Only the public key is printed.
sudo apt update
sudo apt install wireguard nftables nano
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key; wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo cat /etc/wireguard/server.pub
ip -4 route show default
sudo sshd -T | awk '$1 == "port" {print $2}'
sudo nft list rulesetRecord the interface after “dev” in the default route, such as ens3. The firewall below uses ens3 as an example. If the ruleset shows existing policies, stop and reconcile them before continuing; do not erase them.
Install the official WireGuard app on your first device. Create an empty tunnel and generate its key pair in the app. Keep that private key on the device; copy its public key for the server configuration. Repeat with a new key pair for every additional device.
2. Create the server configuration
Open /etc/wireguard/wg0.conf with sudo nano and enter the following. Replace CLIENT_PUBLIC_KEY with the device’s public key. PostUp reads the server’s private key from its protected file.
[Interface]
Address = 10.66.66.1/24, fd42:66:66::1/64
ListenPort = 51820
PostUp = wg set %i private-key /etc/wireguard/server.key
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.66.66.2/32, fd42:66:66::2/128sudo chmod 600 /etc/wireguard/wg0.conf
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/70-vpsray-vpn.conf
sudo sysctl -p /etc/sysctl.d/70-vpsray-vpn.confForwarding lets the VPS route packets for connected devices. The server’s AllowedIPs must identify that individual device, not 0.0.0.0/0. Additional peers use separate addresses such as 10.66.66.3/32 and fd42:66:66::3/128.
3. Allow SSH and WireGuard, then add IPv4 NAT
In any provider-level firewall, allow UDP 51820 and your actual SSH TCP port. On this fresh server, back up /etc/nftables.conf, then replace its unused example configuration with the rules below. Replace every instance of ens3 and change TCP port 22 if necessary.
sudo cp -a /etc/nftables.conf /etc/nftables.conf.before-vpsray
sudo nano /etc/nftables.conftable inet vpsray_vpn
flush table inet vpsray_vpn
table inet vpsray_vpn {
chain input {
type filter hook input priority 0; policy drop;
iifname "lo" accept
ct state established,related accept
ct state invalid drop
ip protocol icmp accept
meta l4proto ipv6-icmp accept
udp sport 67 udp dport 68 accept
udp sport 547 udp dport 546 accept
tcp dport 22 accept
udp dport 51820 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
iifname "wg0" oifname "ens3" ip saddr 10.66.66.0/24 accept
iifname "ens3" oifname "wg0" ip daddr 10.66.66.0/24 ct state established,related accept
}
}
table ip vpsray_vpn_nat
flush table ip vpsray_vpn_nat
table ip vpsray_vpn_nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 10.66.66.0/24 oifname "ens3" masquerade
}
}The NAT rule translates VPN clients’ IPv4 traffic to the VPS’s outgoing address. The forwarding chain permits only VPN-to-internet IPv4 traffic and its replies; it does not forward IPv6. Validate the syntax, apply the file, then immediately test a second SSH login before closing the first session.
sudo nft -c -f /etc/nftables.conf
# Continue only if the check succeeds.
sudo nft -f /etc/nftables.conf
sudo systemctl enable nftables
sudo systemctl enable --now wg-quick@wg0If the new SSH login fails, use the still-open session or recovery console to correct the SSH port rule. The configuration does not open web or database ports; this is why a dedicated VPN VPS is the starting point.
4. Connect Windows, macOS, iPhone or Android
Complete the tunnel in your device’s WireGuard app. Keep its generated private key and replace SERVER_PUBLIC_KEY with the server.pub value. Replace YOUR_VPS_PUBLIC_IPV4 with the actual public IPv4 address, not 127.0.0.1, a private server address or the VPN address.
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.66.66.2/32, fd42:66:66::2/128
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_VPS_PUBLIC_IPV4:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25You can replace the example DNS address with another public IPv4 resolver you trust. PersistentKeepalive helps preserve a connection through a device’s NAT; it can be omitted when unnecessary. Activate the tunnel and allow the operating system’s VPN permission request.
Do not share one configuration across devices or post its QR code. A copied private key grants access as that device. Add a separate server peer and a unique address pair for each phone or computer. After adding a peer to an already running wg0.conf, apply it with sudo systemctl restart wg-quick@wg0; this briefly disconnects existing clients.
5. Verify the tunnel, DNS and restart behavior
sudo wg show wg0
sudo systemctl status wg-quick@wg0 --no-pager
sudo sysctl net.ipv4.ip_forward
sudo nft list table ip vpsray_vpn_nat- Browse from the connected device. A recent handshake and increasing transfer counters should appear in wg show.
- Check your public IPv4 using an independent IP-check page. It should match the VPS’s public egress address, which can differ from its interface address behind provider NAT.
- Run a DNS and IPv6 test from the device. Confirm the intended resolver, and verify that no working ordinary IPv6 path appears. Browser secure-DNS settings can choose a different resolver.
- Test switching Wi-Fi to mobile data and reconnecting. Then reboot the VPS during a convenient maintenance window and confirm that firewall rules and WireGuard return.
Fix common WireGuard connection problems
| Symptom | Check next |
|---|---|
| No handshake | Public endpoint, UDP 51820 in both firewalls, matching peer public keys, and the running wg-quick service. |
| Handshake, but no internet | IPv4 forwarding, the real outgoing interface in both rules, NAT, and the client’s 0.0.0.0/0 route. |
| IP addresses work, names do not | The client DNS setting, resolver reachability and browser secure-DNS overrides. |
| Some sites stall | Investigate path MTU. Temporarily try MTU = 1280 in the client Interface section, reconnect, and compare. |
| Required key not available | Check each peer’s AllowedIPs and the device’s assigned address. |
For startup errors, run sudo journalctl -u wg-quick@wg0 -n 50 --no-pager. Redact endpoint addresses and identifiers before sharing logs; never share private keys or complete client files.
Maintain the VPN or revoke a device
Keep Linux and client apps updated, protect backups, and track which public key belongs to each device. To revoke a lost device immediately, replace CLIENT_PUBLIC_KEY in the command below, then remove its matching Peer block from /etc/wireguard/wg0.conf so it stays revoked after reboot.
sudo wg set wg0 peer CLIENT_PUBLIC_KEY removeTo retire the VPN, run sudo systemctl disable --now wg-quick@wg0. Remove UDP 51820 from both firewall layers, remove the two VPN forwarding rules and the NAT definition from /etc/nftables.conf, and keep the input rules protecting SSH. Validate and apply the edited file, then run sudo nft delete table ip vpsray_vpn_nat to remove the no-longer-defined live NAT table. Remove /etc/sysctl.d/70-vpsray-vpn.conf and set net.ipv4.ip_forward=0 only if nothing else needs routing. Finally remove the unused tunnel files and device profiles.
Common questions
Can I use a Windows laptop with an Ubuntu VPN server?
Yes. The server and client do not need the same operating system. Install the official Windows WireGuard app and create a client profile using your server’s public key and endpoint.
Do I need a domain name for WireGuard?
No. A reachable public IPv4 address works as the endpoint in this guide. A hostname can also work, but its DNS must resolve to the right server.
Why does this setup include ::/0 if it only supports IPv4 internet?
It directs IPv6 into the VPN, where forwarding is blocked. This avoids deliberately leaving the ordinary IPv6 default route in use. Check the actual behavior on each device; this configuration does not promise protection after the tunnel is disabled.
Does a VPS VPN make my internet faster?
Not necessarily. Distance, routing, packet loss, your connection and the VPS plan all affect performance. Compare measurements with and without the VPN before upgrading resources.
Official documentation
Documentation reviewed October 18, 2026. Check the linked project documentation before installing or upgrading; commands below have not been run on your VPS.
- WireGuard: key generation and keepalive
- WireGuard: official installation and client downloads
- Ubuntu: VPN as a default gateway
- Ubuntu: nftables and firewall-manager compatibility
- Debian: nft command reference
- Debian: wg-quick routing and configuration reference
- Debian Handbook: firewall persistence
- Ubuntu: troubleshooting WireGuard
- Ubuntu: WireGuard security tips