Skip to content
Skip to the article
In Linux: 9 articles
Linux

Set Up a WireGuard VPN Host

Configure a Linux WireGuard server with wg-quick, generate client keys, and give remote clients access to the server's LAN.

Updated
Applies to
  • Ubuntu 24.04
  • Ubuntu 26.04
  • WireGuard tools 1.0
Tags
  • wireguard
  • vpn
  • networking
  • systemd
Reading time
4 min

This page sets up a Linux server as a WireGuard VPN host that remote clients connect to, with optional access to the network behind the server. The examples use 10.0.0.0/24 for the VPN tunnel, <LAN_SUBNET> for the server's local network, and 203.0.113.10 as the server's public address. Run the commands as root.

1. Install WireGuard

apt install wireguard

2. Generate Keys

Generate the server's key pair, then one key pair plus a preshared key for each client. umask 077 keeps the key files private:

umask 077
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee client1.key | wg pubkey > client1.pub
wg genpsk > client1.psk

The preshared key is optional. It adds a symmetric layer of protection on top of the public-key exchange.

Warning

Private keys and preshared keys are secrets. Never paste them into tickets, chat, or documentation. Generate client keys on the client device if you can, so the private key never leaves it.

3. Configure the Server

Create /etc/wireguard/wg0.conf:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>

# NAT VPN traffic out of the LAN interface so LAN hosts can reply.
PostUp = iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o <LAN_INTERFACE> -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o <LAN_INTERFACE> -j MASQUERADE

[Peer]
# client1
PublicKey = <CLIENT1_PUBLIC_KEY>
PresharedKey = <CLIENT1_PRESHARED_KEY>
AllowedIPs = 10.0.0.2/32

Add one [Peer] block per client, each with its own /32 address. On the server, AllowedIPs means "traffic from this peer may use these source addresses, and traffic to them goes to this peer".

If clients only need to reach the server itself, leave out the PostUp and PostDown lines and skip step 4.

4. Enable Forwarding

To let clients reach the LAN behind the server, turn on IP forwarding:

echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-wireguard.conf
sysctl --system

If the server runs a firewall with a default-deny forward policy (such as UFW), also allow the VPN port and forwarding between wg0 and the LAN interface:

ufw allow 51820/udp
ufw route allow in on wg0 out on <LAN_INTERFACE>

5. Start the Tunnel

systemctl enable --now wg-quick@wg0
wg show

6. Configure the Client

Give each client a config file like this one. Import it into the WireGuard app, or save it as /etc/wireguard/wg0.conf on a Linux client:

[Interface]
PrivateKey = <CLIENT1_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = <DNS_SERVER_IP>

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <CLIENT1_PRESHARED_KEY>
AllowedIPs = 10.0.0.0/24, <LAN_SUBNET>
Endpoint = 203.0.113.10:51820
PersistentKeepalive = 25
  • AllowedIPs on the client lists the networks routed through the tunnel. Use 0.0.0.0/0 to send all traffic through the VPN.

  • DNS is optional. Point it at a resolver on the LAN to resolve internal hostnames.

  • PersistentKeepalive keeps NAT mappings open when the client sits behind a home router or mobile network.

To hand the config to a phone, render it as a QR code on the server with qrencode -t ansiutf8 < client1.conf, then delete the file.

Add a Client Without Restarting

Add a peer to the running interface, then save it to the config file:

wg set wg0 peer <CLIENT2_PUBLIC_KEY> preshared-key /etc/wireguard/client2.psk allowed-ips 10.0.0.3/32
wg-quick save wg0

wg-quick save overwrites wg0.conf with the running state and drops comments, so keep a copy if you annotate the file. Alternatively, edit wg0.conf and run systemctl reload wg-quick@wg0, which applies peer changes without dropping existing connections.

Sources

This article is in the public domain (CC0 1.0), code samples included. Use it however helps you.