How to Set Up WireGuard Server
Introduction
This is step-by-step guide to set up a WireGuard server.
Understanding WireGuard Basics
How WireGuard Works
WireGuard uses public-key cryptography (similar to SSH) to establish secure tunnels. Each device has: - Private Key: Kept secret on the device - Public Key: Shared with peers - Preshared Key (optional): Additional layer of security
Network Topology
In our setup:
- Server: Acts as the central hub (e.g., 10.0.0.1/24)
- Peers: All client devices (e.g., 10.0.0.2, 10.0.0.3, etc.)
- All traffic is encrypted and routed through the server
Installing WireGuard
On Ubuntu/Debian Server
# Update package list
sudo apt update
# Install WireGuard
sudo apt install wireguard
# Verify installation
wg --version
Generating Keys
Understanding Key Security
Before generating keys, set the proper umask to ensure your private keys are only readable by you:
umask 077
Server Keys
Generate keys for your WireGuard server:
# Navigate to WireGuard directory
cd /etc/wireguard/
# Generate privatekey
wg genkey > privatekey
# Generate publickey from the private key
wg pubkey < privatekey > publickey
# Generate a pair of private and public keys with one command
wg genkey | tee server_privatekey | wg pubkey > server_publickey
Client Keys (Automated Script)
#!/bin/bash
umask = 077
peers=("peerServer" "peerA" "peerB" "peerC")
for peer in "${peers[@]}"; do
wg genkey | tee "${peer}_privatekey" | wg pubkey > "${peer}_publickey"
wg genpsk > "${peer}_presharedkey"
echo "Keys generated for ${peer}:"
echo " - Private Key: ${peer}_privatekey"
echo " - Public Key: ${peer}_publickey"
echo " - Preshared Key: ${peer}_presharedkey"
done
Save this script as generate_peer_keys.sh, make it executable, and run it:
chmod +x generate_peer_keys.sh
./generate_peer_keys.sh
Important: Store these keys securely! Anyone with a private key can access your VPN.
Configuring the Server
Create Server Configuration
Create /etc/wireguard/wg0.conf:
[Interface]
# Server private key
PrivateKey = <SERVER_PRIVATE_KEY>
# Server IP address in the VPN network
Address = 10.0.0.1/32 [or other subnet]
# UDP port for WireGuard (default: 51820)
ListenPort = 51820
# Enable IP forwarding you can also enable it permanently in /etc/sysctl.conf
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
### Peers Configuration ###
[Peer]
# Client's public key
PublicKey = <Peer A PUBLIC KEY>
# Optional: Preshared key for additional security
PresharedKey = <Peer A PRESHARED KEY>
# IP address assigned to this peer
AllowedIPs = 10.0.0.2/32
### Peer B Configuration ###
[Peer]
PublicKey = <Peer B PUBLIC KEY>
PresharedKey = <Peer B PRESHARED KEY>
AllowedIPs = 10.0.0.3/32
Note: Replace eth0 with your actual network interface name. Find it using ip link show.
Set Proper Permissions
sudo chmod 600 /etc/wireguard/wg0.conf
Enable IP Forwarding Permanently
Edit /etc/sysctl.conf:
sudo nano /etc/sysctl.conf
Add or uncomment:
net.ipv4.ip_forward=1
Apply changes:
sudo sysctl -p
Start WireGuard Server
# Start the VPN
sudo wg-quick up wg0
# Enable automatic startup on boot
sudo systemctl enable wg-quick@wg0
# Check status
sudo wg show
Configuring Clients
Client Configuration
Create wg0.conf for each client:
[Interface]
# Client's private key
PrivateKey = <PEER_PRIVATE_KEY>
# Client's VPN IP address
Address = 10.0.0.2/32
# Optional: DNS servers to use when connected
DNS = 1.1.1.1, 8.8.8.8
[Peer]
# Server's public key
PublicKey = <SERVER_PUBLIC_KEY>
# Preshared key
PresharedKey = <PEER_PRESHARED_KEY>
# Server's public IP and port
Endpoint = <SERVER_PUBLIC_IP>:51820
# Route all traffic through VPN (full tunnel)
AllowedIPs = 0.0.0.0/0, ::/0
# Keep connection alive (important for mobile)
PersistentKeepalive = 25
Configuration Options Explained:
- AllowedIPs = 0.0.0.0/0: Routes all traffic through VPN (full tunnel)
- AllowedIPs = 10.0.0.0/24: Routes only VPN subnet traffic (split tunnel)
- PersistentKeepalive = 25: Sends keepalive packets every 25 seconds to maintain NAT mappings
Start the client:
sudo wg-quick up wg0
Network and Firewall Setup
Router Configuration
- Port Forwarding:
- Forward UDP port
51820to your server's local IP -
Example: External
51820→ Internal192.168.1.100:51820 -
Dynamic DNS: If your ISP provides a dynamic IP, set up Dynamic DNS (DDNS) to map a domain name to your changing IP. I am not able to do this as I am using eduroam for most of the time.
Firewall Configuration (UFW)
# Allow WireGuard port
sudo ufw allow 51820/udp
# Allow SSH (important! if you use SSH at port 22 to manage the server)
sudo ufw allow 22/tcp
# Enable firewall
sudo ufw enable
# Check status
sudo ufw status
Testing Your VPN
Verify Server Status
# Check if WireGuard is running
sudo wg show
# Should show connected peers
sudo wg show wg0
Expected output:
interface: wg0
public key: <server_public_key>
private key: (hidden)
listening port: 51820
peer: <peer1_public_key>
preshared key: (hidden)
endpoint: <peer_ip>:<peer_port>
allowed ips: 10.0.0.2/32
latest handshake: 30 seconds ago
transfer: 15.2 MiB received, 8.4 MiB sent
Security Best Practices
- Never share private keys
- Regenerate keys if compromised
- Use preshared keys for additional security
Advanced Configuration
Split Tunneling
To route only specific traffic through VPN (e.g., home network only):
Client configuration:
[Peer]
# Only route home network traffic through VPN
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24