As part of some hardware upgrades, I’m moving Home Assistant and it’s associated programs off it’s shared box onto a dedicated VM. This means a fresh install of everything. Whilst docker would usually be an ideal candidate for this, I decided against it because I use a few custom components and troubleshooting these is a lot easier without Docker.
Preparing the VM
Nothing too special here, I used the latest network install media for Debian Buster (10). The netinst media is particularly useful if you have a fast internet connection, as the latest version of each package is downloaded before installing). Unfortunately this does mean slowing internet connections or offline installs are out of the question. If you’re doing a large number of installs, a local debian repository should work with the netinst media, but I have yet to test this.
Once this was done there’s the usual routine of adding SSH keys (yay for Ansible), setting up backups (Veeam works nicely), and installing Monitoring (Zabbix is awesome). I didn’t pay much attention to the system Python version, as Debian still ships with 3.5 which Home Assistant no longer supports.
Installing Dependencies
There are a number of global dependencies we can install through Apt to save time in the future. Here’s the command I eventually came up with to get everything up and running
1 |
apt install autoconf build-essential libbz2-dev libffi-dev libreadline-dev libsqlite3-dev libssl-dev sudo zlib1g-dev libopenzwave1.5-dev nmap libudev-dev |
Installing Home Assistant
By this point, I hope I don’t have to explain what Home Assistant is. In short, it’s some of the best home automation and BMS software out there. Unfortunately the latest versions have some dependency issues with AppDaemon (despite being designed to work together) and has now dropped support for Python 3.5. Because of this, we’ll install a separate version of Python for each of them.
Create a system account
First, we’ll create a new user to run the service. Useradd can do most of the work for us, using these parameters:
- -r Create a system account, disables password ageing and uses a lower ID
- -m Create the user’s home directory
- -d Specify the location of the home directory
- -s The login shell (or lack thereof) for the user
Overall, that gives us this:
1 |
useradd -rmd /var/lib/homeassistant -s /bin/nologin homeassistant |
From here on, everything will be run from this user account, because nothing else needs to use it’s version of Python or the libraries. To make this easier, we can use sudo to run bash as Home Assistant’s account:
1 |
sudo -u homeassistant bash |
Install Python
It’s always handy when people scripts exist to do the work for you, and installing Python is no different. To handle the installation, we turn to PyEnv. Using these commands we can install PyEnv, and then use it to install the latest version of Python.
1 2 |
curl -s -S -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash ~/.pyenv/bin/pyenv install 3.8.0 |
Install Home Assistant
Now we have a working install of Python, Home Assistant can be installed using it’s version of pip
1 |
~/.pyenv/versions/3.8.0/bin/pip install homeassistant |
Starting automatically with systemd
There are lots of arguments in favour of and against systemd, though from my point of view the benefits outweigh the disadvantages. For example, here we’re going to tell systemd to start home assistant when the system boots, but after the network and Z-Wave adapter are ready this was causing a few issues for me, so I’ve removed it for now.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[Unit] Description=Home Assistant Wants=network-online.target After=network-online.target [Service] Type=simple User=homeassistant ExecStart=/var/lib/homeassistant/.pyenv/versions/3.8.0/bin/hass -c /var/lib/homeassistant/config ExecStartPre=+/bin/chown -R homeassistant:homeassistant /var/lib/homeassistant [Install] WantedBy=multi-user.target |
Installing Mosquitto
Out of the three Mosquitto is by far the easiest to install, and that’s saying something
1 |
apt install mosquitto |
And that’s it. Told you it was simple. As with all of these, the configuration will need adjusting to suit your needs, but that’s well covered by the relevent documentation.
Installing AppDaemon
AppDaemon is a companion for home assistant, and is capable of doing much more powerful automations using python modules & scripts.
The first part of this is very similar to the Home Assistant installation. I’m doing them using separate Python versions and environments because there are some dependency issues between the two. Keeping the environments completely separate will make updating in the future much easier.
Create a system account
Same as for the Home Assistant user, Debian will do most of the work for us with this command:
1 |
useradd -rmd /var/lib/appdaemon -s /bin/nologin appdaemon |
Most of the following commands needs to be run as the appdaemon user. We can switch to it using sudo to explicitly run Bash
1 |
sudo -u appdaemon bash |
Install Python
Again, we’ll use pyenv to install the latest version of Python for the service account
1 2 |
curl -s -S -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash ~/.pyenv/bin/pyenv install 3.8.0 |
Install AppDaemon
Again this is fairly simple. AppDaemon is available through PyPi, so it can be installed using the Pip command:
1 |
~/.pyenv/versions/3.8.0/bin/pip install appdaemon |
Starting automatically with systemd
Finally, we can use systemd to automatically start appdaemon with the server. The below unit file can be placed in /etc/systemd/system/appdaemon.service
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=AppDaemon After=home-assistant@homeassistant.service [Service] Type=simple User=appdaemon ExecStart=/var/lib/appdaemon/.pyenv/versions/3.8.0/bin/appdaemon -c /var/lib/appdaemon/config ExecStartPre=+/bin/chown -R appdaemon:appdaemon /var/lib/appdaemon [Install] WantedBy=multi-user.target |
There’s a couple of non-obvious options in here, so let’s go through them all:
- After… – This makes sure appdaemon doesn’t start until Home Assistant is up and running
- ExecStartPre… – Like many users I store my Home Assistant configuration in Git. AppDaemon requires permissions on it’s configuration file, and modifying them through git as another user may accidentally remove the permissions. This command explicitly grants those permissions each time AppDaemon starts.
Installing/configuring HASS Apps, or any other AppDaemon app
One of my main uses of AppDaemon is Schedy, part of HASS Apps. Though this is just an example, and should work for any AppDaemon-powered app. First we install HASS Apps:
1 |
~/.pyenv/versions/3.8.0/bin/pip install hass-apps |
Now we can configure AppDaemon, using the config file /var/lib/appdaemon/config/appdaemon.yaml
and it’s matching secrets file.
1 2 3 4 5 6 7 8 |
--- appdaemon: threads: 10 plugins: HASS: type: hass ha_url: !secret hass_url token: !secret hass_key |
Then we need to load the HASS Apps module into AppDaemon. This is done using a shim in /var/lib/appdaemon/config/apps/hass_apps_loader.py
1 |
from hass_apps.loader import * |
Now the important bit, we tell AppDaemon to use Schedy and what schedules we want. This goes in /var/lib/appdaemon/config/apps/schedy.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
--- schedy_heating: module: hass_apps_loader class: SchedyApp actor_type: thermostat rooms: everywhere: rescheduling_delay: 120 actors: climate.heating: schedule: - v: 20 rules: - {start: "18:00", end: "20:30"} - weekdays: 1-5 rules: - {start: "06:00", end: "08:00"} - weekdays: 6-7 rules: - {start: "07:00", end: "09:00"} - v: 18 |
Turning Everything On
Now all of our software is in place, and has a basic starting configuration, let’s tell systemd to turn everything on!
1 2 3 |
systemctl enable --now mosquitto systemctl enable --now homeassistant systemctl enable --now appdaemon |
Home assistant will take a while to start for the first time, so now is ideal to go and make a cup of tea. In my case, this took over 90 minutes due to the complexity of my particular setup.