Setup WireGuard VPN on Linux
A practical, no‑fluff guide to install and configuring a secure WireGuard VPN server and client on Linux.
Published on Jul 10, 2026
Introduction
WireGuard is a modern, fast, and lightweight VPN protocol that uses state-of-the-art cryptography to create secure tunnels between machines. Unlike older VPN solutions, it is designed to be simple, lightweight and easy to configure which makes it well-suited for self-hosted setups on a single server and a few clients or scale it to a commercial VPN service.
This guide will walk you through setting up your own WireGuard VPN on a Linux server, explaining how to install WireGuard, generate the keys, configure the server and client, and make sure the connection is secure and functional. By the end, you’ll have a working VPN you can use to protect your traffic, access remote networks, or connect devices securely over the Internet.
Architecture Overview
WireGuard uses a peer-to-peer architecture, meaning every machine is technically equally a server as a client, each has its own private and public key pair, and “server” vs “client” is just a matter of how you configure routing and the purpose of tha machine. In practice, you usually designate one machine as the central hub (the VPN server) that the clients connect to and route traffic through.
The connection between two peers is defined by:
- A private key (kept secret on each machine).
- A public key (shared with each other).
- A
AllowedIPslist that tells WireGuard which IP ranges will be routed over the tunnel. - An
Endpoint(IP and port) that clients use to reach the server.
When a client sends traffic to an IP in AllowedIPs, WireGuard encrypts the packet, sends it to the server’s endpoint, the server decrypts it, and then forwards it according to its routing rules. If IP forwarding and NAT are enabled, the server can also send the traffic out to the Internet and pass the replies back through the tunnel, effectively making the VPN act as a secure gateway.
Installing WireGuard
WireGuard is available in the official repositories of most modern Linux distributions, modern kernels come with the WireGuard kernel module, you only need to install the user-space tools to manage keys, configuration, and interfaces.
apt install wireguarddnf install wireguard-toolspacman -S wireguard-toolsapk add -U wireguard-toolsAfter installing, you can quickly confirm that WireGuard is available with:
wg --version Disclaimer: While modern Linux kernels (Version 5.6 from March 2020 and after) include WireGuard natively in the kernel, a full user-space implementation is also available. The user-space version (often named
wireguard-go) can be used on older kernels.
Key Generation
Each peer in a WireGuard setup needs its own key pair: a private key that stays on the local machine, and a public key that is shared with the other peers. To generate such a key pair you can run the following command:
wg genkey | (umask 0077 && tee private.key) | wg pubkey > public.pub This creates:
private.key- must be kept private and never exposed.public.key- you’ll reference this in the[Peer]section of the other machine’s configuration.
IPv4 and IPv6 Addresses
When setting up WireGuard, you need to pick one or two private subnets that will be used only for the VPN itself. These addresses are not exposed to the internet directly; they only exist inside the tunnel between your server and clients.
For IPv4, a common choice is a small private range from the reserved ranges that does not collide with any other private ranges in use on the network:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
For IPv6 you can choose a range from the private ULA (Unique Local Address) range:
- fd00::/8
For this example we will use the following ranges:
- IPv4: 192.168.255.0/24
- IPv6: fd00:ffff::/64
Server Configuration
Now that you have your keys and address ranges chosen, it’s time to create the actual configuration files. This file lives at /etc/wireguard/wg0.conf and defines your server’s own tunnel identity in the [Interface] section, along with one [Peer] blocks for every client that is allowed to connect.
[Interface]
PrivateKey = <server private key>
Address = 192.168.255.10/24, fd00:ffff::10/64
ListenPort = 51820
[Peer]
PublicKey = <client public key>
AllowedIPs = 192.168.255.20/32, fd00:ffff::20/128 To automatically start the WireGuard tunnel on boot you should enable it as a systemd service:
sudo systemctl enable --now wg-quick@wg0.service Server Network Configuration
By default, Linux does not forward packets between network interfaces. Since WireGuard needs to receive traffic from the client on the wg0 interface and forward it out to the Internet or other clients, this behavior needs to be explicitly enabled. This can be done by putting the following lines in /etc/sysctl.d/forwarding.conf:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1 To apply the new rules you can simply run:
sudo sysctl -p Client Configuration
With the server side listening and ready to accept connections, each client needs its own configuration file. also stored at /etc/wireguard/wg0.conf on Linux or imported directly into the WireGuard app on desktop and mobile.The client’s [Interface] section holds its own private key and the internal tunnel address you assigned it. The [Peer] section points back the the server using the Endpoint field which specifies the “public” IP of the server, the public key of the server and the AllowedIPs field which specify what address ranges should be routed through the WireGuard tunnel.
[Interface]
PrivateKey = <client private key>
Address = 192.168.255.20/24, fd00:ffff::20/64
ListenPort = 51820
[Peer]
PublicKey = <server public key>
Endpoint = <server ip>:51820
AllowedIPs = 0.0.0.0/0, ::/0 To start the tunnel on a Linux machine, you can use the following command or if you want it to automatically start reuse the same command as the server:
sudo wg-quick up wg0 Optimization and Hardening
With a working tunnel in place, the following sections cover ways to tighten up your deployment beyond the defaults. Protecting the keys, thinking ahead to cryptography that may need to change as new threats emerge and ways to bypass Deep Packet Inspection (DPI) systems.
Safe Key Storage
Private keys and the configuration files should never be world-readable. By default, wg-quick expects config files to live in /etc/wireguard, so to lock the whole directory down, run the following commands:
sudo chmod 700 /etc/wireguard
sudo chmod 600 /etc/wireguard/wg0.conf For an extra layer of security, store the private and public keys in a secrets manager or encrypted vault rather than flat files.
Quantum Resistance
WireGuard’s handshake relies on Curve25519 for key exchange, which like most elliptic-curve cryptography in wide use today is not resistant to a sufficiently large quantum computer running Shor’s algorithm. This isn’t a near-term practical risk, but an adversary could record encrypted traffic now and decrypt it later.
WireGuard itself has no built-in post-quantum key exchange, and the upstream project has been deliberately conservative about adding one. In the meantime, the common approach is layering a pre-shared key (PSK) into the handshake with the PresharedKey field in each [Peer] block. This doesn’t make the key exchange itself quantum-resistant, but it does mean an attacker would need to break both the elliptic-curve exchange and the pre-shared key to recover the session key.
Pre-shared keys can be generated with the following command:
wg genpsk AmneziaWG
Standard WireGuard packets have a very recognizable structure with fixed header sizes and consistent field patterns that make the protocol trivial to fingerprint with Deep Packet Inspection (DPI). In most environments this doesn’t matter, but on networks that actively block or throttle WireGuard traffic, that fingerprint is exactly what gets flagged. This is exactly what corporate networks and countries like Russia, China and the Middle East rely on to detect and block VPN traffic at the corporate and national firewall level.
AmneziaWG is a WireGuard fork that addresses this by obfuscating the handshake and transport packets by adding configurable junk packets, randomizing header fields and adding padding to avoid fingerprinting. It also supports protocol masking which mimics QUIC, DNS, SIP or other UDP protocols commonly less likely to be firewalled.
The AmneziaWG configuration file is fully interoperable with the configurations we already built above, the extra obfuscation parameters just get added as additional fields in the same [Interface] section.
Conclusion
At this point you have a working WireGuard tunnel between your server and client, keys locked down with proper file permissions and a couple of paths to consider if you need more than just the defaults. Pre-shared keys as a hedge against future cryptographic attacks, and AmneziaWG if you’re operating somewhere that actively fingerprints and blocks VPN traffic.
Stay updated for new self-hosted, privacy focused and news worthy tutorials and articles via RSS. Questions? Contact Us.