Contents

The ultimate installation of Home Assistant: Docker, HACS Plugin and HTTPS

Why not install HomeAssistant? directly on the computer.

Apparently installing HomeAssistant directly on the operating system (whether on a Raspberry or a regular PC) may seem like the best way to take advantage of one of the world’s most popular home automation and automation software. However, this solution also brings with it several limitations, which manifest themselves in the most annoying ways possible:

  • Inability to choose the operating system of the host on which HomeAssistant will be installed. Indeed, there are many situations for which we cannot reinstall the operating system from 0, just think of a NAS or the possibility of employing a computer with incompatibilities or with other services already configured.
  • Do you need to use the computer for other services and literally want to go crazy to get all the dependencies between Home Assistant and your software to work?
  • If I need to migrate my Home Assistant instance, I have to reinstall everything from scratch on the new pc.
  • Since it is a boxed, ready-made system, the configuration and log files will be on default paths within the machine. To go and save them elsewhere or provide mechanisms for manually backing up files we would have to modify the system and risk having to reconfigure everything every time we upgrade.
  • Did you do a HomeAssistant or security update and the computer no longer turns on? Big problem when the only feasible solution is to reinstall everything from scratch.

To put it simply, you risk wasting a lot of time, having an unreliable and inflexible system.

The alternative to containers: Docker

The Docker solution involves installing our instance of HomeAssistant inside a Docker container, freeing us almost completely from the base operating system. It can be said that in this mode we avoid all the disadvantages we identified above in the simple installation.

With the right approach, moreover, we can take advantage of a whole series of extra features with ease, such as HTTPS encryption, the use of a url without having to remember port numbers, the ability to change versions effortlessly and without “damaging” the environment.

But is it more complicated to install HomeAssistant in this mode? Is it difficult to get an instance with HTTPS enabled? And can I still use my HACS plugins?

it’s all in the guide! keep reading and you will find it already done

The ultimate solution to install Home Assistant

Prerequisites.

  • A local server, such as an old pc or a power-saving one that is always on. Anything from rack mount servers to Intel NUCs (I personally do well with the Gigabyte Brix) and maybe why not, a Raspberry.
    Note
    The guide describes the steps in case of using intel x64 architecture on Linux-based operating system. In case of ARM architecture (e.g. a Raspberry) or other operating systems do not worry, with a few adaptations you will be able to achieve the same goal.
  • Port 80 and 443 must not already be used by the local server. *The local server must have a static address in the LAN (e.g. 192.168.1.X).
  • The home network must be connected to the Internet. In case it does not have a static ip address (in Italy as far as I know they are granted purely to business contracts) there is no problem, only dynamic dns registration is required.
  • Via the home router, port 80 and 443 of the WAN interface will have to be routed to the local server (port forwarding).
  • docker and docker-compose must be installed on the server. In case you haven’t already installed them, the official docker site provides simple and effective guides to them.
  • A “dynamic DNS name” (such as those offered by NoIP and dyn.com) or a static dns name in case you have a static ip address. Basically, for certificates for https to work, it is necessary in this case to get a symbolic url pointing to the public home address; the ip alone is not enough. By the way, when configuring dynamic dns it is important to remember to address all subdomains with the wildcard asterisk-dot before the name. In the guide I will indicate “YourPersonalHomeLabSite.dyndns.org” as your dynamic dns.
  • Optional - On your home server you can work however you like, using keyboard and mouse, via ssh, or kvm. My advice is to use Visual Studio CODE with the Remote Development extension, it is really convenient.

What is a reverse proxy and why do we need one?

The Nginx Proxy Manager product consists of the Nginx proxy (configured as a reverse proxy) and a management and configuration interface. The reverse proxy we can imagine it as a web server that responds to each page request by sending content from another server. Basically, when I request something from a reverse proxy he does not own the content and has to request it from the real server synchronously to my request.

Why is it so employed today?
Just an example: say I have an instance of Home Assistant published on my local server on 192.168.1.4:5000 and one of Owncloud on another server with 192.168.1.10:8000. Exposing these two services in https and outside on the wan could be onerous and require specific configurations on each of the services, in addition to forcing me to remember for each service, the correct url and port. If I set these two local endpoints as routes associated with subdomains of my reverse proxy I could reach homeassistant by asking the reverse proxy for pages referring to homeassistant.mydomain.org and owncloud by asking owncloud.mydomain.org. The reverse proxy acts as a request collector for all internal resources, keeping the real server exposing the individual service not directly involved with interaction with clients. This leads to advantages on the security front, ease of configuration and management, not to mention the ease of scaling up resources in case you need more resources.

Let’s start the containers.

On the local server we find a folder to organize all the configurations and files pertaining to the exposed services. Usually I am used to /opt/homelab or /homelab (you can choose any other folder, you will have to change the paths that you find below in the guide agreeing with your choice). Inside this folder we are going to create spaces for proxy and HomeAssistant:

  • /opt/homelab/homeassistant
  • /opt/homelab/nginxproxymanager.

Now we configure the proxy docker-compose file /opt/homelab/nginxproxymanager/docker-compose.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version: '3.2'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    deploy:
      mode: global
    restart: always
    network_mode: host # with network_mode: host all ports are potentially exposed. if you want to select only few of them comment this line and uncomments "ports" chapter.
    #ports: 
    #  - target: 80
    #    published: 80 # Public HTTP Port
    #    protocol: tcp
    #    mode: host
    #  - target: 443
    #    published: 443 # Public HTTPS Port
    #    protocol: tcp
    #    mode: host
    #  - '81:81' # Admin Web Port - This port will be exposed only in the LAN
    volumes:
      - /opt/homelab/nginxproxymanager/config.json:/app/config/production.json
      - /opt/homelab/nginxproxymanager/data:/data
      - /opt/homelab/nginxproxymanager/letsencrypt:/etc/letsencrypt
    dns:
      - 8.8.8.8

  dns:
    restart: always
    image: strm/dnsmasq
    volumes:
      - /opt/homelab/nginxproxymanager/dnsmasq.conf:/etc/dnsmasq.conf
    ports:
      - "53:53/udp"
    cap_add:
      - NET_ADMIN

Okay, let’s start the Nginx proxy by running from the terminal:

1
2
cd /opt/homelab/nginxproxymanager
sudo docker-compose up -d

Similarly, we configure the containers for HomeAssistant by creating the file /opt/homelab/homeassistant/docker-compose.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
version: '3'
services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - /opt/homelab/homeassistant/config:/config
      - /etc/localtime:/etc/localtime:ro
    restart: always
    privileged: true
    network_mode: host

Ladies and Gentlemen, start your engines:

1
2
cd /opt/homelab/homeassistant
sudo docker-compose up -d

Now you need to go and authorize the reverse proxy address directly edntro the Home Assistant configuration. Let’s go into the file /opt/services/homeassistant/config/configuration.yaml and add under trusted proxyies:

1
2
    - IP_OF_YOUR_HOME_LAB_SERVER # type here the local ip. needed if you use network_mode:host
    - 172.16.0.0/12 # needed if you don't use network_mode:host on nginx proxy

This will make the configuration file look something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Loads default set of integrations. Do not remove.
default_config:

# Text to speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
http:
  use_x_forwarded_for: true
  trusted_proxies:
    - IP_OF_YOUR_HOME_LAB_SERVER
    - 172.16.0.0/12

Configuring the Nginx Reverse Proxy.

From a pc in the LAN or from the server itself we navigate with a browser to the proxy management page:

http://IP_OF_THE_HOMELAB_SERVER:81

Note

The service will ask to change the password after the first login. The default credentials are:

As a first step we need to create 2 Access Lists. We start with the first one which we call LAN.

/docker-home-assistant-with-hacp/access_list.png
Access List: LAN
/docker-home-assistant-with-hacp/access_list_subnet.png
Access List: Lan - Subnet

Now we move on to create “LAN or Password.” In this case it is important to indicate the “Pass authentication to host” flag to pass the credentials to the application that will serve the request, in this case HomeAssistant.

/docker-home-assistant-with-hacp/access_list_password.png
Access List: LAN or Password
/docker-home-assistant-with-hacp/access_list_password_subnet.png
Access List: LAN or Password - Subnet

/docker-home-assistant-with-hacp/access_list_password_user.png
Since the system will be exposed on the Internet, it is even more important to choose strong passwords.

Now we can configure the hosts, the pointers to our reverse proxy. Let’s go to Hosts->Proxy Host->Add Proxy Host. Let’s go to configure HomeAssistant as our own host. In case you wanted to configure a homepage (take a look at the dashboard I propose) or other services you can do it the same way.

/docker-home-assistant-with-hacp/proxy_host.png
With the access list 'LAN or PASSWORD' the site will be exposed on the internet but will be accessible only after authentication with username and password given here. If you do not want to expose the service on the internet in any way just select the 'LAN' access list.

![Proxy Host for Proxy GUI -SSL](proxy_host_ssl.png “If you choose “Request a new SSL Certificate” Nginx proxy manager will take care of requesting, configuring and maintaining the ssl certificate for https connections automatically!")

In the “location” tab add some HomeAssistant specific configuration to the “/” path:

1
2
3
4
5
# Cross-Origin Resource Sharing.
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-type, X-HA-access
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Save, wait, and BOOM, you can now browse to https://homeassistant.YourPersonalHomeLabSite.dyndns.org to access your HomeAssistant instance, either from your network or from the outside (e.g., from your phone on a mobile network), provided you have configured port forwarding on your router as indicated in the prerequisites.

Local DNS server setup.

To use access lists based on the sender’s ip, you need to have local requests handled within your network without going through the wan. If you are requesting a page from the Internet, say from a mobile connection, a public dns will route you to the public interface of your home router, which in turn will route you to your local server. And so far so good. Conversely, if the request comes from the lan itself, perhaps a pc connected to the same network, then we have to make sure that we are not routed to our router, going out and back in our network, but we have to go directly to the local server and reverse proxy. Only in this way will our sender ip re-enter the subnet and we will be able to distinguish it from the traffic coming from outside the network. To do this we will configure a small internal dns server. To do this, create the file /opt/homelab/nginxproxymanager/dnsmasq.conf:

1
2
3
4
5
6
7
server=1.1.1.1
server=8.8.8.8
#explicitly define host-ip mappings
address=/YourPersonalHomeLabSite.dyndns.org/IP_OF_THE_HOMELAB_SERVER
address=//.YourPersonalHomeLabSite.dyndns.org/IP_OF_THE_HOMELAB_SERVER
address=/#.YourPersonalHomeLabSite.dyndns.org/IP_OF_THE_HOMELAB_SERVER
address=/homeassistant.YourPersonalHomeLabSite.dyndns.org/IP_OF_THE_HOMELAB_SERVER

Once you have configured the internal dns server you will need to configure it on the router dhcp page and/or directly on the devices themselves as the primary dns server of the ip configuration.

Activating HACS plugins on HomeAssistant with Docker.

/docker-home-assistant-with-hacp/hacs.png
HACS on Home Assistant with Docker
To activate the HACS plugin a script has been provided that will need to be run in the Home Assistant configuration folder, nothing could be simpler. Then open a terminal window and use the following commands:

1
2
wget https://get.hacs.xyz -O /opt/homelab/homeassistant/config/hacs.sh 
sudo sh /opt/homelab/homeassistant/config/hacs.sh

And finally a nice reboot to start from a clean condition.

Boom, you’ve done it

Now all that’s left is to configure HomeAssistant with all the devices you have inside your home.

Are your hands still itching?

  • Tired of having to remember dozens of ip’s, ports, urls for each of your apps installed in your home? Take a look at the simple dashboard you can make.
  • A good idea when exposing web services to the Internet is to adopt a Web Application Firewall to control and supervise traffic with the outside world.

Warnings.

You are basically exposing the reverse proxy and all hosts on the Internet, short of configured access lists, and this can pose a privacy and cybersecurity risk. For this reason you should always have an eye on testing and refining your configuration, making sure that everything is working properly and the only things accessible on the Internet are the things you want. If you browse from the outside to your public ip you will notice a 404 error screen, motivated by the fact that the reverse proxy is asked for the web page associated with that ip address. However, the reverse proxy does not know what content to provide, since no host associated with an ip address is configured.

If you want to limit the services exposed on the Internet as much as possible, all you have to do is set all hosts, except the main one in the dashboard, to the “LAN” access list.

One last thing. Google Chrome, Edge, and Google devices seem to have started using their own dns services instead of the operating system’s. This can create some problems for internal traffic, as we will notice that internal requests will go to the wan and then back again. To avoid the problem, from your browser settings just set the “use secure dns” configuration to off. Alternatively, if your home has a firewall, you can block dns requests to Google’s authoritative servers (perhaps allowing them only to your local server). I also noticed that it is best to disable the #use-dns-https-svcb-alpn flag in edge://flags/ and chrome://flags/. I discuss it here.

Need help?

If something doesn’t work as it should don’t worry, you’re on the right track. Make a pass to check point by point that the prerequisites are met and be sure to start with as clean an environment as possible. If there are still any problems, do not hesitate to leave a comment so that I or someone else can help you.