A quick-start guide for setting up WireGuard on Unraid. Benefits of WireGuard include easy deployment, lower latency, and improved battery life.
unRAID 6.8 is soon to be released and within it lies a game changer for all of us, including those new to the homelab to those of us with more "advanced" setups. I am, of course, talking about WireGuard.
What Is WireGuard?
In short, WireGuard is a lightweight VPN server/client embedded in the Linux kernel. What does that mean for you? It's fast.
Why Should You Implement WireGuard?
- Rapid VPN Deployment- If you're new to unRAID or haven't otherwise deployed a VPN, the biggest reason to implement WireGuard is that it's extremely fast to deploy. This stands in stark contrast to deploying the openVPN Docker container which, while certainly faster than deploying an openVPN server from scratch, still takes some effort (and even with the great guides available, you do have to know what you're doing). With WireGuard, we're talking 15 minutes tops, assuming you have the prerequisite dynamic DNS already set up (and if you don't that adds maybe 30 minutes).
- Security- A VPN makes your remote laptop just another device on the network, just as if you were at home. In doing so, this allows you to access all of your network's resources locally. If you don't utilize a VPN, then you have to port forward to make your homelab's local resources available over the internet. Do this enough times and the firewall that separates your home network from the internet starts to look like swiss cheese with all of the holes you've punched through it with those port forwards. VPNs allow you to minimize your network's attack surfaces to a single (very secure) port forward for the VPN server.
- Redundancy- As I have spoken about in the past, a VPN is an essential component of the Unattended Server Checklist. It allows you access to your homelab in the event that something happens and you need to remote in.
Other Niche Benefits of WireGuard
- Low overhead -> Better Battery Life- WireGuard, as described by its developer, isn't a chatty protocol. The client sends its request and then shuts up. It tries to avoid keep alive handshakes if they're not needed. As a result, when you're working on a laptop on wireless, your wireless card has a higher likelihood of being able to idle down which leads to better battery life. (An idle wifi card uses something like ~20 mW at idle but can easily climb to ~2W under load). Anecdotally, in my own testing, I am noticing about a 2-3 hour improvement in battery life when working remotely at a coffee shop on WireGuard compared to openVPN.
- Mosh-like Connectivity- This is part of my core stack for remote development. Mosh allows you to roam seamlessly between IP addresses and bad network connections. I've noticed that WireGuard gives many of the same benefits and when I have a poor network connection in a coffee shop (are there any coffee shops with good wifi connections?), where with openVPN, I would continue working only to find my connection had been dropped and would be interrupted by openVPN attempting to reconnect. In contrast, WireGuard rapidly re-establishes connection without me even knowing. It even works across full IP address changes such as when I change hotspots from AT&T to T-Mobile.
Hopefully by now I've convinced you to implement WireGuard and you're ready to deploy the WireGuard server on unRAID. Let's begin!
WireGuard Implementation on unRAID
- unRAID Server Running 6.8+
- Dynamic DNS Configured- This is outside of the scope of this guide, but thankfully it's relatively simple and available on most routers. You can find either find instructions by Googling, "<Your Router Name> + dynamic DNS" or implementing it directly in unRAID with the legendary SpaceInvader One's guide:
Set Up The WireGuard VPN Server:
1. Go to Community Applications under the "Apps" tab and search for the Dynamix WireGuard plugin. Install it:
2. Go to Settings > VPN Manager:
3. In the tunnel VPN configuration, give the tunnel a name. Also specify your dynamic DNS name in the local endpoint section and generate your keys:
The purpose of this local endpoint information is to tell your client how to find your WireGuard VPN server in the vast world of the internet. That's why a dynamic DNS is used- it translates your home network's public IP address into a URL and keeps it updated any time your public IP address changes.
In my case, this blog is self-hosted (that is, this blog's web server sits on the same network as my unRAID server in my homelab) and therefore I will use my URL as the local endpoint.
Also take note of the port specified (typically 51820), we'll need it to set up port forwarding on the firewall.
4. Set up port forwarding on the router/firewall. This will vary from router-to-router. I use pfSense which leads to the simple rule shown below:
All routers will have this ability (typically under advanced configuration), but if you need help with this step, let me know in the comments below and I'll do my best to help you out.
5. Activate your WireGuard server and set it so that it automatically starts on boot up:
Set Up The WireGuard VPN Client:
6. Click on "Add Peer":
7. Set peer type to "Remote Tunneled Access". Generate the peer private/public keypair and generate the preshared key. Click apply:
Note: I am making a judgement call here with the "peer type of access" to use. My recommendation of "Remote tunneled access" does two things for us that I think most users will want:
- It gives access to the unRAID server as well as the LAN
- It routes all of our internet traffic through the unRAID server (which gives us an additional layer of security instead of just routing our regular internet traffic through whatever our laptop's local connection happens to be). Call me paranoid, but I don't like doing my credit card transactions over a public wifi connection (even if the connection is relatively secure with https).
8. Click the eye next to your new peer listing:
9. This will present you with the configuration for your client. Click download:
10. To be able to use this configuration file, you'll need to download the WireGuard client available here (install it):
11. Add your configuration to the WireGuard client with "Add Tunnel":
12. Click "activate" to test/use your new WireGuard tunnel:
If you are not using a Pi-hole docker container on unRAID, you are now done and can stop here. If you are running a Pi-hole docker container on unRAID, keep reading for the special set up below that will allow you to keep using your Pi-hole docker container.
Special Instructions for Pi-hole with WireGuard on unRAID
Again, all of this is optional. It only applies if you're running a Pi-hole Docker container on unRAID and want to continue using it with your new WireGuard configuration. If you do, you'll likely run into a problem with DNS resolution at this point.
The problem is that Docker, by design, isolates bridged networks from each other:
In terms of Docker, a bridge network uses a software bridge which allows containers connected to the same bridge network to communicate, while providing isolation from containers which are not connected to that bridge network. The Docker bridge driver automatically installs rules in the host machine so that containers on different bridge networks cannot communicate directly with each other. Source: https://docs.docker.com/network/bridge/
(This may be a bit of an oversimplification since I think when you use the "custom" network type in the Docker container, you're actually using an ipvlan network, but the end result is apparently the same).
The way around this is would be to either move to another interface or set up a router-on-a-stick with VLANs. However, I recognize that this isn't necessarily the most practical solution. VLANs carry a lot of overhead in the sense that your network has to be set up for them. And you don't necessarily have a second NIC for the alternative interface option.
In that spirit, I have found a way around having to do either, instead I'll have you first move your unRAID webGUI port off port 80 to a new port and subsequently switch your Pi-hole Docker container over to the host network. Detailed instructions below!
Instructions For Pi-Hole with WireGuard:
For those of you who don't have a homelab exotic enough to have VLANs and who also don't have a spare NIC lying around, I have come up with a solution to make the Docker Pi-Hole container continue to function if you are using WireGuard. Here are the following steps I used to get a functional Pi-hole DNS on my unRAID VM with WireGuard:
1a. Since we're going to change our Pi-hole to a host network, we'll first need to change your unRAID server's management ports so there isn't a conflict with Settings > Management Access:
1. Take your Pi-hole container and edit it. Change the network type to "Host". This will allow us to avoid the problems inherent in trying to have two bridge networks talk to each other in Docker. (Thus removing our need to use a VLAN or set up a separate interface).
You'll also want to make sure the ServerIP is set to your unRAID server's IP address and make sure that DNSMASQ_LISTENING is set to single (we don't want PiHole to take over dnsmasq):
2. We'll need to do some minor container surgery. Unfortunately the Docker container lacks sufficient control to handle this through parameters. For this step, I will assume you have the following volume mapping, modify the following steps as needed:
3. Launch a terminal in unRAID and run the following command to cd into the above directory:
4. We're going to create an additional dnsmasq config in this directory:
5. Inside this dnsmasq configuration, add the following:
Where the listen-address is the IP address of your unRAID server. The reason this is necessary is because without it, we end up with a race condition depending on if the Docker container or libvirt starts first. If the Docker container starts first (as what happens when you set the container to autostart), libvirt seems to be unable to create a dnsmasq which could cause problems for those of you with VMs. If libvirt starts first, you run into a situation where you get the dreaded: "dnsmasq: failed to create listening socket for port 53: Address already in use". This is because without the above configuration, the dnsmasq created by Pi-hole attempts to listen on all addresses. By the way, this should also fix that error for those of you running Pi-hole normally (I've seen this error a few times in the forum and I can't help but wonder if this was the reason we went with the ipvlan set up in the first place).
Now, just restart the container. I tested this and it should not cause any interference with the dnsmasq triggered by libvirt.
Update (12/30/19): If you intend on using a Linux client, as opposed to setting up a Windows client as described above, I have added an additional quick start guide: How to Set Up a WireGuard Client on Linux with .conf File
Update (1/4/20): WARNING: DO NOT add a new client ("peer") to a WireGuard tunnel if you are connected to that same tunnel remotely. Adding a new peer toggles the WireGuard tunnel off which will render you unable to reconnect. All the more reason to always have more than one way into your homelab.
Update (1/18/20): Added special instructions for those of you running the Pi-hole DNS docker container on unRAID.
That's it! You should now be up and running with WireGuard on unRAID.
If you run into any problems and need help troubleshooting, feel free to ask in the comments below (this is always a standing offer, by the way). If you've successfully implemented WireGuard, I'd love to hear how you're using it.