WireGuard is built into the Linux kernel, so a working VPN server is a short config file and two commands. This guide sets up the server, adds a client, and covers the mistakes that break it.
1. Install WireGuard
$ sudo apt update && sudo apt install -y wireguard$ sudo dnf install -y epel-release $ sudo dnf install -y wireguard-tools
2. Generate the server keys
$ cd /etc/wireguard $ sudo sh -c 'umask 077; wg genkey | tee server.key | wg pubkey > server.pub' $ sudo cat server.key $ sudo cat server.pub
umask 077 makes the key files readable only by root. Keep the private key private; the public key is meant to be shared.
3. Find your outgoing interface
The NAT rule in the next step needs the name of the interface that reaches the internet. Do not assume it is eth0:
$ ip route | grep defaultThe name after dev is what you use below.
4. Write the server config
[Interface] Address = 10.8.0.1/24 ListenPort = 51820 PrivateKey = PASTE_SERVER_PRIVATE_KEY PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Replace eth0 with the interface from step 3, and paste the contents of server.key as the private key. The MASQUERADE rule is what lets client traffic reach the internet through the server. Without it, clients connect but nothing loads.
5. Turn on forwarding and start the tunnel
$ echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf $ sudo sysctl --system $ sudo systemctl enable --now wg-quick@wg0 $ sudo wg show
Open the port in your firewall. WireGuard uses UDP, not TCP:
$ sudo ufw allow 51820/udp$ sudo firewall-cmd --permanent --add-port=51820/udp $ sudo firewall-cmd --reload
6. Add a client
Generate a key pair for the client. You can do this on the server and copy the config over:
$ sudo sh -c 'umask 077; wg genkey | tee client1.key | wg pubkey > client1.pub'Add the client's public key to the server config as a peer, then reload:
[Peer] PublicKey = PASTE_CLIENT1_PUBLIC_KEY AllowedIPs = 10.8.0.2/32
$ sudo systemctl restart wg-quick@wg0The client's own config, using the server's public key and public address:
[Interface] PrivateKey = PASTE_CLIENT1_PRIVATE_KEY Address = 10.8.0.2/32 DNS = 1.1.1.1 [Peer] PublicKey = PASTE_SERVER_PUBLIC_KEY Endpoint = 203.0.113.10:51820 AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 25
AllowedIPs = 0.0.0.0/0, ::/0 sends all traffic through the tunnel. To reach only the servers on the VPN and leave normal browsing alone, use 10.8.0.0/24 instead. PersistentKeepalive = 25 stops home and mobile routers from dropping the connection while it is idle.
Import that file into the WireGuard app on your phone or laptop, or save it as /etc/wireguard/wg0.conf on a Linux client and run sudo wg-quick up wg0.
Each client needs its own key and its own address
Do not reuse one config on several devices. The AllowedIPs line on the server maps one address to one key, so two devices sharing a key will knock each other offline. Give each device the next address in the range: 10.8.0.3, 10.8.0.4, and so on.
7. Check that it works
On the client, after connecting, confirm your traffic leaves through the server:
$ curl -4 ifconfig.meIt should print your VPS address, not your home address. On the server, sudo wg show lists each peer with the time of its last handshake.
Common problems
- Clients connect but nothing loads: the MASQUERADE interface name is wrong, or IP forwarding is off. Check
ip route | grep defaultandsysctl net.ipv4.ip_forward. - Everything breaks after a reboot: you ran
wg-quick upbut never enabled the service. Runsudo systemctl enable wg-quick@wg0. resolvconf: command not foundon a Linux client: installopenresolv, or remove theDNSline and set DNS yourself.
Quick reference
| Task | Command |
|---|---|
| Status and handshakes | sudo wg show |
| Start and enable | sudo systemctl enable --now wg-quick@wg0 |
| Apply config changes | sudo systemctl restart wg-quick@wg0 |
| Find outgoing interface | ip route | grep default |
| Client test | curl -4 ifconfig.me |
Where to go next
A VPN between two of your own servers uses the same steps, with the second server as the client and AllowedIPs set to the private range instead of everything. That is also how you link servers in different locations, since a private network inside one location does not stretch between them.