Configure and Verify a WireGuard Interface with wg
You will generate a WireGuard key pair, prepare a small configuration file for one peer, apply it to an existing interface, and check whether traffic has actually exchanged. This guide uses the installed wg from wireguard-tools version 1.0.20210914-1ubuntu4, reporting upstream version 1.0.20210914.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 20 minutes if the interface already exists and you have the peer's public key and network details. You need a shell, the wg command, an existing WireGuard interface such as wg0, and the peer's endpoint and allowed addresses. Creating the interface and assigning its IP address are separate jobs handled by ip-link, ip-address and usually wg-quick.
1. Check the command and interface
Start with read-only checks. These do not require elevated privileges on a normal installation:
$ command -v wg
/usr/bin/wg
$ wg show interfaces
wg0
Your interface list may be empty, or it may contain a different name. Substitute that exact name below. The command uses show when no subcommand is given, but writing the subcommand makes scripts and reviews clearer:
$ sudo wg show wg0
sudo is shown because the kernel may restrict configuration reads. Use it only if an unprivileged wg show wg0 cannot read the device. A successful read prints the interface's public key, listening port and peers. It normally hides private and preshared keys.
Checkpoint
Stop here if wg0 does not exist. Do not try wg set wg0 ... as a way to create it. Create the link through your normal WireGuard network setup, then return to this guide.
2. Generate keys without exposing them on the command line
Private keys should not appear in shell history or in a process argument list. Create a protected directory and generate a private key there:
$ install -d -m 700 "$HOME/wireguard-keys"
$ umask 077
$ wg genkey > "$HOME/wireguard-keys/wg0-private.key"
$ wg pubkey < "$HOME/wireguard-keys/wg0-private.key" > "$HOME/wireguard-keys/wg0-public.key"
$ stat -c '%A %n' "$HOME/wireguard-keys" "$HOME/wireguard-keys/wg0-private.key"
drwx------ /home/you/wireguard-keys
-rw------- /home/you/wireguard-keys/wg0-private.key
The exact home directory in stat will differ. wg genkey prints a random private key, and wg pubkey calculates the corresponding public key from standard input. Give the public key to the peer administrator through an authenticated channel. Never paste the private key into chat, a ticket or a world-readable configuration.
If this is a new key and you need to abandon it, remove both files before creating replacements. That is irreversible, so first check that the keys are not already used by a live peer:
$ sudo wg show wg0 public-key
$ sudo wg show wg0 dump
3. Write a peer configuration file
Make a temporary configuration with the interface's private key and one peer. Replace every uppercase placeholder. The peer's PublicKey is not your own public key.
[Interface]
PrivateKey = /home/you/wireguard-keys/wg0-private.key
ListenPort = 51820
[Peer]
PublicKey = PEER_PUBLIC_KEY_BASE64
Endpoint = vpn.example.net:51820
AllowedIPs = 10.20.0.0/24
PersistentKeepalive = 25
In a wg configuration file, PrivateKey is a base64 key value, not a file path. The example above is therefore a template for a tool that expands file references, not a file that wg setconf can consume directly. Create the actual file with the key content inserted without printing it:
umask 077
private_key=$(cat "$HOME/wireguard-keys/wg0-private.key")
cat > /tmp/wg0.conf <<EOF
[Interface]
PrivateKey = $private_key
ListenPort = 51820
[Peer]
PublicKey = PEER_PUBLIC_KEY_BASE64
Endpoint = vpn.example.net:51820
AllowedIPs = 10.20.0.0/24
PersistentKeepalive = 25
EOF
chmod 600 /tmp/wg0.conf
Review the file before applying it. AllowedIPs controls both which incoming addresses are accepted for the peer and which outgoing destinations are directed to it. Use 0.0.0.0/0 only when you deliberately want this peer to be the IPv4 default route. A broad value can interrupt management access or send unrelated traffic into the tunnel.
PersistentKeepalive = 25 is useful when this host sits behind a stateful NAT and needs to remain reachable while otherwise idle. It is off by default, and most peers do not need it.
4. Apply the configuration with the least disruption
Warning
Configuration changes can alter routes and peer access immediately. Keep an existing administrative session open and have a rollback plan before applying a default route or changing a production peer.
For a first complete replacement, use setconf:
$ sudo wg setconf wg0 /tmp/wg0.conf
$ sudo wg showconf wg0
setconf makes the interface match the file. It can remove peers that are not present in the file, so do not use it with an incomplete multi-peer configuration. The output of showconf is in the same configuration format, but private keys are normally hidden when using the human-readable show command.
If the interface already carries live sessions and you have a complete intended configuration, syncconf changes only values that differ. The installed manual describes it as less efficient than setconf, but less disruptive to current peer sessions:
$ sudo wg syncconf wg0 /tmp/wg0.conf
addconf appends peer configuration, but it is easy to misuse when you meant to replace a peer. Prefer a reviewed complete file and one of the two commands above.
To undo this example, reapply the last known-good configuration file with wg setconf, or restore the previous service-managed configuration. Do not delete the interface as a rollback shortcut if other services depend on it.
5. Verify keys, endpoint and handshake
Inspect the configured interface without revealing secrets:
$ sudo wg show wg0
interface: wg0
public key: YOUR_INTERFACE_PUBLIC_KEY
private key: (hidden)
listening port: 51820
peer: PEER_PUBLIC_KEY_BASE64
endpoint: 203.0.113.20:51820
allowed ips: 10.20.0.0/24
latest handshake: 42 seconds ago
transfer: 1.20 KiB received, 1.05 KiB sent
persistent keepalive: every 25 seconds
Public keys, endpoints and byte counts vary. The useful evidence is an endpoint, a recent handshake and transfer counters that change when you send expected traffic. A configured peer with no handshake is not proof that the tunnel works.
For scripts, request selected fields or machine-friendly output:
$ sudo wg show wg0 latest-handshakes
PEER_PUBLIC_KEY_BASE64 1720000000
$ sudo wg show wg0 transfer
PEER_PUBLIC_KEY_BASE64 1228 1075
The handshake timestamp is Unix time. An old or zero value usually means to check the endpoint, UDP reachability, both sides' public keys, allowed addresses and firewall rules. The wg command does not configure those surrounding network controls.
6. Use safe diagnostics when something fails
Ask for the exact configuration syntax before editing a production file:
$ wg set --help
$ wg show --help
Do not put a private key directly after wg set. The manual warns that command-line arguments are not private on most systems. If you must use the imperative form, supply the key through a protected file or Bash process substitution, and check permissions first.
To identify whether a problem is on this host, compare these read-only values with the peer administrator's record:
- this interface's public key;
- the peer's public key;
- the endpoint hostname and UDP port;
- the non-overlapping allowed address ranges;
- the latest handshake and transfer counters.
Do not enable debugging or reload kernel modules as a first response. If ordinary checks are inconclusive, schedule any service-disrupting diagnostic work and capture the current wg show output first. Remove /tmp/wg0.conf after the configuration has been handed to its service manager:
$ rm -- /tmp/wg0.conf
This removes the temporary copy, not the live interface configuration or the protected private-key file. If a service such as wg-quick owns the interface, make the durable change in its managed configuration and reload it through that service's documented workflow instead of leaving a one-off wg setconf change behind.
Done means
wgand the target interface were identified before any change.- The private key is protected, and only its public key was shared with the peer.
- The configuration uses the correct peer key, endpoint and narrowly reviewed
AllowedIPs. setconforsyncconfwas chosen knowingly, with a rollback path.wg showreports the expected peer and a recent handshake with changing transfer counters.- Temporary configuration copies were removed, while the interface and service remain intentionally configured.