Introduction
Hello everybody. I recently bought my first Home Assistant Green and needed a setup for remote access with wireguard. The existing Wireguard Community Add-on did not work for me for two reasons:
-
The community add-on requires port forwarding to my HA Green device. Well, my router is behind a carrier-grade NAT and port forwarding is just too much of a hassle. So the wireguard on my HA Green device has to “dial out” in order to get through CGNAT and firewalls.
-
The community add-on provides support for a server setup only but not for a client setup. I wanted to integrate my HA Green into my existing wireguard VPN as a client, connecting to my existing wireguard server.
So I started to work on a solution. I logged into the device in order to look at the problem from the inside and managed to get it to work within the homeassistant container. I took inspiration from the Wireguard Community Add-on. At the end, I boiled everything down to the most canonical solution and wrote a new add-on.
It took me the better part of a day. So I thought I’d grab the chance to give something back to this great community and decided to share my work. This tutorial will show you how to create a minimal Home Assistant add-on to connect to an existing wireguard server.
Before we begin, please open another browser tab with this Tutorial: Making your first add-on. Our process here is very similar to the description in that tutorial, and we are not going into the details for tasks that are explained there. So when I write things like “start the samba server add-on and navigate to the addons folder”, you can look it up in the other tutorial.
So let’s start.
Building the add-on
- Start the samba server addon and navigate to the addons folder
- Create a new directory called
runwg
. Always inside that directory: - Create the
Dockerfile
ARG BUILD_FROM
FROM $BUILD_FROM
# We need two additional packages for the
# wireguard client:
RUN apk add --no-cache iptables
RUN apk add --no-cache wireguard-tools
# Copy the wireguard configuration file(s)
# and the run script into the container.
COPY rootfs /
COPY run.sh /
RUN chmod 700 /etc/wireguard/*
RUN chmod a+x /run.sh
CMD [ "/run.sh" ]
Please note: if you are on Windows, make sure to use the LF-only line ending convention for all files described in this tutorial.
- Create the file
config.yaml
name: "Run Wireguard"
description: "Run wireguard from config files"
version: "1.0.0"
slug: "runwg"
arch:
- aarch64
- amd64
- armhf
- armv7
- i386
init: false
privileged:
- NET_ADMIN
- Create the file
run.sh
#!bin/sh
echo "Bringing up wireguard interface wg0 ..."
wg-quick up wg0
echo "Sleep 5 seconds ..."
sleep 5
echo "Showing status information for wireguard:"
wg show
while true; do
sleep 99999
done
- Inside
runwg
, create directory treerootfs/etc/wireguard
Now, before we create the file wg0.conf
, let me describe the sample setup we are going to use:
- The HA Green is integrated in a LAN with the address range 192.168.100.0/24 and a router
- The HA Green has a fixed IP address of 192.168.100.100 (in my case, this is archived through a permanent address lease in the DHCP server, but any other method works as well)
- The HA Green wireguard client is going to connect to a VPN with address range 192.168.200.0/24 and has the IP address 192.168.200.2
- The VPN has a reachable wireguard server at
server.myvpn.com:5661
(that could be a cloud instance or a device inside another LAN reachable through dynamic DNS and port forwarding, etc.)
So whenever you see those IP addresses and ranges in this tutorial, you know what you have to change in order to fit your own setup. And of course you have to replace server.myvpn.com
with your own wireguard server address.
Let’s continue.
- Create the file
rootfs/etc/wireguard/wg0.conf
[Interface]
PrivateKey = ___PRIVATE_KEY_HASSIO___
Address = 192.168.200.2/24
# In order to be able to access the Home Assistant frontend and
# other addresses outside of our container, we have to masquerade
# all incoming traffic from the VPN address range.
PostUp = iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 192.168.200.0/24 -j MASQUERADE
[Peer]
PublicKey = ___PUBLIC_KEY_SERVER___
AllowedIPs = 192.168.200.0/24
Endpoint = server.myvpn.com:5661
# Since we are traversing NAT and firewall setups,
# we must keep the connection alive from inside.
PersistentKeepalive = 25
Fill in the required public and private keys (there are plenty of tutorials in the web how to create a key pair for wireguard) and that’s it, the addon is ready. Now install and start your add-on.
Configuring the wireguard server
Now let’s see what we have to do in order to reach our new wireguard node from it’s peers. Let’s start with the wireguard server and two scenarios.
- Scenario one: VPN peers can only access the Home Assistant:
[Interface]
### This is server.myvpn.com
PrivateKey = ___PRIVATE_KEY_SERVER___
Address = 192.168.200.1/24
ListenPort = 5661
### whatever else belongs to your server configuration ###
[Peer]
### Home Assistant
PublicKey = ___PUBLIC_KEY_HASSIO___
AllowedIPs = 192.168.200.2/32,192.168.100.100/32
### other peers ... ###
- Scenario two: VPN peers can access the Home Assistant and other devices on the same LAN (like the router, etc.):
[Interface]
### This is server.myvpn.com, same as above
[Peer]
### Home Assistant
PublicKey = ___PUBLIC_KEY_HASSIO___
AllowedIPs = 192.168.200.2/32,192.168.100.0/24
### other peers ... ###
And that’s it for the server.
Configuring the other peers in the network
For every other peer on the VPN, in order to reach your HA Green, you just have to add 192.168.100.100/32
(scenario one) or 192.168.100.0/24
(scenario 2) to the Allowed IPs. One example:
[Interface]
### This is my desktop
PrivateKey = ___PRIVATE_KEY_DESKTOP___
Address = 192.168.200.10/24
### whatever else belongs to your desktop configuration ###
[Peer]
PublicKey = ___PUBLIC_KEY_SERVER___
AllowedIPs = 192.168.200.0/24, 192.168.100.0/24
Endpoint = server.myvpn.com:5661
Of course, if your peers use the server as an exit node, you don’t have to change nothing:
[Interface]
### This is my desktop, same as above
[Peer]
PublicKey = ___PUBLIC_KEY_SERVER___
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = server.myvpn.com:5661
Here, the AllowedIPs already include the Home Assistant’s IP address and range.
And that’s it, now you should be able to reach the Home Assistant from every peer in your VPN using the address http://192.168.100.100/
.
Additional tasks
Debugging
If you can’t connect and want to debug your wireguard add-on, you can ssh into your device, open a bash shell inside your add-on’s container and use all the tools you are used to (just use apk
if something is missing).
Reconfiguration
In order to reconfigure your wireguard interface, just navigate into the addons folder, edit the rootfs/etc/wireguard/wg0.conf
file and hit the Rebuild
button for the add-on.
Additional interfaces
You can run as many interfaces from this add-on as you need. Just add files wg1.conf
, wg2.conf
etc. to the rootfs/etc/wireguard/
directory and the corresponding commands wg-quick up wg1
, wg-quick up wg2
etc. to the ´run.sh´ script. Then hit the Rebuild
button for the add-on.
Final notes
This setup makes most sense if your Home Assistant is the only always-on device on it’s LAN. If there is another always-on wireguard peer on that LAN, you could just use that one as an exit node for your HA Green.
I am using this on a Home Assistant Green, but it should also work if you install hassio elsewhere, for instance on a Raspberry PI.