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.
On this page
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 wireguard2. 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.pskThe 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/32Add 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 --systemIf 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 show6. 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 = 25AllowedIPson the client lists the networks routed through the tunnel. Use0.0.0.0/0to send all traffic through the VPN.DNSis optional. Point it at a resolver on the LAN to resolve internal hostnames.PersistentKeepalivekeeps 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 wg0wg-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.