Introduction Link to heading

When I originally published instructions on installing Home Assistant Core into a FreeBSD jail, I did not allow for the fact that Python and Home Assistant Core would need to be upgraded in the future. In the original instructions I:

  • used pyenv to install a version of Python,
  • created a virtual environment with that version of Python, and
  • installed and ran Home Assistant core from that Python virtual environment.

This is fine and I should be able to upgrade Home Assistant, but what if I need to:

  • upgrade my version of Python? or
  • roll back to the previous version of Home Assistant?

What I wanted to see was whether or not I could manually upgrade and downgrade Python and Home Assistant and still have a working HA instance.

Warning

Here be dragons!

You are responsible for taking snapshots and backups before you do any upgrades or downgrades.

One day, an upgrade may introduce a breaking change that stops you going back a version. Or an upgrade to a plugin may not work on a previous version of HA or Python. These steps worked for me when I went back one release of HA or Python with no extra plugins installed. I provide no assurances nor any guarantees that this will work for you.

If it breaks, you will need to glue both pieces back together.

Preparing the jail Link to heading

The idea here is to set up the jail, install dependencies, and create the homeassistant user once.

Creating the jail Link to heading

First we create the jail:

host # bastille create -V home-assistant-test 14.0-RELEASE "DHCP SLAAC" igb0

host # bastille console home-assistant-test

I prefer to use VNET jails so that I can assign IP addresses later.

Installing dependencies in the jail Link to heading

jail # pkg update

jail # pkg install \
    ca_root_nss \
    cmake \
    curl \
    git \
    openblas \
    openjpeg \
    pkgconf \
    pyenv \
    rust \
    sqlite3 \
    vim

Create the homeassistant user in the jail Link to heading

jail # pw useradd homeassistant -w no -m -c "Home Assistant"

jail # pw groupmod dialer -m homeassistant

jail # chmod 770 /home/homeassistant

jail # pw usermod homeassistant -s /usr/local/bin/bash

I prefer to use bash as my shell and the rest of the commands assume that you are also using bash.

All commands from here onwards are run in the jail.

Installing Python using pyenv Link to heading

These instructions are taken from decuser over at the FreeBSD forums

We need to switch to the homeassistant user and install Python using pyenv. We’re going to install the previous version of Python (at the time of writing: 3.11.7) so that we can upgrade it later.

# su - homeassistant

$ pyenv install 3.12.2

$ pyenv global 3.12.2

$ pyenv init
# Load pyenv automatically by appending
# the following to 
# your shell's login startup file (for login shells)
# and your shell's interactive startup file (for interactive shells) :

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# Restart your shell for the changes to take effect.

You will have to add the following lines to ~/.bashrc and ~/.profile

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

Finally, we leave the homeassistant use shell and switch back into it to check that pyenv has loaded its shims correctly:

$ exit

# su - homeassistant

$ echo $PATH
/home/homeassistant/.pyenv/shims:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/homeassistant/bin

$ python --version
Python 3.12.2

Managing versions of Home Assistant Link to heading

We’re going to install each release of Home Assistant into its own Python virtual environment (PVE). In other words, 2023.12 will be in one environment, 2024.1 will be in another environment, and so on. These PVEs use the same version of Python, but will be separate from each other. This will let us upgrade to new point releases of HA within the same PVE, and let us test the next release of HA by creating a new PVE.

Creating a virtual environment for one release of Home Assistant (e.g. 2023.12) Link to heading

We’re going to install an old version of Home Assistant so that we can upgrade it later. For this example, I’m going to start with 2023.12

$ mkdir HA-2023.12

$ cd HA-2023.12/

$ python -m venv .

$ source bin/activate

If all went well, the shell prompt now begins with:

(HA-2023.12) $

This indicates that the HA-2023.12 environment is being used.

We update pip and install wheel:

$ pip install --upgrade pip

$ pip install wheel

There are a few a few dependencies that are not installed automatically when we use pip to install Home Assistant (python-zlib-ng, numpy, webrtc-noise-gain). The instructions for installing these are described here.

For 2023.12 I also had to manually install botocore:

$ pip install git+https://github.com/boto/botocore

Now, let’s install and run 2023.12.1:

$ pip install homeassistant==2023.12.1

$ hass --ignore-os-check --verbose

After a while, we’re greeted by the starting page:

HA 2023.12 Start Page

Once we’ve set up a dummy user, we can see that were running 2023.12.1:

HA 2023.12.1 Info

We also have a new folder in the homeassistant user’s home directory:

$ ls -lah

drwxr-xr-x   7 homeassistant homeassistant   19B Feb 22 07:52 .homeassistant

Upgrading to a later point release of Home Assistant (e.g. 2023.12.1 -> 2023.12.3) Link to heading

Warning
I will assume that you have taken and tested a backup of the jail before you make any changes.

This is very easy to do inside the Python virtual environment. All you need to do is use pip to install the next point release of HA:

$ pip install -U homeassistant~=2023.12.1

Installing collected packages: homeassistant
  Attempting uninstall: homeassistant
    Found existing installation: homeassistant 2023.12.1
    Uninstalling homeassistant-2023.12.1:
      Successfully uninstalled homeassistant-2023.12.1
Successfully installed homeassistant-2023.12.3

HA 2023.12.3

Upgrading to a later release of Home Assistant (e.g. 2023.12 -> 2024.1) Link to heading

When a new version of HA is released, we want to keep the old PVE intact and create a new PVE for the new version of HA.

Note

There’s nothing to stop you upgrading to a new release of HA in a single PVE. For example, you may have created a single PVE called homeassistant and upgrade to a new release of HA in that PVE.

I run separate PVEs so that I can leave the old PVE and HA instance up and running while I’m getting the new release installed. This lets me fix up any missing dependencies and build errors before taking HA offline while I switch to the new version.

To do this, I’m going to log into a new shell in the jail and confirm that we’re still using the same version of Python:

$ which python
/home/homeassistant/.pyenv/shims/python

$ pyenv versions
* 3.12.2 (set by /home/homeassistant/.pyenv/version)

$ python --version
Python 3.12.2

I’m using a new shell because I don’t want to disrupt the already running HA instance.

First, we create a new Python virtual environment for Home Assistant Core 2024.1:

$ mkdir HA-2024.1

$ cd HA-2024.1

$ python -m venv .

$ source bin/activate

$ pip install --upgrade pip

$ pip install wheel

Second, we have to install the manual dependencies just like we did earlier.

Finally, we install Home Assistant Core 2024.1:

$ pip install homeassistant~=2024.1.0

If you have HA running in another shell, you will need to stop your previous HA instance before you start the new one.

$ hass --ignore-os-check --verbose

When we go to the HA web page now, we’re greeted by a login page, not the getting started page. Once we log in with the previously created user, we can see that everything works fine and is now running 2024.1:

HA 2024.1.1

Downgrading to a previous release of Home Assistant (e.g. 2024.1 -> 2023.12) Link to heading

What if something wasn’t working with 2024.1.1 and we wanted to go back to 2023.12.3?

Assuming that we’re still in the HA-2024.1 PVE, all we need to do is deactivate the current HA-2024.1 PVE and activate the HA-2023.12 PVE and restart hass:

$ deactivate

$ source HA-2023.12/bin/activate

$ hass --ignore-os-check --verbose

And we can log in as usual.

I was able to switch between 2023.12 and 2024.1 with ease. I could update the Lovelace dashboard in one version of HA and have it look exactly the same when I changed version of HA.

Recap: Managing Home Assistant versions Link to heading

So far, what we’ve done is create new PVEs for each minor version of HA (e.g. one for 2023.12 and another for 2024.1). Within each PVE, we use pip to upgrade the point release of HA (e.g. from 2023.12.1 to 2023.12.3). We can create a new PVE and switch to that PVE when we want to upgrade to a new HA release (e.g. going from 2023.12 to 2024.1). But eventually, we’re going to need to upgrade Python.

Managing Python versions Link to heading

Upgrading Python (e.g. 3.11 -> 3.12 OR 3.12.0 -> 3.12.1) Link to heading

Home Assistant regularly updates the minimum supported version of Python. I can’t find a link to where I read about the minimum supported Python version, but from memory, HA will only work with the stable releases of Python (also reported as bugfix releases). This means that you will need to update your version of Python at least every two years - but you are diligent enough to keep ot up to date aren’t you?

Installing a new version of Python is done via pyenv:

$ pyenv versions
* 3.12.1 (set by /home/homeassistant/.pyenv/version)

$ pyenv install 3.12.2

$ pyenv global 3.12.2

$ pyenv versions
  3.12.1
* 3.12.2 (set by /home/homeassistant/.pyenv/version)

This does not update the version of Python being used by the PVEs that you’ve already created.

You will need to create new PVEs based on the newly installed version of Python.

$ mkdir HA-2024.1.2

$ python -m venv .

$ source bin/activate

(HA-2024.1.2) $

$ which python
/usr/home/homeassistant/HA-2024.1.2/bin/python

$ python --version
Python 3.12.2

The rest of the HA install process is exactly the same as we have done previously, so I won’t repeat the steps here.

Going back to the previous version of Python (e.g. 3.12 -> 3.11) Link to heading

What if you are very diligent in keeping Python up to date, but for some reason a plugin doesn’t work with a newer version of Python? If you still have the old PVE, you may be able to simply deactivate the current PVE, activate the previous PVE, and be back up and running.

(HA-2024.1.2) $ deactivate

$ source HA-2024.1/bin/activate

(HA-2024.1) $ hass --ignore-os-check --verbose

Recap: Managing Python versions Link to heading

The process of upgrading Python is very straight forward. Install a new version using pyenv and then create a new PVE for HA. You may decide to upgrade Python when you upgrade to a new release of HA because you are already creating a new PVE. Going back a version of Python is also easy, just reactivate the old PVE.

Summary Link to heading

I hope you’ve found this a helpful suggestion on how to manage Home Assistant and Python virtual environments in a FreeBSD jail. This is probably not the only, or necessarily the best, way to manage the upgrades to HA. I wrote this up because, for my purposes, this works well.

Credits Link to heading

Thanks to @jan@jit.social for noticing that I had not listed ca_root_nss as a dependency.