Jailed Zigbee and HomeAssistant on FreeBSD – Brnrd – Bernard Spil

rodrigo9751 pts0 comments

Jailed Zigbee and HomeAssistant on FreeBSD | brnrd - Bernard Spil

bhyve

FreeBSD

LibreSSL

MariaDB

Misc

Security

Setting up IoTs ("S" for security) at home, apparently HomeAssistant is the tooling to use. It's Python, so at least I have a chance of understanding what goes wrong. Which it will...

Overview

Some caveats:

HomeAssistant provides no support for FreeBSD (we have to tell it to ignore OS)

HomeAssistant no longer provides this style of installation, only containers are supported.

HomeAssistant needs a recent version of Python to install the latest version.

There is a FreeBSD HomeAssistant port, but it is broken.

A bit of a faff to get this to work, but it does run.<br>We're using the latest available Python package

End result:

FreeBSD 15.0 amd64 system

Zigbee2mqtt 2.8.0 installed running in the zigbee jail (/usr/local/z2m)

A devfs ruleset for the Zigbee dongle

HomeAssistant 2026.2.3 installed and running in the hass jail (/usr/local/hass)

NOTE : When you start HomeAssistant, it will start using uv to build additional things (e.g. habluetooth)

There's a follow-up to this blog-post "Fixing" my HomeAssistant install on FreeBSD where I further optimize the install.

Jail setup

The minimal-jail pkgset wasn't enough to install, but it was enough to run. I use "thin" jails that share the base jail.<br>This ties nicely in to the breakage of the port: it needs to compile things so you need clang.

I've ended up with the folloing jail.conf file `/etc/jail.conf.d/hass.conf

hass {<br>host.hostname = "hass";<br>path = "/jails/hass";<br>ip4.addr += "lo0|127.0.0.20/24";<br>allow.raw_sockets = 0;<br>exec.clean;<br>exec.system_user = "root";<br>exec.jail_user = "root";<br>exec.start += "/bin/sh /etc/rc";<br>exec.stop = "";<br>exec.consolelog = "/var/log/jail_hass_console.log";<br>mount.fstab = "/etc/fstab.hass";<br>mount.devfs;<br>devfs_ruleset = "6";<br>mount.fdescfs;<br>allow.set_hostname = 0;<br>allow.sysvipc = 0;<br>enforce_statfs = "2";

and in /etc/fstab.hass

/jails/basefull150 /jails/hass/basejail nullfs ro 0 0

And start the jail. Verify it is running.

Create a homeassistant user

On the host system we create a homeasisstant user ("hass" for short) without login rights or homedir.<br>This way the process shows up under user "hass" on the host.

pw useradd hass -u 8123 -d /var/empty -s /usr/bin/nologin

In the jail, we'll give it a homedir /home/hass which we'll use for npm's storage.

jexec hass pw useradd hass -u 8123 -d /home/hass -m -s /bin/sh

Config for (temporary) internet access

pkg, git and npm need access to internet resources.

# Add to /usr/local/etc/pkg.conf<br>PKG_ENV {<br>http_proxy = "http://squid.example.org:3128";

git config --global http.proxy = http://squid.example.org:3128

npm config set proxy http://squid.example.org:3128

NOTE : this works once you've installed npm using pkg

To use pkg, you must allow the following in squid

pkg.freebsd.org

pkgmir.geo.freebsd.org

(pkg0.fra.freebsd.org?)

(cloudfront.aws.pkgbase.freebsd.org?)

Your squid config will have to allow the hass jail to use

pypi.org

files.pythonhosted.org

Your squid access logs will show what went wrong.

Install

Install required packages in the jail

Adapted from this blog-post.

pkg -r /jails/hass install python314 rust

We need to create the directory in /usr/local as hass has no permissions to do so.

install -d -o 8123 -g 8123 /jails/hass/usr/local/homeassistant

Now we switch to the hass user.<br>The rest of the install is as hass.

su -l hass<br>mkdir $HOME/bin $HOME/lib<br>export PATH=$PATH:$HOME/bin

Zigbee2MQTT

Another jail named zigbee, and a user zigbee.

The cheap dongle I bought shows up in dmesg like so

uchcom0 on uhub0<br>uchcom0: vendor 0x1a86 USB Serial, rev 1.10/2.64, addr 1> on usbus1<br>uchcom0: CH340 detected

The device nodes are named ttyU*.<br>To allow access to the Zigbee dongle from the jail, we need a specific devfs ruleset.

$ cat /etc/devfs.rules<br>[devfsrules_jail_zigbee=16]<br>add include $devfsrules_hide_all<br>add include $devfsrules_unhide_basic<br>add include $devfsrules_unhide_login<br>add path 'ttyU*' unhide group 1883 mode 660

The jail configuration is internal only with the specific devfs ruleset.

zigbee {<br>host.hostname = "zigbee";<br>path = "/jails/zigbee";<br>ip4.addr += "lo0|127.0.0.21/24";<br>allow.raw_sockets = 0;<br>exec.clean;<br>exec.system_user = "root";<br>exec.jail_user = "root";<br>exec.start += "/bin/sh /etc/rc";<br>exec.stop = "";<br>exec.consolelog = "/var/log/jail_zigbee_console.log";<br>mount.fstab = "/etc/fstab.zigbee";<br>mount.devfs;<br>devfs_ruleset = "16";<br>mount.fdescfs;<br>mount.procfs;<br>allow.mount;<br>allow.set_hostname = 0;<br>allow.sysvipc = 0;<br>enforce_statfs = "2";

Create a group and user (id is the same as in devfs.rules!) and the homedir

pw -R /jails/zigbee groupadd zigbee -g 1883<br>pw -R /jails/zigbee useradd zigbee -u 1883 -d /usr/local/z2m -g zigbee -s /usr/sbin/nologin<br>install -d -o zigbee -g zigbee -m 750 /jails/zigbee/usr/local/z2m

Start the zigbee jail and open a shell as user zigbee in the jail.

Get the source (check for latest tag)

cd /usr/local<br>git...

hass zigbee jail homeassistant exec freebsd

Related Articles