A self-hosted VPN exit node routes your device’s traffic through a VPS that you control. WireGuard encrypts traffic between the client and the VPS, while the VPS forwards that traffic to the public internet. This is useful for securing traffic on untrusted networks, giving remote devices a consistent egress address, or reaching resources that allowlist one server IP.
An exit node is not an anonymity service. The VPS provider can associate the server with your account, destinations can see the VPS address, and a single hosting IP can be easier to correlate than a large shared VPN network. Streaming platforms may also block hosting ranges or restrict location-based access. Use the setup only where it is lawful and consistent with the services’ terms.
Plan the Exit Node Before You Provision It
Choose a location by measuring from the clients that will use the tunnel. A nearby city often reduces round-trip time, but network peering can matter more than straight-line distance. Test more than one candidate region when possible. If a particular jurisdiction or data residency boundary matters, document that requirement separately; low latency does not prove legal or policy suitability.
Start with a small VPS, then size it from observed throughput, concurrent clients, CPU use, and packet loss. WireGuard is lightweight, but there is no universal CPU or memory figure that guarantees a certain number of high-resolution streams. The path between the client, VPS, and destination can become the bottleneck before the server does.
- Reserve a private tunnel subnet that does not overlap the client’s home, office, or travel networks. This guide uses
10.90.90.0/24. - Decide whether the first deployment is IPv4-only or dual-stack. Routing only
0.0.0.0/0does not carry IPv6 traffic. - Keep one out-of-band recovery path, such as the provider console, before changing firewall or routing rules.
- Give every client a unique key pair and tunnel address so one lost device can be revoked without replacing every peer.
If you need a broader comparison of VPN deployment models, read the VPS.us guide to self-hosted VPN benefits, limits, and hosting choices.
Prepare an Ubuntu VPS Without Losing Access
The commands below target Ubuntu 24.04 LTS. Take a provider snapshot or verified backup first, create a sudo-capable administrative user, and confirm key-based SSH in a second terminal before changing the firewall. Do not disable the session that currently gives you access until the replacement login has been tested.
sudo apt update sudo apt full-upgrade sudo apt install wireguard ip -brief address ip route get 1.1.1.1
The final command shows the current public egress interface. Record its real name, such as ens3 or eth0; the server configuration must use that exact interface. Also confirm that the VPS or provider firewall permits the chosen WireGuard UDP port. This guide uses 51820/udp.
Ubuntu’s default host-firewall frontend is UFW. If you enable it, allow the proven SSH service before enabling or reloading it. Gateway forwarding also needs explicit forward/NAT handling; opening the UDP listener alone is not enough. Avoid combining UFW with a separate native nftables ruleset unless you have designed and tested their ownership carefully.
Route Client Traffic Through the VPS

A WireGuard handshake proves that two peers can exchange encrypted packets. It does not automatically make the VPS a gateway. The server must forward packets between interfaces and apply source NAT so replies return through the VPS. Ubuntu’s official WireGuard gateway guidance requires both IPv4 forwarding and masquerading.
Enable IPv4 forwarding in a dedicated sysctl drop-in, then load that exact file. Keeping the setting in its own file makes it easier to audit and remove later.
sudo tee /etc/sysctl.d/70-wireguard-routing.conf >/dev/null <<'EOF' net.ipv4.ip_forward = 1 EOF sudo sysctl -p /etc/sysctl.d/70-wireguard-routing.conf sysctl net.ipv4.ip_forward
The NAT and forward rules in the next section are attached to the WireGuard service with PostUp and PreDown. That keeps the rules aligned with the tunnel lifecycle and avoids installing a second unrelated persistence mechanism. Ubuntu 24.04 uses the nftables backend for the iptables compatibility commands by default; do not run a competing native nftables ruleset at the same time.
Create Server and Client Key Pairs
WireGuard uses a private key on each peer and distributes only the corresponding public keys. Generate the server key on the server. Generate the client key on the client when practical, so its private key never needs to leave that device. The example below creates both on the server for a controlled first test; transfer the client configuration through a secure channel and remove any unnecessary copy afterward.
sudo install -d -m 700 /etc/wireguard umask 077 wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub >/dev/null wg genkey | tee client1.key | wg pubkey | tee client1.pub >/dev/null sudo chmod 600 /etc/wireguard/server.key chmod 600 client1.key
Do not paste private keys into tickets, chat, screenshots, or command output. The server configuration below loads its private key from a root-readable file. Replace CLIENT_PUBLIC_KEY with the client’s public key and replace ens3 with the egress interface you recorded earlier.
[Interface] Address = 10.90.90.1/24 ListenPort = 51820 PostUp = wg set %i private-key /etc/wireguard/server.key PostUp = iptables -A FORWARD -i %i -o ens3 -j ACCEPT PostUp = iptables -A FORWARD -i ens3 -o %i -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT PostUp = iptables -t nat -A POSTROUTING -s 10.90.90.0/24 -o ens3 -j MASQUERADE PreDown = iptables -D FORWARD -i %i -o ens3 -j ACCEPT PreDown = iptables -D FORWARD -i ens3 -o %i -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT PreDown = iptables -t nat -D POSTROUTING -s 10.90.90.0/24 -o ens3 -j MASQUERADE [Peer] PublicKey = CLIENT_PUBLIC_KEY AllowedIPs = 10.90.90.2/32
Save that content as /etc/wireguard/wg0.conf with mode 600. Before starting the service, allow SSH and the WireGuard listener in every firewall layer you actually use. Provider firewalls and the host firewall are separate controls.
sudo chmod 600 /etc/wireguard/wg0.conf sudo ufw allow OpenSSH sudo ufw allow 51820/udp sudo ufw status verbose sudo systemctl enable --now wg-quick@wg0 sudo systemctl status wg-quick@wg0 --no-pager
If UFW is currently disabled, review its complete policy and use the provider console as a fallback before enabling it. Enabling a firewall during a remote session without a tested SSH rule can lock you out. For a broader server baseline, see the VPS.us server access and hardening checklist.
Add a Full-Tunnel Client Profile

A full-tunnel profile sends all IPv4 destinations through the VPS by using AllowedIPs = 0.0.0.0/0. The client still needs the server’s public key, public endpoint, and a unique tunnel address. Replace every uppercase placeholder before importing the file.
[Interface] PrivateKey = CLIENT_PRIVATE_KEY Address = 10.90.90.2/32 DNS = 1.1.1.1 [Peer] PublicKey = SERVER_PUBLIC_KEY Endpoint = SERVER_PUBLIC_IP:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25
WireGuard’s official guidance describes PersistentKeepalive = 25 as a useful interval when a peer behind NAT or a stateful firewall must keep its mapping alive. It is not required for every client; remove it when the client does not need to receive traffic after idle periods.
The DNS field is handled differently across WireGuard clients. On Linux, wg-quick commonly relies on resolvconf; desktop and mobile apps expose the setting in their own interface. Confirm the behavior on the actual client rather than assuming that the line changed the system resolver.
Verify the Handshake, Routing, and DNS Path
Test one layer at a time. First confirm the UDP listener and a recent handshake. Then confirm forwarding and NAT on the server. Finally, check the public IPv4 address and DNS behavior from the client. A successful handshake with no internet access usually points to forwarding, firewall, NAT, or an incorrect egress interface—not to WireGuard cryptography.
sudo wg show sudo ss -lunp | grep 51820 sysctl net.ipv4.ip_forward sudo iptables -t nat -S POSTROUTING sudo iptables -S FORWARD # Run on the connected client: curl -4 https://icanhazip.com resolvectl status
The client’s public IPv4 result should match the VPS egress address. Inspect the resolver used for the tunnel and perform a DNS leak test with a service you trust. Also test IPv6 separately. If the client has working native IPv6 while the profile routes only IPv4, IPv6 destinations can bypass the tunnel. Either build and verify complete dual-stack forwarding with ::/0, or explicitly control IPv6 on the client during an IPv4-only deployment.
Do not force an MTU merely because a generic guide recommends one. The current wg-quick documentation says automatic MTU selection is usually sensible. Change it only after reproducing fragmentation or path-MTU trouble, and measure before and after. The VPS.us VPS optimization guide covers the broader measurement discipline for CPU, storage, and network bottlenecks.
Maintain and Revoke Access Safely

Treat the exit node as internet-facing infrastructure. Apply security updates, monitor disk and service health, review firewall rules, and keep encrypted off-host copies of the configuration needed for recovery. Backups that contain WireGuard private keys are credentials: restrict access, encrypt them, and test restoration in an isolated environment. The VPS.us guide to self-hosted backup and restore planning explains why a successful backup job is not enough without a restore test.
When a device is lost or retired, remove only that peer from wg0.conf, reload the configuration, and confirm the peer no longer appears. Unique client keys make revocation narrow and auditable. If the server private key is exposed, replace the server key and update every client with the new public key.
sudo apt install unattended-upgrades sudo systemctl enable --now unattended-upgrades sudo systemctl enable wg-quick@wg0 sudo systemctl is-active wg-quick@wg0 sudo wg show sudo journalctl -u wg-quick@wg0 --since today --no-pager
Before an OS upgrade or firewall redesign, save the current configuration, verify console access, and define a rollback. Re-test the handshake, egress address, DNS behavior, and IPv6 path after every material networking change.
Frequently Asked Questions
Does a self-hosted WireGuard exit node make me anonymous?
Why can WireGuard connect while websites still fail?
Should every client use PersistentKeepalive?
Does AllowedIPs 0.0.0.0/0 prevent every leak?