WireGuard Config Builder
Assemble a ready-to-save WireGuard config from your own keys and settings — every key is checked as a 32-byte base64 key, every Address/AllowedIPs/DNS entry and every port is validated. Runs in your browser; nothing is uploaded.
About this tool
This builder turns the values you already have — your interface private key, the peer's public
key, addresses, endpoint and AllowedIPs — into a complete, ready-to-save WireGuard config file
(wg0.conf). Unlike a plain template, every field is validated before the file is produced:
- Each key must base64-decode to exactly 32 bytes (the Curve25519 key length), so a truncated or mistyped key is rejected with a clear message instead of silently producing a config that never connects.
- Every Address, AllowedIPs and DNS entry is parsed as a real IPv4/IPv6 address, and CIDR prefixes are range-checked (0–32 for IPv4, 0–128 for IPv6).
- The Endpoint is checked as
host:port(IPv6 literals must be bracketed,[2001:db8::1]:51820), and every ListenPort, MTU and PersistentKeepalive value is range-checked.
Everything runs locally in your browser via WebAssembly — your keys are never uploaded.
This tool does NOT generate keys
By design, it validates and assembles keys you paste; it does not create them. Key generation
needs a cryptographically secure random source and is non-deterministic, which does not fit a
recompute-on-input page. Generate your keypair first with the official wg tools:
wg genkey | tee privatekey | wg pubkey > publickey # interface keypair
wg genpsk > preshared # optional preshared key
Then paste the interface PrivateKey, the peer's PublicKey, and (optionally) the PresharedKey into the fields above.
Worked example
For a full-tunnel client — private key AAAA…AAA=, address 10.0.0.2/32, DNS 1.1.1.1, 8.8.8.8,
peer public key MTIz…MDEy=, AllowedIPs = 0.0.0.0/0, ::/0, endpoint vpn.example.com:51820,
keepalive 25 — the tool emits:
[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Address = 10.0.0.2/32
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25
Save that as wg0.conf and bring it up with wg-quick up ./wg0.conf.
Full tunnel vs. split tunnel
AllowedIPs on the peer decides what traffic goes through the tunnel:
0.0.0.0/0, ::/0— a full tunnel: route all IPv4 and IPv6 traffic through the peer (a typical VPN client).10.0.0.0/24(or any specific subnet) — a split tunnel: only that subnet is routed through WireGuard; everything else uses your normal connection.
Limits and edge cases
- Single interface, single peer. The form assembles one
[Interface]and one[Peer]. Hub configs with many peers are outside this tool's scope — assemble each peer block separately. - No key generation and no QR export. Paste keys from
wg genkey/wg pubkey; QR/image output has no text-page render mode here. - Fields left blank are simply omitted, so a roaming client with no
ListenPortor a server with noEndpointboth produce a clean file.
FAQ
Does this tool generate my WireGuard keys?
No. It validates and assembles keys you paste — it never creates them. Generate a keypair with
wg genkey | wg pubkey (and wg genpsk for an optional preshared key), then paste the values in.
Key generation needs a secure random source and can't be a deterministic page function.
What should I put in AllowedIPs?
Use 0.0.0.0/0, ::/0 to route all traffic through the peer (a full VPN tunnel), or a specific
subnet such as 10.0.0.0/24 for a split tunnel that only routes that network. Each entry is a
CIDR and is validated; you can list several separated by commas.
Why is my key rejected as "not 32 bytes"?
WireGuard keys are Curve25519 keys: exactly 32 raw bytes, which base64-encode to a 44-character
string ending in =. If your input decodes to a different length it was truncated, mistyped, or
isn't a WireGuard key. Re-copy the full output of wg genkey/wg pubkey.
How do I write an IPv6 endpoint?
Bracket the IPv6 literal and put the port after the bracket: [2001:db8::1]:51820. A bare
2001:db8::1:51820 is ambiguous (the last group looks like the port) and is rejected. Domain names
and IPv4 endpoints use the plain host:port form, e.g. vpn.example.com:51820.
Do I need ListenPort, MTU or PersistentKeepalive?
All three are optional. A roaming client can omit ListenPort (WireGuard picks a random port);
MTU defaults to 1420 and only needs changing if you see fragmentation; set
PersistentKeepalive to 25 when this side is behind NAT so the tunnel stays open. Blank fields
are left out of the file entirely.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool wireguard-config-builder "gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=" 'address=10.0.0.2/32, fd00::2/128' 'peer_public_key=HIgo9xNzJMWLKASShiTqIybxih0kSDAVY+kSyKHXWJU=' 'allowed_ips=0.0.0.0/0, ::/0'New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
https://gizza.ai/tools/wireguard-config-builder/?private_key=gI6EdUSYvn8ugXOt8QQD6Yc%2BJyiZxIhp3GInSWRfWGE%3D&address=10.0.0.2%2F32%2C%20fd00%3A%3A2%2F128&listen_port=51820&dns=1.1.1.1%2C%208.8.8.8&mtu=1420&peer_public_key=HIgo9xNzJMWLKASShiTqIybxih0kSDAVY%2BkSyKHXWJU%3D&preshared_key=K5W7q%E2%80%A6%20%28optional%29&allowed_ips=0.0.0.0%2F0%2C%20%3A%3A%2F0&endpoint=vpn.example.com%3A51820&persistent_keepalive=25&format=confMachine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
