WireGuard Server Setup on Ubuntu: Configure and Verify

WireGuard Server Setup on Ubuntu: Configure and Verify

Kevin Wu
October 9, 2026· 12 min read

WireGuard server setup needs more than a recent handshake. This guide builds an IPv4 internet gateway on Ubuntu 24.04 LTS, using a separate Ubuntu 24.04 LTS client, then checks forwarding, DNS, rejection, revocation, restart, and recovery. Use dedicated hosts you own or may administer. The commands are reader instructions, not a record of an author deployment.

Key Takeaways

  • A peer connection does not establish internet forwarding or DNS behavior.
  • Keep an independent management connection and a recoverable firewall baseline.
  • This example covers IPv4; an active alternative IPv6 path needs separate work.
  • Runtime peer removal and persistent configuration removal are both necessary.
  • Enable automatic startup only after the bounded task and recovery checks pass.

Should you choose a WireGuard server setup or a managed exit?

Use the self-hosting planning guide to define who owns the host, credentials, updates, and retirement. For one application with an explicit proxy setting, the VLESS/REALITY deployment tutorial is a different route, not a prerequisite. The full-tunnel and application-proxy comparison explains that coverage choice.

If you only need everyday public access without administering peers, AethoVPN offers a supported-terminal route. On Windows, use the official .exe, continue with an email verification code, select an actually available location in the App, and connect. Check the visible exit IP for that request, then repeat the original browser or upload task.

Compare VPS and VPN responsibilities before renting a host. Standard supports one mobile device; Pro supports two desktop and two mobile devices; Premium supports eight devices without a device-type distinction.

This method neither provisions your host nor claims compatibility with this WireGuard configuration. New users receive one three-day Pro trial; deleting and recreating an account does not reset it. Try a managed everyday exit.

Prepare a WireGuard Ubuntu server and a recovery path

Choose a dedicated Ubuntu 24.04 LTS server with a reachable public IPv4 endpoint and a separate authorized Ubuntu client. A host behind NAT also needs an authorized upstream UDP mapping; a private address alone is insufficient.

Reserve UDP 51820, tunnel network 10.77.0.0/24, server 10.77.0.1, and client 10.77.0.2. Replace these if they overlap any existing network. WireGuard's peer model explains the roles.[1]

Before changing anything, record ip address, ip route, ip rule, ip -6 address, ip -6 route, resolvectl status, sysctl net.ipv4.ip_forward, and the relevant firewall configuration. Keep those records privately. Test a new management connection through an independent provider console or recovery path; a terminal left open is insufficient. Save current configuration files outside public repositories.

This firewall example requires iptables with no competing UFW, firewalld, or independent nftables manager. Inspect sudo iptables-save and identify the policy owner. If another manager owns the rules, stop and implement the same narrow policy through that manager instead. Never flush the tables.

Record the real server egress interface from ip -4 route get 1.1.1.1; this command displays a route selection and does not send a probe. Below, EGRESS_IF is a placeholder, not a literal interface.

Use a controlled client without a usable IPv6 default path. If baseline inspection shows one, stop this IPv4-only exercise and design IPv6 routing and failure policy separately. Do not disable IPv6 on a shared machine to make a test look successful. This procedure also provides no kill switch: stopping the tunnel restores ordinary routing.

The topology separates the tunnel, server forwarding/NAT, and public destination. The management path must survive a tunnel failure; the diagram is explanatory, not measured traffic evidence.

Step 1: Install tools and generate separate peer keys

Install from Ubuntu's configured trusted repositories on both hosts. The project lists Ubuntu installation through apt.[2]

sudo apt update
sudo apt install wireguard iptables
sudo install -d -m 700 /etc/wireguard
sudo -i
cd /etc/wireguard
umask 077
wg genkey > wg-exit.private
wg pubkey < wg-exit.private > wg-exit.public
exit

Generate independently on each host. The private key remains on its own host; exchange only the corresponding public key.[1]

Keep the files root-owned and private; do not publish profiles, QR codes, screenshots, or usable key values. The names below identify replacements, not example secrets. Record which public key belongs to which device before adding it to the server.

Step 2: Configure forwarding and the WireGuard server firewall

Create /etc/wireguard/wg-exit.conf on the server with a private editor, replacing the key and EGRESS_IF. These hook rules carry an identifying comment and only serve this single client. wg-quick runs the hooks during interface lifecycle.[3]

[Interface]
Address = 10.77.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
PostUp = iptables -I INPUT 1 -p udp --dport 51820 -m comment --comment wg-exit-lab -j ACCEPT
PostUp = iptables -I FORWARD 1 -i %i -o EGRESS_IF -s 10.77.0.2/32 -m comment --comment wg-exit-lab -j ACCEPT
PostUp = iptables -I FORWARD 1 -i EGRESS_IF -o %i -d 10.77.0.2/32 -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment wg-exit-lab -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -s 10.77.0.2/32 -o EGRESS_IF -m comment --comment wg-exit-lab -j MASQUERADE
PreDown = iptables -D INPUT -p udp --dport 51820 -m comment --comment wg-exit-lab -j ACCEPT
PreDown = iptables -D FORWARD -i %i -o EGRESS_IF -s 10.77.0.2/32 -m comment --comment wg-exit-lab -j ACCEPT
PreDown = iptables -D FORWARD -i EGRESS_IF -o %i -d 10.77.0.2/32 -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment wg-exit-lab -j ACCEPT
PreDown = iptables -t nat -D POSTROUTING -s 10.77.0.2/32 -o EGRESS_IF -m comment --comment wg-exit-lab -j MASQUERADE

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.77.0.2/32

Allow the same UDP port in the provider's security group, preserving management access. Restrict the INPUT rule and security group to the authorized client's public source when it is stable; if using -s CLIENT_PUBLIC_IPV4/32, put it in both insertion and deletion rules. Do not confuse a cloud security group with the host firewall.

The forwarding rule permits this client's destinations reachable through EGRESS_IF. On a host with private routes, that might include private services: use a dedicated host without protected internal destinations, or first add an explicitly reviewed destination policy. Authentication does not establish a destination ACL.

NAT supplies a public return path; it does not authorize another peer. Ubuntu documents forwarding plus masquerading for an internet gateway.[4]

sudo chmod 600 /etc/wireguard/wg-exit.conf
sudo chown root:root /etc/wireguard/wg-exit.conf

Create a new, dedicated /etc/sysctl.d/70-wg-exit.conf containing net.ipv4.ip_forward=1, after recording the previous value and checking that the path is unused. Apply only that file:

sudo sysctl -p /etc/sysctl.d/70-wg-exit.conf
sudo wg-quick up wg-exit
sudo wg show wg-exit

If startup fails partway through a hook, inspect interface and rule state before retrying; remove only leftover rules with the exact matching deletion commands. Repeated insertion can create duplicates. Do not add SaveConfig=true: the manual warns that it writes runtime state back over the configuration when shutting down.[3]

Step 3: Configure the client and WireGuard internet gateway DNS

Create the client's private /etc/wireguard/wg-exit.conf:

[Interface]
Address = 10.77.0.2/32
PrivateKey = CLIENT_PRIVATE_KEY
PostUp = resolvectl dns %i AUTHORIZED_DNS_IPV4
PostUp = resolvectl domain %i ~.
PreDown = resolvectl revert %i

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_PUBLIC_IPV4:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Replace the public endpoint and select a reachable DNS resolver you are authorized to use. Set root ownership and mode 600, then use sudo wg-quick up wg-exit.

AllowedIPs has both routing and peer-address consequences; the server's /32 and client's default route have different roles. Read the AllowedIPs guide before changing them. wg-quick uses policy routing for a default route, so inspect ip rule and all relevant route tables instead of only the main table.[3]

Ubuntu's systemd-resolved can configure per-interface DNS and a ~. routing domain using resolvectl.[5] This example deliberately does not add DNS=, which wg-quick hands to resolvconf. Confirm that the client's resolver actually uses systemd-resolved before applying these hooks.

Application-specific encrypted DNS needs a separate application check. Keepalive is useful for some NAT mappings, not a throughput upgrade; omit it when unnecessary.[1]

Step 4: Verify, revoke, restart, and recover

Use the following acceptance matrix. Record your actual observations privately, with versions and timestamps. The outcomes here are expected, not author results.

CheckMethodExpected observationFailure action
Interface and peerOn both hosts: sudo wg show wg-exit and ip -4 address show dev wg-exit[6]Correct public-key pairing; server 10.77.0.1/24, client 10.77.0.2/32Correct ownership before changing routes
AuthenticationSend an authorized task request, inspect latest handshakeA recent handshake after that requestCheck UDP reachability and keys
Data and exitRepeat an owned/authorized public task; compare counters and its egress observationTraffic counters advance and intended server exit is observedCheck forwarding, NAT, return route
DNSresolvectl status wg-exit; resolvectl query TASK_HOSTIntended resolver/interface and successful answerCorrect resolver scope; check app DNS separately
IPv6 scopeRepeat baseline address/route inspectionNo alternative usable IPv6 path in this bounded clientStop the IPv4-only acceptance
Unregistered peerFresh disposable client key not listed by serverNo authenticated handshake or forwarded taskStop exposure and inspect effective peer list
RevocationRemove runtime and persistent peer, repeat its trafficRemoved device cannot authenticate or continue its tunnel dataFind a source restoring the peer

For revocation, use the device's actual public key:

sudo wg set wg-exit peer CLIENT_PUBLIC_KEY remove

Then delete that peer block from the server file. Do not save the entire runtime configuration over your hooks. Retry from the removed client and inspect the server's effective peer list; use a replacement credential for any later authorized test. Deleting the client profile alone does not revoke server permission.

After restoring an authorized disposable peer and passing the checks, enable startup on each dedicated host:

sudo systemctl enable wg-quick@wg-exit.service

Reboot only a host you may reboot. Check systemctl status wg-quick@wg-exit.service, wg show, forwarding value, the exact firewall rules, resolver scope, and a fresh task request. A container restart cannot substitute for this host lifecycle. If reboot is unavailable, leave this acceptance row unverified.

Failure branches and maintenance

No handshake points first to keys, endpoint, listener, or UDP filtering. A handshake with no task response points next to client route, server forwarding, NAT, and destination return policy. A working IP request with failed names points to DNS.

Follow the connected-without-internet checklist; change one layer at a time and repeat the same bounded request. A different VPN working does not locate this failure.

Keep software supported, assign one peer per revocable device, and repeat rejection and recovery checks after relevant changes. Record provider network changes too. Stop when you cannot explain an active rule, lose independent management, or need to alter shared production policy.

Restore the baseline

On the client, run sudo wg-quick down wg-exit, then disable its startup unit if enabled. On the server, use sudo systemctl disable --now wg-quick@wg-exit.service for an active managed unit, or sudo wg-quick down wg-exit for a manually started interface. Check actual state before choosing; disabling an inactive unit does not remove a manually started interface.

Inspect leftover rules after any failed hook and delete only this trial's exact entries. Remove the owned cloud rule too.

Remove the dedicated sysctl file and restore the recorded forwarding value only if no other service now depends on forwarding. Reconcile drift rather than replacing a whole firewall backup. Read back routes, resolver, rules, and a new management connection; repeat the original ordinary task.

Securely retire unused keys and owned files. Host, address, disk, and snapshot billing require separate provider cleanup.

Summary

  • Build one peer and one authorized task before adding devices.
  • Accept handshake, forwarding, DNS, scope, rejection, and lifecycle separately.
  • Revoke both effective and persistent access, then prove restoration of the baseline.

FAQ

Do I need a public server?

You need an authorized reachable endpoint for this internet-exit task. A host behind NAT needs suitable upstream mapping; private LAN access is a different topology.

Why does a handshake not prove internet access?

The encrypted peer relationship can work while forwarding, NAT, return routing, or DNS fails. Repeat an authorized public task and examine each layer separately.

How should I verify DNS?

Inspect per-interface resolver state and query the task hostname, then check the actual application's resolver behavior. Applications using their own encrypted DNS need separate evidence.

Does this setup cover IPv6?

No. It is an IPv4 example for a controlled client without a usable alternative IPv6 path. An active IPv6 default route requires a separately designed configuration.

How do I revoke one device?

Remove its peer from running WireGuard and the persistent server file, then retry its traffic. Removing only its client profile leaves server authorization intact.

What must I check after reboot?

Verify the service, effective peers, forwarding, exact firewall rules, resolver scope, and a fresh task request. A running service alone does not prove a working gateway.

When should I use a managed service?

Consider that route when you need supported-device public access and do not need server control. Verify its device terms and your actual task rather than assuming protocol compatibility.

Scope: Prepared from official sources for Ubuntu 24.04 LTS; no complete end-to-end author test was performed. This IPv4 gateway example provides no IPv6 or kill-switch acceptance. Use owned or authorized hosts and follow applicable law and service policy.

Sources:

  1. WireGuard, "Quick Start": https://www.wireguard.com/quickstart/
  2. WireGuard, "Installation": https://www.wireguard.com/install/
  3. Ubuntu Noble, "wg-quick(8)": https://manpages.ubuntu.com/manpages/noble/man8/wg-quick.8.html
  4. Ubuntu Server, "Using the VPN as the default gateway": https://ubuntu.com/server/docs/how-to/wireguard-vpn/vpn-as-the-default-gateway/
  5. Ubuntu Noble, "resolvectl(1)": https://manpages.ubuntu.com/manpages/noble/man1/resolvectl.1.html
  6. Ubuntu Noble, "ip-address(8)": https://manpages.ubuntu.com/manpages/noble/man8/ip-address.8.html

Sources checked 9 October 2026.


Related Articles:

Start your 3-day free trial

Sign up to experience all premium features at no cost.

*Available only to new users. Each user is limited to one trial.

WireGuard Server Setup on Ubuntu: Configure and Verify | AethoVPN