About a year ago, I wrote about how to use OpenVPN to provide secure remote access to your home network and its resources to start building your own private cloud. I have been incrementally adding network services since.
Recently, I’ve started using WireGuard instead of OpenVPN. I’ve found that the configuration is far simpler, while also letting me create what I’ve started to call my “Personal Virtual Private Network” (PVPN).
Instead of simply connecting into your home network, you can use WireGuard to build out a new subnet without regard to the physical location of devices or which networks they’re physically connected to. This allows you to access your personal devices and services from anywhere you have an Internet connection. The devices (peers) are all accessible to one another on your PVPN.
1. Configure Your DNS
The first step is to define which hosts you want on your PVPN. Since I’m using Pi-Hole to block trackers and ads, I was able to define the hosts simply by editing the
/etc/pihole/lan.list file on my Pi-Hole Raspberry Pi system. This file is set up like a standard
hosts file on any modern system.
lan.list file, I already had DNS configuration for the hosts on my “home” network:
# ---------- Home Network ---------- ## Home PC 10.10.10.50 desktop.home media.home # Cellular Connected via Wi-Fi 10.10.10.51 phone.private 10.10.10.52 laptop.private ## Data Backup Devices 10.10.10.100 onsite-backup.home ## Network Service Devices 10.10.10.252 dns.home 10.10.10.254 router.home
If this is the first time you are setting up DNS records for your home network, make sure the DHCP server on your router (or within Pi-Hole) points the MAC addresses of the machines to the corresponding IP addresses referenced in your DNS configuration.
To define the landscape of my PVPN, I can simply use a different domain name (“private”) to easily differentiate my home and private networks. Make sure to choose a different subnet; we’ll use it later when configuring WireGuard.
# ---------- Personal Private Network ---------- ## Network Service Devices 192.168.99.10 wireguard.private 192.168.99.11 dns.private ## Data Backup Devices 192.168.99.20 onsite-backup.private 192.168.99.21 offsite-backup.private ## Cellular Devices 192.168.99.30 phone.private 192.168.99.31 laptop.private ## Home PC 192.168.99.40 home-desktop.private media.private ## Work PC 192.168.99.50 work-desktop.private
Remember that it doesn’t matter where your devices are located physically or what network they’re directly connected to. In my case, I have devices that are on my home network, at work, at an offsite location, and on cellular networks.
After you make changes, you’ll need to run
$ sudo pihole restartdns to restart Pi-Hole and make the changes active.
2. Install WireGuard
For each peer that will be part of your PVPN, install the WireGuard software:
3. Configure Peers
Generating Public and Private Keys for Peers
There are scripts available to manage peers on your PVPN.
I’ve chosen to manage my peers manually, including generating public and private keys, because the configuration is pretty easy.
I use a simple script (
generate-keys.sh) to generate a public/private key pair:
#!/bin/sh PRIVATE_KEY=`wg genkey` PUBLIC_KEY=`echo $PRIVATE_KEY | wg pubkey` echo Private Key: $PRIVATE_KEY echo Public Key: $PUBLIC_KEY
Every time I want to generate the public/private key pair for a peer on my PVPN, I simply run
$ ./generate-keys.sh. Running the script yields output in this format:
Private Key: GOBOeE6LNY6eBDSl/BNX0a6tsMl4I3ggkcBcjoo5wVU= Public Key: 3+2GmFwqhKrjA6f5r83uNUl3YO+BtNwpDYh+HMJwYAI=
For each peer on my PVPN, I can simply copy and paste these keys to the appropriate places (which I’ll cover in the next section).
Primary Peer Configuration
The primary peer (analogous in my mind to a “server”) needs to be accessible on the Internet. Let’s call this machine
pvpn.example.com. In my case, it’s a Raspberry Pi 4 on my home network that’s accessible on my home cable network connection through a port-foward on my home router (port
51820). I set up a CNAME for my domain name to point to the dynamic hostname of my home network cable Internet connection.
As long as the machines on your PVPN have the ability to get to
pvpn.example.com, they will be able to connect. This could be machines far away from your home network or directly connected to it — it does not matter.
After installing WireGuard on my Raspberry Pi 4 (my primary peer), I setup my
/etc/wireguard/wg0.conf configuration as follows:
[Interface] Address = 192.168.99.10/32 ListenPort = 51820 PrivateKey = PRIVATE KEY for wireguard.private PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat - D POSTROUTING -o wlan0 -j MASQUERADE [Peer] PublicKey = PUBLIC KEY FOR dns.private AllowedIPs = 192.168.99.11/32 [Peer] PublicKey = PUBLIC KEY FOR dns.private AllowedIPs = 192.168.99.11/32 [Peer] PublicKey = PUBLIC KEY FOR onsite-backup.private AllowedIPs = 192.168.99.20/32 [Peer] PublicKey = PUBLIC KEY FOR offsite-backup.private AllowedIPs = 192.168.99.21/32 [Peer] PublicKey = PUBLIC KEY FOR phone.private AllowedIPs = 192.168.99.30/32 [Peer] PublicKey = PUBLIC KEY FOR laptop.private AllowedIPs = 192.168.99.31/32 [Peer] PublicKey = PUBLIC KEY FOR home-desktop.private AllowedIPs = 192.168.99.40/32 [Peer] PublicKey = PUBLIC KEY FOR work-desktop.private AllowedIPs = 192.168.99.50/32
Interface section configures the machine itself, while the
Peer sections configure the peers allowed to connect into my PVPN. The
PostDown directives allow routing traffic out to the other machines on the physical network.
Other Peer Configurations
For each “regular” peer that connects to my WireGuard network, I’ve set up two configurations. My first configuration routes all traffic to the private network, including Internet traffic. This is good for use on untrusted networks. These configurations are setup for my
laptop.private peer (
“Personal Private Virtual Network” + Internet Traffic
[Interface] PrivateKey = PRIVATE KEY for laptop.private Address = 192.168.99.31/24 DNS = 192.168.99.11 [Peer] PublicKey = PUBLIC KEY for wireguard.private AllowedIPs = 0.0.0.0/0 Endpoint = pvpn.example.com:51820 PersistentKeepalive = 120
In the WireGuard configuration UI on the peer, ensure that “Block Untunnelled Traffic” is enabled.
“Personal Private Virtual Network” Extension
[Interface] PrivateKey = PRIVATE KEY for laptop.private Address = 192.168.99.31/24 DNS = 192.168.99.11 [Peer] PublicKey = PUBLIC KEY for wireguard.private AllowedIPs = 192.168.99.0/24 Endpoint = pvpn.example.com:51820 PersistentKeepalive = 120
I want my connection to always be active, so I’ve configured my peers to send a keep-alive message every 120 seconds. Otherwise, my peers could drop off the network and become inaccessible to me. This is especially a problem for remote machines that require physical access to regain the connection.
Once you’ve got everything installed and configured, you should be able to connect your peers to your new PVPN. All of the existing services you have already hosted should be accessible as before with OpenVPN. In addition, all of the peers should be able to connect directly to one another, which was not possible using the OpenVPN setup.
We’re another step closer to our self-hosting goal. Later in this series, I’ll cover hosting alternatives to Gmail and Google Photos and building up more network services.
- Setting up OpenVPN
- SMB File Server with Automated Backups using Rsync/Rclone
- Note-taking with Nextcloud & Syncthing
- Movies and Music using Emby
- Protect Yourself Online with Privacy Tools
- Ad and Tracker Blocking with Pi-Hole
- Building a Personal Private Network with WireGuard
- Creating your Own Certificate Authority and Reverse Proxying Services with Caddy
- Note-taking with Standard Notes
- Email, Contacts, and Calendars
- Photos and Home Movies using Custom Tool