Skip to content

Your Private Wireguard Network from Scratch

Let's learn how to set up our own private network for secure self-hosted services.

T
Jan 30, 20258 min read

ata centers. The "cloud." If you haven't yet recognized it for the threat it is, now's the time. In this era, entrusting your sensitive data to third parties is not the safest bargain, and may be downright dangerous, depending on your situation.

<!--more-->

I don't know if you've noticed, but data centers are now directly an instrument of an oppressive regime. The grift is quite clear: lock people into cloud services; charge an arm and a leg for them; and keep building data centers to meet "demand." Oh, and since we'll need something to power those data centers, let's enrich energy companies by building nuclear reactors instead of investing in renewable energy and upgrading transmission lines.

Self-hosting the things you used to put on the cloud might be appealing for you. Problem is, you'd like to be able to access your devices from anywhere. The solution is a virtual private network, or VPN. If you work remotely, you almost certainly are familiar with the process of connecting to a VPN to access your organization's network assets. Individuals can set up the same

Wireguard Basics

WireGuard is a secure, encrypted networking protocol intended to be much simpler than traditional VPNs. Its core concept is the association of nodes in an ad-hoc network with asymmetric keys. It's these keys that are used for authentication, keeping access simple to secure and maintain. WireGuard runs on pretty much everything—including mobile devices. That makes is ideal as a way to create a private network for you and your family.

Before we go too far, let's get some Wireguard terms out of the way.

Peer: Any member of a Wireguard network

Endpoint: A Wireguard Peer that receives Wireguard tunnels to join peers to the network. Endpoints can be thought of as "servers."

Subnet Router: A specialized Peer that can provide access to one or more non-Wireguard subnets it is connected to

"Lighthouse" Server: This isn't really a Wireguard term; it's my term for a Wireguard Peer that serves as the Endpoint for every other Peer in the network, because every Peer can connect to it

There are plenty of commercial implementations of Wireguard. Probably the best-known (and best-regarded) is Tailscale. And Tailscale is indeed fantastic! But in the spirit of owning as much of our stack as possible, I'm going to show you how to implement a Wireguard-based network from scratch, without third-party tools.

Well, almost.

By the end of this, you may well understand why people decide to offload this effort to Tailscale. You've been warned.

Network Design

Our design involves a cloud-hosted virtual machine that serves as a "lighthouse" for all our devices to be able connect to each other, from anywhere in the world. This might seem like a compromise in the notion of "no dependencies," but it's an important tradeoff: the use of the cloud server means we don't have to open up any ports on our home router.

Our network topology looks a little like this:

!wireguard network diagram showing all hosts connecting to lighthouse

The "Lighthouse" serves as the connection point for all members of our private network. Each Peer will reach out to the Lighthouse as an Endpoint, providing a public key for authentication and authorization. Each Peer, in turn, has a copy of the Lighthouse's public key for mutual trust. The nodes are configured to connect using a given IP address in a predetermined subnet. The lighthouse has a record of each node's public key, and associates that identity with a given IP address it will accept traffic from.

It's worth noting that Tailscale performs some additional tricks so that while a central server is required to initally connect and configure hosts, the traffic actually sent is peer-to-peer, without a central server in the middle, which is what we'll be doing. To use a Lighthouse is to accept that the intermediary server will see the traffic between hosts. This is the tradeoff for not opening your home router to the internet. Consider your threat model. But also remember that even though the Wireguard decryption terminates at the Lighthouse, any interior encryption—such as HTTPS, SSH, or TLS-encrypted RDP traffic—remains secure.

This design is slightly different from a more traditional "Road Warrior" design, which connects directly to a home router and uses Network Address Translation (NAT) to allow Wireguard to cross from the internet into the home network.

!road warrior wireguard diagram

In some road warrior designs, the home router itself can be the subnet router. So why not use this design? You can, if you like. But we are favoring the lighthouse approach to preserve the security and anonymity of our home router. By allowing the lighthouse to be our connection point, we do not have to expose a Wireguard port on our home router.

So the tricky part is generating those keys and configs. But don't worry; this article comes complete with a Bash script to help you out!

There's one additional component that is a _little_ more special in our setup. If you have a homelab, you may want to gain access to the entire lab directly, rather than connecting to a jumpbox in the lab. So while we're setting up Wireguard, we can also set up a virtual machine in our lab as a subnet router to provide direct access to the lab subnet(s) while connected to our Wireguard network. This is completely optional, but handy to have if you use a virtual homelab network for some of the resources you'd want to access remotely.

As far as Wireguard is concerned, the subnet router is just another Peer—except that we'll use nftables to write rules that forward traffic intended for the lab subnet. More on that later.

Let's start setting up our Peers. We'll begin with the Lighthouse itself.

Wireguard Setup

Lighthouse Server

First, you'll need a Linux virtual machine of your choice, on a cloud service provider of your choice. Be sure to set up SSH access, but limit the access to only your home IP. This ensures that your server is safe from opportunistic brute-force attacks against exposed SSH ports.

You'll also want to choose a UDP port for incoming Wireguard connections. The default is 51820, so I recommend choosing something else. 51888 perhaps? It's up to you, but just be aware that using the default port, which has to be open to the internet, will make the server more likely to attract scanners and attacks of opportunity.

Not sure what your home IP is? A visit to https://www.whatismyip.com will sort you out.

With the virtual machine up and running, log in via SSH. You'll want to install Wireguard straight away.

Ubuntu/Debian:

Fedora/Red Hat/Rocky

Now we're ready to start building our config files. This is the part that tools like Tailscale handwave away. Personally, I think it is valuable to understand how this works, especially if you rely on it for your privacy and security.

Wireguard uses specially-formatted text files to stand up its interfaces. Each config file has at least an [Interface] section that defines how the Wireguard network interface will be configured on the system. You can also have any number of [Peer] entries that define what Peers you connect to, what Peers can connect to you, and how you handle them.

Let's begin by creating our public and private keys for the server. We'll use those to populate our config file. The wireguard-tools we just installed contain the wg command, which provides the genkey subcommand, which creates a private key, and a pubkey subcommand, which takes the aforementioned private key and produces a public key. We're gonna save both to variables in our shell session.

You can echo these if you want to confirm the commands worked.

We need two more values before we can easily write the starting config file: a subnet of choice, and your listening port.

The listening port should already be decided based on the security rules you set up for your cloud VM. That same port is what we'll use, and save to a shell variable.

The subnet can be any RFC 6890 private address space, but I recommend something like 192.168.100.0/24 to keep it simple. The Lighthouse will take .1 in that subnet, and Peers will take subsequent addresses as needed. Wireguard networks don't really use DHCP; it's all static assignment. That's why tools like Tailscale are so valuable for larger deployments, but we're keeping it simple.

Assign that address to another shell variable.

Finally, we can generate our starter config file. We'll write it to /etc/wireguard/lighthouse.conf. We'll use a cool Bash trick to do it: here documents.

Make sure to do this as root or use sudo.

I love this technique for writing text to a file while honoring shell variables. You can sudo cat /etc/wireguard/lighthouse.conf to confirm the file looks right.

One more thing before we're finished with the Lighthouse server. We need to enable IP forwarding on this machine so that traffic intended for other destinations can make it there.

We do this in two ways: a temporary way for the current boot, and a permanent way that will persist after reboot. To start IPv4 forwarding right away:

And to set that permanently:

Now, let's bring up the Wireguard interface, and make sure it comes up automatically on reboots.

The Lighthouse is ready to go—for now. We'll need to modify the config to add our Peers, once we have some.

So let's make some.

Computer Setup: Windows/macOS

As much as I'd love for everyone to run Linux, I recognize that's not reality. We'll begin configuring our roaming devices with a Windows or macOS laptop.

Luckily, Wireguard makes installers available for both operating systems. For Windows, there's a direct installer download. For macOS, Wireguard is available in the App Store. Follow the normal installation process there.

Oh hey, you will want to grab the Lighthouse server's public key from its configuration. Make it available to paste into your Wireguard client. Maybe send yourself a Signal message? However you do it, do it s

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions