Over the past like 9 months or something I've built up a pretty nice wireguard VPN setup between all my computers at home, a couple of cloud machines, and my roaming devices (phone and laptop). There's a lot going on there that's incredibly specific to my needs, but I figured I would write up some guides on how to achieve various outcomes, since I ended up synthesizing information from a lot of different sources to get where I am now. This is the first and most basic: simply connecting a couple of machines to one another. This guide will cover Linux machines but the process isn't too different for other platforms, you will just have to load the configuration into their respective applications.

prerequisites

it starts with two

We'll start out by connecting two machines to each other over a wireguard tunnel. First, you will need wireguard software installed on each computer. It's available in most distributions' package managers, and there's also downloads on the wireguard website.

Next, choose a subnet for your wireguard network to use. You will want to make sure pick something in a private range that won't collide with the addresses used on your physical network. For the sake of demonstration, I'll choose 10.0.0.0/24.

I'll be using wg-quick for the purposes of this, since it's the easiest way to set up wireguard and it also has some handy-dandy things to prevent you from shooting yourself in the foot. We'll start on the machine with the public IP. In my case, this is a VPS, and I'll say the IP address is 1.2.3.4. First, generate the public and private key for this machine's wireguard device:

$ wg genkey | tee >(wg pubkey)
KAyRe+Y3R/K+5klJqG41jcdDispbP1NAgceFiLww2G0=
GE2rCmCqFmor2Rcbsyo6nO82EvqC+enGaZ561juMuWM=

I've included example keys here. Don't use them. The first output is the private key (generated by genkey) and the second is the public key (generated by pubkey from the input of the private key). Don't lose the private key, but the public key can be regenerated.

Create the file /etc/wireguard/wg0.conf. wg0 will be the name of the network interface that is created, you could make it be anything but for simplicity I'm using wg0. The file will start with an Interface section:

[Interface]
Address = 10.0.0.1/32
# use the key you generated!
PrivateKey = KAyRe+Y3R/K+5klJqG41jcdDispbP1NAgceFiLww2G0=
ListenPort = 51820

In this section, you're setting the private key for the machine, the port that wireguard will listen on (51820 is the default, but you can set it to any open port), and the IP address (on the wireguard network) of this machine. Note that it's a /32, meaning that this machine only can route to its own IP on the VPN.

Next, we'll go to the other machine and generate its keys:

$ wg genkey | tee >(wg pubkey)
iOBPrrvPL6AyshY7r80P4sF61y6sAiDVXoxeXMnrTVI=
7qXRGuP0R9wxHZu7SxJ+tnprUtg85DDO2Mya2wUPyBo=

And also create a /etc/wireguard/wg0.conf and add the Interface section:

[Interface]
Address = 10.0.0.2/32
PrivateKey = iOBPrrvPL6AyshY7r80P4sF61y6sAiDVXoxeXMnrTVI=

Make sure you are using a different IP address. Also, only one of the machines in this case needs to have a consistent port set, so we can omit ListenPort on this host.

Now each machine needs Peer configuration so they know how to communicate with each other. Starting with the one we did first, go into the same wg0.conf file, and add:

[Peer]
# PUBLIC KEY FROM THE SECOND COMPUTER
PublicKey = 7qXRGuP0R9wxHZu7SxJ+tnprUtg85DDO2Mya2wUPyBo=
AllowedIPs = 10.0.0.2/32

Make sure you are not using the public key from this computer, but from the other one. The AllowedIPs value has dual purpose: it both restricts incoming traffic from that peer to that source address, and restricts outgoing traffic to that peer to that destination address.

Back on the second machine, we'll also add a peer to connect to the first:

[Peer]
PublicKey = GE2rCmCqFmor2Rcbsyo6nO82EvqC+enGaZ561juMuWM=
AllowedIPs = 10.0.0.1/32
Endpoint = 1.2.3.4:51820

This looks pretty familiar, just using the IP address that we assigned in the first machine's Interface section. It also has an Endpoint value set: this tells wireguard where to actually send the traffic to.

With both of the machines configured, you can save the files and run

# wg-quick up /etc/wireguard/wg0.conf

on each. You should see some stuff printed out. You should now be able to ping them from one another, e.g.

$ ping 10.0.0.1

from the second computer.

more computers

To add more computers, you will turn your network into a hub-and-spokes sort of shape, where the machine with a public IP (first one we did earlier) is the hub. Just repeat what you did for the second one for each new machine, and add a corresponding Peer section onto the hub. Make sure to use the correct keys and a unique IP address for each peer that you add. All of these peers should now be able to communicate with one another as long as the hub remains available. Unfortunately, without a lot of extra effort, wireguard won't be able to create a true mesh network where individual spoke machines can communicate directly.

conclusion

you have now created a simple wireguard network between a few hosts. it's pretty simple to add more machines to this network, but it can get a bit unwieldy if you have a lot of computers. i'll cover a site-to-site vpn in the next post, which can help to solve this problem depending on your situation.