Build a WireGuard VPN
Install WireGuard and create keys
Install the tools on Ubuntu and generate one protected private and public key pair for each peer.
Let’s install WireGuard on the Ubuntu server. The kernel module ships with modern Ubuntu, so the package mostly adds the wg and wg-quick tools:
sudo apt update
sudo apt install wireguard
Check it worked with wg --version. You should see something like wireguard-tools v1.0.20210914.
Now the keys. Each peer needs its own pair, and the private key must never be readable by other users on the machine. We handle that with umask before creating anything:
umask 077
wg genkey | tee server-private.key | wg pubkey > server-public.key
Here is what that line does. wg genkey prints a fresh private key. tee saves it to server-private.key and passes it along. wg pubkey reads the private key and derives the matching public key, which lands in server-public.key. The umask 077 makes both files readable by your user only.
Both keys are 44 characters of base64. They look like hIhpm5DfIhSNQvvBpG0fWo6yQqYamOoO70QI0DGkfBM=. If yours look different, something went wrong.
On an Ubuntu laptop, install the same package and create a separate pair, this time named laptop-private.key and laptop-public.key. On macOS, Windows, or a phone, install the official WireGuard app first. The app can generate keys for you.
Never copy a private key to the other peer. Each device generates its own pair, on the device, and only the public half ever travels.
After creating the keys, inspect the files before moving on:
ls -l *-private.key *-public.key
wc -c *-private.key *-public.key
The private files should only be readable by your user. Do not compare keys by printing the private value into a terminal recording or chat. Compare public keys instead. Delete this practice pair and create it again once, so key rotation feels like a normal operation rather than an emergency.
The ls -l output should show -rw------- for the private file. If you see -rw-r--r-- instead, you forgot umask 077. Delete the pair and start over. Fixing permissions after the fact is not enough, because the key was already readable for a moment. Cheap to redo now, expensive to explain later.
The wc -c output should be 45 bytes per file: 44 characters plus a newline. A 0 means an empty file, usually because wg was not in your PATH yet and the pipeline silently failed.
Lesson completed