Setting Up WireGuard VPN on Bare Metal
WireGuard is the modern VPN protocol — faster, simpler, and more secure than OpenVPN or IPSec. With roughly 4,000 lines of code versus OpenVPN's 100,000+, the attack surface is minimal. Here is how to set up a full WireGuard VPN on your own bare metal server.
Why Self-Host Your VPN
Commercial VPN services route your traffic through shared infrastructure you do not control. Self-hosting on bare metal gives you a dedicated exit node with known hardware, zero logging guarantees you can actually verify, and no monthly VPN subscription fees. On a RAW server at $6/mo, you get a private VPN with 20 TB bandwidth included.
Step 1: Install WireGuard
# Deploy a RAW server and SSH in
npx rawhq deploy
ssh root@your-server-ip
# Install WireGuard
apt update && apt install -y wireguard
# Enable IP forwarding
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
sysctl -pStep 2: Generate Server Keys
WireGuard uses Curve25519 key pairs. Generate the server's private and public keys:
# Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
# View the public key (you will need this for clients)
cat /etc/wireguard/server_public.keyStep 3: Server Configuration
Create the server config at /etc/wireguard/wg0.conf:
[Interface]
# Server private key
PrivateKey = SERVER_PRIVATE_KEY_HERE
Address = 10.0.0.1/24
ListenPort = 51820
# NAT for client internet access
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
# Client 1 (laptop)
[Peer]
PublicKey = CLIENT_1_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
# Client 2 (phone)
[Peer]
PublicKey = CLIENT_2_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32Step 4: Client Configuration
On each client device, generate keys and create the config:
# Generate client keys (run on client or server)
wg genkey | tee client_private.key | wg pubkey > client_public.keyClient config file (wg0.conf):
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = your-server-ip:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25Step 5: Start and Enable
# Start WireGuard on the server
wg-quick up wg0
# Enable on boot
systemctl enable wg-quick@wg0
# Check status
wg showOn the client, import the config into the WireGuard app (available for macOS, Windows, iOS, Android, and Linux) or run wg-quick up wg0 on Linux.
Multi-Client Setup
Adding more clients is straightforward. For each new device:
- Generate a new key pair
- Add a [Peer] block to the server config with the client's public key and a unique IP (10.0.0.4/32, 10.0.0.5/32, etc.)
- Create a client config pointing to the server
- Reload the server:
wg syncconf wg0 <(wg-quick strip wg0)
WireGuard supports hundreds of peers on a single interface with negligible overhead.
Kill Switch
A kill switch prevents traffic from leaking outside the VPN tunnel if the connection drops. Add these firewall rules to your client config:
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 1.1.1.1
# Kill switch: block all traffic except WireGuard
PostUp = iptables -I OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
Endpoint = your-server-ip:51820
AllowedIPs = 0.0.0.0/0WireGuard vs OpenVPN: Performance
WireGuard runs in kernel space, which eliminates context switching and delivers 2–4x the throughput of OpenVPN. On dedicated bare metal hardware with no hypervisor overhead, WireGuard can saturate a 1 Gbps link at under 5% CPU usage.
Why Bare Metal for VPN
VPN performance depends on raw CPU speed and network throughput — exactly what shared VMs throttle. On RAW bare metal, you get dedicated cores, dedicated NIC bandwidth, and consistent performance under load. No noisy neighbors, no virtualization overhead, and 20 TB bandwidth included at $6/mo.