Update 2021-03-24: Since writing this article, the dependencies for Home Assistant haven’t changed much, however new VM images are now being released that have all the work done for you. I’d now reccomend using one of these instead of the steps detailed below.
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
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:
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:
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.
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
~/.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.
[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
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:
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
sudo -u appdaemon bash
Install Python
Again, we’ll use pyenv to install the latest version of Python for the service account
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:
~/.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
[Unit]
Description=AppDaemon
[email protected]
[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:
~/.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.
---
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
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
---
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!
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.