WireGuard config generator
Describe the server and who connects to it, and get every config file: the server's wg0.conf, a file for each laptop, phone or server that connects, the commands to start it and the firewall rules. By default the keys are made with wg on your own computer; if you choose, this browser makes them. This page loads no analytics, and nothing leaves it.
Or make the keys in this browser (optional)
For when wg is not at hand, or to scan a QR code from this screen. Your browser makes the keys on this device: they are not sent anywhere, not saved, not put in the link and not measured.
What it does
It writes a complete WireGuard setup for one server and the devices that connect to it: the server's wg0.conf with a [Peer] block for each device, each device's own file with the server as its peer, the commands to start the tunnel on the server, a ufw firewall script, and a QR code for phones when the keys are made here. Addresses come from one tunnel network, which is checked against the networks Docker creates.
How it works
- Every file is written by the same engine as our other Linux tools (@anaroq/linux). Names, addresses, ranges and the interface are checked for form, so a field cannot add a line of its own, and two peers can never claim the same addresses.
- By default the files hold placeholders, and a short script makes every key with wg genkey, wg pubkey and wg genpsk on your computer and writes it in. Our tests run that script and bring the server and its peers up with wg-quick in containers, then check the handshake, the tunnel in both directions and, for a full tunnel, NAT to a host outside it.
- If you make the keys here, the browser's WebCrypto X25519 makes them (or, where a browser lacks it, the bundled tweetnacl library); our tests check that the public key derived from each private key is the one wg pubkey prints, on known keys and on fresh ones.
- This page loads no analytics, its security policy lets it connect only to this site, and nothing is kept in the link or in browser storage.
What each option does
- Address and AllowedIPs
- Each device gets one address on the tunnel network. On the server, a peer's AllowedIPs is that one address: traffic for it goes to that peer, and traffic from it is accepted only with that source. On a peer, AllowedIPs is what goes through the tunnel.
- Full and split tunnel
- A full tunnel sends 0.0.0.0/0 and ::/0 through the server, so all traffic leaves from the server's address. A split tunnel sends only the tunnel network and the networks you list.
- PostUp and PostDown (NAT)
- When the server forwards traffic, wg-quick runs these iptables rules as the tunnel comes up and goes down: forwarding to and from the tunnel is accepted, and the tunnel network is masqueraded out of the server's interface.
- PersistentKeepalive
- A packet every few seconds from the peer keeps the NAT mapping of its router open, so the server can reach a peer that has been idle.
- PresharedKey
- A symmetric key mixed into the handshake, unique to each server and peer pair. It adds protection on top of the key pair and does not replace it.
Example
A server at vpn.example.com and two peers, a laptop and a phone, on a split tunnel over 10.8.0.0/24, with keys left to wg:
# WireGuard interface wg0. Contains a private key: keep it mode 0600.
# Generated by @anaroq/linux 1.0.0 (ANAROQ). Start with: sudo systemctl enable --now wg-quick@wg0
[Interface]
PrivateKey = @SERVER_PRIVATE_KEY@
Address = 10.8.0.1/24
ListenPort = 51820
# laptop
[Peer]
PublicKey = @PEER_1_PUBLIC_KEY@
PresharedKey = @PEER_1_PRESHARED_KEY@
AllowedIPs = 10.8.0.2/32
# phone
[Peer]
PublicKey = @PEER_2_PUBLIC_KEY@
PresharedKey = @PEER_2_PRESHARED_KEY@
AllowedIPs = 10.8.0.3/32
# WireGuard interface laptop. Contains a private key: keep it mode 0600.
# Generated by @anaroq/linux 1.0.0 (ANAROQ). Start with: sudo systemctl enable --now wg-quick@laptop
[Interface]
PrivateKey = @PEER_1_PRIVATE_KEY@
Address = 10.8.0.2/32
# server vpn.example.com
[Peer]
PublicKey = @SERVER_PUBLIC_KEY@
PresharedKey = @PEER_1_PRESHARED_KEY@
AllowedIPs = 10.8.0.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25
#!/usr/bin/env bash
# Makes the WireGuard keys with wg on this computer and writes them into the config
# files in this directory, in place of their @…_KEY@ placeholders. Generated by ANAROQ.
# Usage: bash make-wireguard-keys.sh (needs wireguard-tools: wg genkey, wg pubkey, wg genpsk)
set -euo pipefail
umask 077
command -v wg >/dev/null 2>&1 || { echo 'wg not found: install wireguard-tools first.' >&2; exit 1; }
for f in wg0.conf laptop.conf phone.conf; do
[ -f "$f" ] || { echo "$f is not in this directory." >&2; exit 1; }
done
grep -q '@SERVER_PRIVATE_KEY@' wg0.conf || { echo 'The keys are already filled in.' >&2; exit 1; }
# fill FILE PLACEHOLDER KEY: base64 keys have no | or &, so sed takes them as they are.
fill() {
local tmp
tmp=$(mktemp)
sed "s|$2|$3|g" "$1" > "$tmp"
cat "$tmp" > "$1"
rm -f "$tmp"
}
server_key=$(wg genkey)
server_pub=$(printf '%s\n' "$server_key" | wg pubkey)
fill wg0.conf @SERVER_PRIVATE_KEY@ "$server_key"
# Peer 1: laptop
key=$(wg genkey)
pub=$(printf '%s\n' "$key" | wg pubkey)
fill laptop.conf @PEER_1_PRIVATE_KEY@ "$key"
fill laptop.conf @SERVER_PUBLIC_KEY@ "$server_pub"
fill wg0.conf @PEER_1_PUBLIC_KEY@ "$pub"
psk=$(wg genpsk)
fill laptop.conf @PEER_1_PRESHARED_KEY@ "$psk"
fill wg0.conf @PEER_1_PRESHARED_KEY@ "$psk"
# Peer 2: phone
key=$(wg genkey)
pub=$(printf '%s\n' "$key" | wg pubkey)
fill phone.conf @PEER_2_PRIVATE_KEY@ "$key"
fill phone.conf @SERVER_PUBLIC_KEY@ "$server_pub"
fill wg0.conf @PEER_2_PUBLIC_KEY@ "$pub"
psk=$(wg genpsk)
fill phone.conf @PEER_2_PRESHARED_KEY@ "$psk"
fill wg0.conf @PEER_2_PRESHARED_KEY@ "$psk"
chmod 600 wg0.conf laptop.conf phone.conf
unset server_key key psk
echo 'Done: wg0.conf, laptop.conf, phone.conf now hold their keys. Keep them private (mode 600).'
Limits
- One server, IPv4 tunnel addresses, and peers that connect to the server only: no site-to-site mesh between peers, and not a managed VPN (Tailscale, NetBird and similar tools manage keys and peers for you).
- A full tunnel routes IPv6 into the tunnel too (::/0) and does not give peers an IPv6 address, so IPv6 traffic stops instead of leaking around the tunnel. On a Linux peer whose kernel has IPv6 switched off, remove ::/0 from its file.
- The server steps are for Debian or Ubuntu with ufw and iptables; other systems need their own commands.
- It cannot check that the server is reachable, that the UDP port is open at your cloud provider's firewall, or that the address is right.
- Keys made in the browser are only as safe as the device and the browser; the wg script is the safer default.
Methodology: how the numbers are worked out
Sources
Related
Next step
A free public tool by ANAROQ, a company building compute infrastructure. What ANAROQ is building