How to Install WireGuard on Ubuntu 26.04, 24.04 and 22.04

Install WireGuard on Ubuntu 26.04, 24.04, and 22.04. Covers APT packages, wg0 setup, client DNS, UFW, updates, and removal.

PublishedAuthorJoshua JamesRead time9 minGuide typeUbuntu

WireGuard gives Ubuntu servers a lightweight way to create encrypted tunnels without a hosted control plane or a bulky VPN daemon. Ubuntu ships the kernel module in current kernels, so setup usually means installing the wireguard package, generating peer keys, and letting wg-quick manage the wg0 interface through systemd.

The commands target Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS. The worked example creates one IPv4 WireGuard server at 10.8.0.1, one client at 10.8.0.2, and optional gateway routing so the client can send traffic through the Ubuntu server.

Install WireGuard on Ubuntu

Ubuntu’s WireGuard package path is simple because current Ubuntu kernels already include the WireGuard kernel module. The wireguard metapackage installs the user tools through wireguard-tools, including wg, wg-quick, and the wg-quick@.service systemd template.

The upstream WireGuard installation page lists Ubuntu as a package-based module and tools install. The wireguard-linux Git tree is kernel development source, not a normal “latest stable” Ubuntu installer. Use APT for standard Ubuntu systems; reserve source or DKMS work for custom kernels that you can validate and maintain separately.

Check the WireGuard Package Candidate

Refresh package metadata, then confirm that Ubuntu can see both the metapackage and the tools package:

sudo apt update
apt-cache policy wireguard wireguard-tools

Ubuntu 26.04 currently reports a newer tool package than Ubuntu 24.04 and 22.04, but all three releases provide the same package roles:

wireguard:
  Installed: (none)
  Candidate: 1.0.20250521-1ubuntu1
  Version table:
     1.0.20250521-1ubuntu1 500
        500 http://archive.ubuntu.com/ubuntu resolute/universe amd64 Packages
wireguard-tools:
  Installed: (none)
  Candidate: 1.0.20250521-1ubuntu1
  Version table:
     1.0.20250521-1ubuntu1 500
        500 http://archive.ubuntu.com/ubuntu resolute/main amd64 Packages

If wireguard has no candidate, the Universe component is probably disabled on that system. Enable Ubuntu Universe repositories, refresh APT again, and repeat the package check.

Install the WireGuard Package

Install the metapackage from Ubuntu’s repositories:

sudo apt install wireguard -y

These commands use sudo for package, service, and network changes that need root privileges. If your account is not ready for administrative commands, add a sudo user on Ubuntu before continuing.

Verify WireGuard Tools and Kernel Module

Check the installed tools and confirm that the kernel module is available:

wg --version
command -v wg-quick
sudo modprobe wireguard
modinfo wireguard | head -n 8

Example output from Ubuntu 26.04 includes the WireGuard tools version and the in-tree kernel module path:

wireguard-tools v1.0.20250521 - https://git.zx2c4.com/wireguard-tools/
/usr/bin/wg-quick
filename:       /lib/modules/7.0.0-15-generic/kernel/drivers/net/wireguard/wireguard.ko.zst
version:        1.0.0
description:    WireGuard secure network tunnel
license:        GPL v2

Ubuntu 24.04 and 22.04 can show wireguard-tools v1.0.20210914. That tools version does not mean the VPN protocol is outdated; the kernel module and tools are packaged for each Ubuntu release branch.

Plan WireGuard Server and Client Settings

WireGuard does not allocate addresses with DHCP. Choose a small private subnet that does not overlap your LAN, cloud VPC, Docker networks, or another VPN. The example values work for a single-client setup and can be expanded with more peers later.

SettingExample ValuePurpose
Server interfacewg0Systemd instance and tunnel interface name
Server tunnel address10.8.0.1/24Gateway address inside the WireGuard subnet
Client tunnel address10.8.0.2/32First client address allowed by the server peer entry
UDP listener51820/udpCommon example port for incoming WireGuard handshakes
Server public endpointvpn.example.com:51820DNS name or public IP address clients use to reach the server
Full-tunnel client route0.0.0.0/0Sends IPv4 client traffic through the VPN gateway

AllowedIPs is the most important setting to understand before editing the files. On the server, each peer’s AllowedIPs should be narrow, such as 10.8.0.2/32, so one peer cannot claim another peer’s address. On the client, AllowedIPs controls what traffic enters the tunnel. Use 0.0.0.0/0 for a full IPv4 tunnel, or use narrower networks such as 10.8.0.0/24, 192.168.1.0/24 for a split tunnel.

Find the server’s default outbound network interface before you write NAT rules. The interface name is the value after dev:

ip route show default
default via 192.0.2.1 dev eth0 proto dhcp src 192.0.2.10 metric 100

The example output uses eth0. Your server may use ens3, enp1s0, wlan0, or another name.

Configure the WireGuard Server on Ubuntu

The server configuration owns the listening port, the server private key, the server tunnel address, and a peer entry for each client. The full-tunnel example also enables IPv4 forwarding and adds a NAT rule when wg0 starts.

Enable IPv4 Forwarding for Gateway Mode

Enable forwarding when clients need to reach the internet or another network through the Ubuntu server. Do not create this sysctl file if the tunnel is only for reaching the server itself.

printf 'net.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/99-wireguard-forwarding.conf > /dev/null
sudo sysctl -p /etc/sysctl.d/99-wireguard-forwarding.conf
net.ipv4.ip_forward = 1

For IPv6 tunnels, plan IPv6 addressing, forwarding, firewalling, and provider routing separately. Do not add ::/0 to clients until the server has a working IPv6 forwarding and firewall design.

Generate Server and Client Keys

Create the WireGuard directory with restrictive permissions, then generate one key pair for the server and one key pair for the first client:

sudo install -d -m 700 /etc/wireguard /etc/wireguard/clients
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server_private.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server_private.key > /etc/wireguard/server_public.key'
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/clients/client1_private.key'
sudo sh -c 'wg pubkey < /etc/wireguard/clients/client1_private.key > /etc/wireguard/clients/client1_public.key'

Print only the public keys when you need to compare or copy values:

sudo cat /etc/wireguard/server_public.key
sudo cat /etc/wireguard/clients/client1_public.key

Private keys authenticate the peer that owns them. Do not paste private keys into tickets, chat, screenshots, or public logs. If a client is managed by another person, have that client generate its own private key and send you only the client public key.

Create the Server wg0 Configuration

Set public_interface to the outbound interface from the earlier route check, then create /etc/wireguard/wg0.conf:

public_interface="eth0"
server_private=$(sudo cat /etc/wireguard/server_private.key)
client_public=$(sudo cat /etc/wireguard/clients/client1_public.key)

sudo tee /etc/wireguard/wg0.conf > /dev/null <<EOF
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = ${server_private}
SaveConfig = false
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ${public_interface} -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o ${public_interface} -j MASQUERADE

[Peer]
PublicKey = ${client_public}
AllowedIPs = 10.8.0.2/32
EOF

sudo chmod 600 /etc/wireguard/wg0.conf
sudo chown root:root /etc/wireguard/wg0.conf

The PostUp and PostDown lines add and remove the IPv4 masquerade rule with the interface. Remove those two lines if clients only need to reach 10.8.0.1 on the VPN server and do not need routed traffic.

Start and Enable the WireGuard Server

Start the wg0 interface now and enable it at boot:

sudo systemctl enable --now wg-quick@wg0.service

Verify the systemd state and WireGuard interface:

systemctl is-active wg-quick@wg0.service
sudo wg show wg0
ip -brief address show wg0

Example output with public keys replaced by labels looks like this:

active
interface: wg0
  public key: SERVER_PUBLIC_KEY
  private key: (hidden)
  listening port: 51820
wg0              UNKNOWN        10.8.0.1/24

The peer will not show a recent handshake until the client imports its configuration and sends traffic.

Allow WireGuard Through UFW

Open UFW only after the local wg0 listener is active. Check UFW status first, especially on remote servers where a missing SSH rule can lock out the current session:

sudo ufw status verbose

If UFW reports Status: active, allow the WireGuard UDP listener. For a broader firewall baseline, use the Ubuntu UFW firewall guide. The Ubuntu SSH setup guide covers listener and firewall checks for remote access.

sudo ufw allow 51820/udp

For gateway mode with UFW active, also allow routed packets from wg0 to the server’s outbound interface. Replace eth0 with the same interface used in wg0.conf:

sudo ufw route allow in on wg0 out on eth0

Cloud firewalls, router port forwards, and hosting-provider security groups are separate from UFW. Open or forward the same UDP port in that control plane when the server sits behind one.

If you prefer native rules instead of UFW, configure nftables on Ubuntu and keep one firewall manager responsible for the same host ruleset.

Create a WireGuard Client Configuration

The client configuration needs the client private key, the client tunnel address, the server public key, and the server endpoint. Set server_endpoint to a DNS name or public IP address that reaches the Ubuntu server.

server_endpoint="vpn.example.com"
server_public=$(sudo cat /etc/wireguard/server_public.key)
client_private=$(sudo cat /etc/wireguard/clients/client1_private.key)

sudo tee /etc/wireguard/clients/client1.conf > /dev/null <<EOF
[Interface]
PrivateKey = ${client_private}
Address = 10.8.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = ${server_public}
Endpoint = ${server_endpoint}:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF

sudo chmod 600 /etc/wireguard/clients/client1.conf

For a split tunnel, replace AllowedIPs = 0.0.0.0/0 with the VPN and private networks that should use the tunnel, such as AllowedIPs = 10.8.0.0/24, 192.168.1.0/24. The PersistentKeepalive = 25 setting is useful for laptops, phones, and clients behind NAT because it keeps the mapping open enough for the server to reply.

The client configuration contains the client private key. Anyone who receives that file can authenticate as that peer until you remove or replace the peer public key on the server.

Copy the client file to the client system through a secure channel, or print it for import into a WireGuard app only when your terminal is private:

sudo cat /etc/wireguard/clients/client1.conf

Optional QR Code for Mobile Clients

Phone clients can import a WireGuard profile from a QR code. Install qrencode only on the system where you want to display the code:

The QR code contains the client private key. Generate it only in a private terminal, avoid screen sharing while it is visible, and close the terminal when the import finishes.

sudo apt install qrencode -y
sudo qrencode -t ansiutf8 < /etc/wireguard/clients/client1.conf

Scan the terminal QR code from the official WireGuard mobile app.

Connect an Ubuntu WireGuard Client

On an Ubuntu client, install WireGuard the same way as the server:

sudo apt update
sudo apt install wireguard -y

Client profiles that use a DNS = line need a resolvconf-compatible command. Ubuntu 26.04 and 24.04 usually provide that compatibility through systemd-resolved. Check the client before starting the interface:

command -v resolvconf
/usr/sbin/resolvconf

If an Ubuntu 22.04 client prints no path, install openresolv before starting the interface. On Ubuntu 26.04 and 24.04, keep systemd-resolved installed because it provides /usr/sbin/resolvconf on those releases.

sudo apt install openresolv

Save the client configuration as /etc/wireguard/wg0.conf, then lock down the file:

sudo install -d -m 700 /etc/wireguard
sudo nano /etc/wireguard/wg0.conf
sudo chmod 600 /etc/wireguard/wg0.conf
sudo chown root:root /etc/wireguard/wg0.conf

Start the client tunnel and enable it at boot:

sudo systemctl enable --now wg-quick@wg0.service

Check the client interface and handshake state:

sudo wg show wg0
ping -c 4 10.8.0.1

After the client sends traffic, wg show should include a recent handshake and transfer counters. Example output with public keys replaced by labels looks like this:

interface: wg0
  public key: CLIENT_PUBLIC_KEY
  private key: (hidden)

peer: SERVER_PUBLIC_KEY
  endpoint: vpn.example.com:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 2 seconds ago
  transfer: 476 B received, 564 B sent

A working tunnel shows a recent handshake, transfer counters, and successful replies from 10.8.0.1. For a full-tunnel setup, compare the client’s public IP address before and after connection to confirm traffic exits through the server.

Manage WireGuard on Ubuntu

Use systemd for normal interface lifecycle work and wg for live tunnel state:

systemctl status wg-quick@wg0.service --no-pager
sudo wg show wg0

Restart the interface after changing addresses, NAT commands, DNS lines, or firewall-dependent settings:

sudo systemctl restart wg-quick@wg0.service

If you only add, remove, or edit peer entries in wg0.conf, reload the systemd instance and recheck the peer list:

sudo systemctl reload wg-quick@wg0.service
sudo wg show wg0

Update WireGuard Packages

WireGuard updates through Ubuntu’s normal APT workflow. Upgrade the installed WireGuard packages without pulling in unrelated new packages:

sudo apt update
sudo apt install --only-upgrade wireguard wireguard-tools

Kernel updates can also update the in-tree WireGuard module. Reboot when Ubuntu installs a new kernel and the server’s maintenance window allows it.

Optional helper packages such as qrencode and openresolv update through APT as well when they are installed.

Remove WireGuard from Ubuntu

Stop and disable the wg0 interface before removing packages:

sudo systemctl disable --now wg-quick@wg0.service

Remove the WireGuard packages:

sudo apt remove wireguard wireguard-tools

If you installed qrencode only for mobile profile import, remove it separately:

sudo apt remove qrencode

If you installed openresolv only for WireGuard client DNS handling, remove it only after confirming no other VPN, network profile, or resolver workflow still needs /usr/sbin/resolvconf:

sudo apt remove openresolv

APT may also offer automatically installed dependencies such as libqrencode4. Review the proposed list before accepting the cleanup:

sudo apt autoremove

Remove UFW rules only if you added them for this WireGuard interface. Replace eth0 with your actual outbound interface:

sudo ufw delete allow 51820/udp
sudo ufw route delete allow in on wg0 out on eth0

Review configuration and key files before deleting them:

sudo find /etc/wireguard -maxdepth 2 -type f -print

Deleting /etc/wireguard permanently removes server keys, client keys, peer configs, and exported client profiles stored there. Back up anything you may need to reconnect existing peers.

sudo rm -rf /etc/wireguard

If the server used IPv4 forwarding only for WireGuard, remove the WireGuard forwarding sysctl file and reapply the remaining sysctl configuration:

sudo rm -f /etc/sysctl.d/99-wireguard-forwarding.conf
sudo sysctl --system

Leave forwarding enabled if the system still routes Docker networks, virtual machines, Kubernetes traffic, another VPN, or a router workload.

Troubleshoot WireGuard on Ubuntu

WireGuard Service Fails to Start

Start with the service status and recent unit logs. Most startup failures come from a bad key, a typo in wg0.conf, an already-used address, or a failing PostUp command.

systemctl status wg-quick@wg0.service --no-pager
sudo journalctl -u wg-quick@wg0.service --no-pager -n 50

If the log names iptables, recheck the outbound interface in the PostUp line. If the log names an address conflict, confirm that no old interface is still present:

ip -brief address show wg0

If wg0 is still present and should not be running, bring it down before retrying the service start:

sudo wg-quick down wg0

After fixing wg0.conf, restart the interface and recheck the service state:

sudo systemctl restart wg-quick@wg0.service
systemctl is-active wg-quick@wg0.service

No Latest Handshake Appears

A missing handshake usually means the client cannot reach the server’s UDP listener or one side has the wrong public key. Check the server first:

sudo wg show wg0
sudo ufw status verbose

Confirm that the client Endpoint points at the server’s reachable public IP address or DNS name, that UDP 51820 is open in UFW and any cloud firewall, and that a router forwards the same UDP port to the Ubuntu server when the server is behind NAT.

Client Connects but Cannot Reach the Internet

A successful handshake with no routed traffic usually points to forwarding, NAT, UFW route policy, or client AllowedIPs. Check the server’s forwarding state and default interface:

sysctl net.ipv4.ip_forward
ip route show default
sudo ufw status verbose

For the full-tunnel example, net.ipv4.ip_forward should be 1, the PostUp interface should match the default route interface, and UFW should allow routed traffic from wg0 to that interface. The client should use AllowedIPs = 0.0.0.0/0 for IPv4 full-tunnel routing.

DNS Fails After the Tunnel Connects

If the client service fails with resolvconf: command not found, install the release-specific provider and start the interface again. On Ubuntu 22.04, use openresolv:

sudo apt install openresolv
sudo systemctl restart wg-quick@wg0.service

On Ubuntu 26.04 and 24.04, systemd-resolved provides /usr/sbin/resolvconf:

sudo apt install systemd-resolved
sudo systemctl restart wg-quick@wg0.service

If IP addresses work but hostnames fail, inspect the DNS line in the client configuration and the resolver state on the client:

sudo grep '^DNS' /etc/wireguard/wg0.conf
resolvectl status

Use a resolver that is reachable through the tunnel, such as an internal DNS server for private networks or a public resolver for a normal full-tunnel setup. Restart the client interface after changing the DNS line.

Conclusion

WireGuard is running on Ubuntu with APT-managed tools, locked-down keys, a systemd-managed wg0 interface, and a first client profile ready to import. Keep peer addresses narrow on the server, open only the UDP path you need, and use Tailscale on Ubuntu when you would rather use a managed WireGuard-based overlay than maintain your own endpoint and peer files.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: