Installing HASS in virtualenv on FreeNAS 11.1-U3 w/ iocage jail

Please refer to this article for an updated version.


Finally! The updated guide to installing Home Assistant with iocage. Really this has been a bunch up build up to just a few simple commands

I recently performed some upgrades to my FreeNAS. Among other things, a new pair of SSDs for my jails. My system has been running for a few years now so I wanted to reinstall everything from scratch, ensuring a clean start with my server refresh. Due to the increasing difficulty required get homeassistant running in the now outdated “warden” jail system on FreeNAS, I wanted to switch over to the new and up coming “iocage” jail system. Read here.

The iocage system is in place now but until FreeNAS 11.2 releases - I think iocage is best used from the cli. Also some package requirements for homeassistant have changed. I wanted to take this time and update the now outdated guide I wrote before, as well as include the few extra steps needed to create a jail with iocage for homeassistant. I’m trying to keep this short. I won’t skip any needed steps but instead spend less time explaining. After creating the new jail most of the old commands remain the same. Just some package names will have changed.


FIRST TIME ONLY:
Activate iocage and downloading a release. These first steps are only required for the initial setup of iocage. Activating iocage is basically just telling it which zpool to use when installing jails. I used the same zpool I use for plugins. You can list your available zpools with zpool list In my case it’s called jail

iocage activate jail

Finally, get a list of freebsd releases and select one to download. Running the following command for the first time will create additional datasets, setup the folder structure inside the “iocage” dataset and present a menu available freebsd releases. I select the currant version [ 6 ] 11.1-RELEASE

iocage fetch

That’s it for first time setup.
More details on iocage can be found here


New jails can be created with one command. I named this one “homeassistant” and since I assign the IP address from my router I set the jail to use dhcp

iocage create -r 11.1-RELEASE -n homeassistant dhcp=on bpf=yes vnet=on boot=on

The next step is optional and requires creating the dataset ahead of time. I’m only providing this step as an example: How to mount a dataset inside you’re jail. I’m going to mount a dataset named hass (matching the hass user for which it’s intended). It will be mounted inside the jail as hass user’s home directory.

iocage fstab -a homeassistant "/mnt/jail/ioyard/hass/ /home/hass/ nullfs rw 0 0"

That’s it for creating the jail. Time to get inside to install homeassistant.

iocage console homeassistant

While I personally prefer to have the latest packages install, I believe this optional.

mkdir -p /usr/local/etc/pkg/repos
ee /usr/local/etc/pkg/repos/FreeBSD.conf

copy and paste. Press escape then enter twice to save and exit

FreeBSD: {
url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest"
 }

Install requirements for homeassistant and z-wave

pkg update
pkg upgrade
pkg install python36 py36-sqlite3 bash gmake ca_root_nss

From this point on I believe you can finish installing homeassistant following any desired pip3 install method.

My preference is to create a user/group hass then install homeassistant inside a python virtualenv. hass will be the user used to run homeassistant. My virtualenv lives in a directory I will create inside my jail: /srv/homeassistant NOTE: It has been pointed out that a virtualenv inside a jail is not needed since the jail itself is already well… a jail! I still prefer this method.

The next commands create a home directory if it doesn’t already exist, as well as group/user hass I will add hass to the dialer group as required for using the Aeotec Z-Wave stick. I’m setting the UID/GUID of hass to 990. The is just a personal preference and not required.

install -d -g hass -o hass -m 775 -- /home/hass
pw addgroup -g 990 -n hass
pw adduser -u 990 -n hass -d /home/hass -s /usr/local/bin/bash -G dialer -c "Daemon user for Homeassistant"

Install pip and virtualenv then create directory to install virtualenv.

python3.6 -m ensurepip
pip3 install --upgrade pip
pip3 install --upgrade virtualenv
install -d -g hass -o hass -m 775 -- /srv/homeassistant

Switch to user hass, activate the virtualenv and finally install homeassistant!

su hass
virtualenv -p /usr/local/bin/python3.6 /srv/homeassistant
source /srv/homeassistant/bin/activate
pip3 install --upgrade homeassistant
deactivate

You should now be able to test homeassistant! Be sure your still user hass. If you typed exit or used ‘Ctrl+D’ to exit the virtualenv you may have been switched back to user root

su hass
/srv/homeassistant/bin/hass

While it is very simple to just add one line to rc.local and get homeassistant to start on boot up, I wanted to try starting homeassistant with a slightly more advanced startup script. Since I started using Emby as my first plugin, that’s one of the first places I looked for an example to get started. As such this script started by copying and editing the Emby script to reflect homeassistant. This is my latest version which I am now using. It differs from the example I posted in the previous guide.

If not already, open cli inside the jail

iocage console homeassistant

Create directory if it doesn’t exist and add the startup script

mkdir -p /usr/local/etc/rc.d
ee /usr/local/etc/rc.d/homeassistant

copy and paste. Press escape then enter twice to save and exit

#!/bin/sh
#
# PROVIDE: hass-server
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# homeassistant_enable:    Set to YES to enable the homeassistant service.
#            Default: NO
# homeassistant_user:    The user account used to run the homeassistant daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run as root.
#            Default: hass
# homeassistant_group:    The group account used to run the homeassistant daemon.
#            This is optional, however do not specifically set this to an
#            empty string as this will cause the daemon to run with group wheel.
#            Default: hass
# homeassistant_dir:    Directory where config files are located.
#            Default: /home/hass/.homeassistant

# sysrc homeassistant_enable=yes
# service homeassistant start

. /etc/rc.subr
name=homeassistant
rcvar=${name}_enable

pidfile_child="/var/run/${name}.pid"
pidfile="/var/run/${name}_daemon.pid"

load_rc_config ${name}
: ${homeassistant_enable:="NO"}
: ${homeassistant_user:="hass"}
: ${homeassistant_group:="hass"}
: ${homeassistant_config_dir:="/home/hass/homeassistant"}

command="/usr/sbin/daemon"

start_precmd=${name}_precmd
homeassistant_precmd()
{
        rc_flags="-f -P ${pidfile} -p ${pidfile_child} /srv/homeassistant/bin/hass --config ${homeassistant_config_dir} ${rc_flags}"
       
    if [ ! -e "${pidfile_child}" ]; then
            install -g ${homeassistant_group} -o ${homeassistant_user} -- /dev/null "${pidfile_child}";
    fi

    if [ ! -e "${pidfile}" ]; then
            install -g ${homeassistant_group} -o ${homeassistant_user} -- /dev/null "${pidfile}";
    fi
   
    if [ ! -d "${homeassistant_config_dir}" ]; then
        install -d -g ${homeassistant_group} -o ${homeassistant_user} -- "${homeassistant_config_dir}";
    fi
}

stop_postcmd=${name}_postcmd
homeassistant_postcmd()
{
    rm -f -- "${pidfile}"
    rm -f -- "${pidfile_child}"
}

run_rc_command "$1"

Make this file executable and start homeassistant

chmod +x /usr/local/etc/rc.d/homeassistant
service homeassistant start

Once satisfied everything is working you can enable homeassistant to start automatically

sysrc homeassistant_enable=yes

A few ways to control homeassistant from the cli INSIDE your jail

service homeassistant [ start | stop | status | restart ]

A few ways to control your homeassistant JAIL from the FreeNAS cli (NOT inside your jail)

iocage [ start | stop ] homeassistant
If you need to restart the jail iocage docs recommend using the -s switch. This “soft-restart” will help prevent issues that could arise from a “hard-restart” if vnet=on

iocage restart -s homeassistant

You can list jails you have installed and see if they are running. To see the ip address requires root

iocage list -l
+-----+---------------+------+-------+------+-----------------+---------------------+-----+----------+
| JID |     NAME      | BOOT | STATE | TYPE |     RELEASE     |         IP4         | IP6 | TEMPLATE |
+=====+===============+======+=======+======+=================+=====================+=====+==========+
| 1   | homeassistant | on   | up    | jail | 11.1-RELEASE-p8 | epair0b|192.0.1.145 | -   | -        |
+-----+---------------+------+-------+------+-----------------+---------------------+-----+----------+

Upgrading:
First get in the jail, stop homeassistant, then become user hass

iocage console homeassistant
service homeassistant stop
su hass

Next activate the VirtualEnv
source /srv/homeassistant/bin/activate

Finally we can update
pip3 install --upgrade homeassistant

And exit the VirtualEnv and restart Homeassistant

exit
service homeassistant start
5 Likes

I’ve been trying out the Hass Configurator. I don’t know why I didn’t try this sooner. I just added it to the homeassistant jail. This is not going to use a VirtualEnv like Hass but I’m still going to place the it in the /srv directory. I run this as the hass user and the Configurators config file will be in /home/hass/configurator

Enter the jail, install wget (to download configurator) and create the directory /srv/configurator.

iocage console homeassistant
pkg install wget
install -d -g hass -o hass -m 775 -- /srv/configurator

Become user hass and download the Configurator from GitHub and make it executable.

su hass
cd /srv/configurator
wget https://raw.githubusercontent.com/danielperna84/hass-configurator/master/configurator.py
chmod +x configurator.py

Still as the user hass, create the config directory and grab the example settings.conf

mkdir /home/hass/configurator
cd /home/hass/configurator
wget https://raw.githubusercontent.com/danielperna84/hass-configurator/master/settings.conf

Finally you may need to edit the setting.conf file. If you set a password for homeassistant, on the line "HASS_API_PASSWORD": replace null with your homeassistant super secure password. I would also suggest setting the "LISTENIP": to that of the jail.

ee /home/hass/configurator/settings.conf

Press escape, then enter twice to exit

There is more information about settings.conf in the link above but as another example here’s the conf I used with the homeassistant jail created above.
image

At this point you should be able to start it.
The following command will run it in the foreground. (Again still as user hass)

/usr/local/bin/python3.6 /srv/configurator/configurator.py /home/hass/configurator/configurator.conf

Press Ctrl+C to stop

Press Ctrl+D to logout user hass and become root again
To autostart the configurator with the jail.
ee /usr/local/etc/rc.d/configurator

copy and paste. Press escape then enter twice to save and exit

#!/bin/sh
#
# PROVIDE: configurator
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# configurator_enable:	Set to YES to enable the configurator service.
#			Default: NO
# configurator_user:	The user account used to run the configurator daemon.
#			This is optional, however do not specifically set this to an
#			empty string as this will cause the daemon to run as root.
#			Default: USER_NAME
# configurator_group:	The group account used to run the configurator daemon.
#			This is optional, however do not specifically set this to an
#			empty string as this will cause the daemon to run with group wheel.
#			Default: USER_GROUP
# configurator_conf:	Hass-configurator user settings
#			Default: ~/configurator/settings.conf

# copy file to /usr/local/etc/rc.d/configurator 
# chmod +x /usr/local/etc/rc.d/configurator
#
# sysrc configurator_enable=yes
# service configurator start | status | stop

. /etc/rc.subr
name=configurator
rcvar=${name}_enable

pidfile_child="/var/run/${name}.pid"
pidfile="/var/run/${name}_daemon.pid"

load_rc_config ${name}
: ${configurator_enable:="NO"}
: ${configurator_user:="hass"}
: ${configurator_group:="hass"}
: ${configurator_config:="/home/hass/configurator/settings.conf"}
: ${configurator:="/srv/configurator/configurator.py"}

command="/usr/sbin/daemon"

start_precmd=${name}_precmd
configurator_precmd()
{
        rc_flags="-f -P ${pidfile} -p ${pidfile_child} /usr/local/bin/python3.6 ${configurator} ${configurator_config} ${rc_flags}"
        
    if [ ! -e "${pidfile_child}" ]; then
            install -g ${configurator_group} -o ${configurator_user} -- /dev/null "${pidfile_child}";
    fi

    if [ ! -e "${pidfile}" ]; then
            install -g ${configurator_group} -o ${configurator_user} -- /dev/null "${pidfile}";
    fi
}

stop_postcmd=${name}_postcmd
configurator_postcmd()
{
    rm -f -- "${pidfile}"
    rm -f -- "${pidfile_child}"
}

run_rc_command "$1"

Make this file executable and enable the service

chmod +x /usr/local/etc/rc.d/configurator
sysrc configurator_enable=yes

To now start the configurator as a daemon without restarting the jail
service configurator start

The Configurator can be reached at your jail ip port 3218. For example http://192.168.1.145:3218

You can embed this in the HomeAssistant as well.

1 Like

Nice job! I followed your guide and and I got it up and running. The only thing I haven’t figured yet out is how to edit the configuration files inside the jail. Do you have any recommendation for this?

I tried realising this with the creation of a CIFS share pointing to the config dataset. I gave the dataset (the config one, not the jail itself) ownership to the user hass with group hass with both ID of 990, the same as in the jail it self, but I can’t seem to get the permissions right.

When I connect to the share as the ‘hass’ user I can edit the files and save them, but when I connect to the share as an other user (which should have the same rights as the hass user because I put that user in the hass group) I can open the files but I cannot save them. When I inspect the permissions on the files I can see that the hass user has rwx permissions but the hass group has only rx and no w.

I have no idea why the right permissions aren’t implemented on the files because the permissions I setup in FreeNAS corresponds with the permissions I entered in the jail when following your instructions on the installation.

I hope you can help me with this one, or maybe you have a better way to share/edit/backup your configuration files.

Im not home right now to explain in more detail but you’re on the right track with permissions. You need to change the group permissions to rwx. Many ways to do this but one simple way is

iocage console homeassistant
chmod -R 775 /home/hass/homeassistant

Edit:
Im not sure if it matters in this exact case but I was thinking you may not want to have changed the permissions of the other user. The [5] of 775. A better way to do this would be to set the group permission equal to the owner permission.

iocage console homeassistant
chmod -R g=o /home/hass/homeassistant

Allright, thanks for the quick reply! I changed the permissions. First through 775 and secondly with g=0 and now I indeed see drwxrwxr-x when I enter ‘ls -l in the jail’, but when I restart CIFS and inspect the files through the share on my Windows computer, I still see that the hass group still doesn’t have write permission on the files :face_with_raised_eyebrow:.

I restarted the jail and CIFS again and it is still the same, no write permissions for group hass…

What sorcery is this?!

How is that even possible haha

Any clues?

Did you also create the user hass on your FreeNAS using the GUI or only in the jail? Permission can be a complicated thing but basic rule is the most restrictive permissions win. I can edit my homeassistant config over cifs or ssh. This may not be the exact step by step to work in your setup but hopefully you find the missing clue you need.


On my FreeNAS:
1st I create the group hass with GID of 990
image


Then I add the group hass to MY user
image


And finally add the hass user with matching 990 UID


Also I make hass the owner/group of the dataset I mount inside the jail (This is hass user’s home directory in the jail) and set rwx permissions for user/group. 99% of the time if I mess up my permission somehow, I come back to this window check my settings match what’s pictured here and hit change.

The above step is the same effect as chmod -R 775 /home/hass/homeassistant from inside the jail.



And here are my settings when I create samba share

Hope this helps.

ps Im sure I’ll have to edit this a dozen times because I’m ocd

Wow, thank you for the detailed explanation, more than I could ask for! I checked your settings with mine and my setup is exactly the same as yours… I restarted and checked and I still don’t have write permission on the other account… This is so weird, I guess i’m gonna start all over again and see if that changes anything.

Is there a reason that in the last picture, with the samba settings, you checked the box with ‘export read only’? I searched for the function of this in the documentation and that checkbox ensures that you can only read the share, and explicitly not write. Just a mistake in the picture or am I missing something?

Thanks anyhow for the help, I will let you know if I manage to get it working after another try at it.

Sorry it’s just a habit I have. I do this on all my shares as a small security step. It the bottom of the same picture under Auxiliary parameters I explicitly give write permission to troy which is my user I normally connect to my NAS with. write list = troy will override the export read-only but only for troy. This way I can always connect to the share, even as a guest or another user that has any account, even in the same group but it’s read-only. It’s only when I connect to the share logged in as troy that I can write to the folder.

Good Luck! I know there is a lot that’s going on w/ permissions. Your basically dealing w/ permissions in 3 places. Inside the jail. On the FreeNAS server itself. The settings the samba service applies. If any one little thing is wrong it wont work as expected. In the end it’s usually some tiny detail that gets overlooked but is simple to fix when finally noticed

So I tried again and I was still getting the same error, no permission on write while I knew I had everything setup right in the jail and on the freenas host. After some searching and tearing my hairs out, I logged in as my user (that is member of the hass group, so be able to write) on the freenas host and I tried to edit the hass config files and it worked! So now I knew the problem was somewhere inside SMB. After deleting the share and restarting the SMB service everything suddenly worked and I had write rights.

So I guess, the SMB share doesn’t change its permissions according to the dataset it points to? Even when that dataset is destroyed or edited, then restarting the SMB service, it still holds the old permissions? This doesn’t sound like how it should work, or am I missing something?

Thank you very much for the guide and your help trying to figure this out. Normally I don’t have to depend on other people for installing and configuring software on my FreeNAS machine, but this error was sooo weird and I could’nt figure it out, so I am glad you helped!

Now I have home assistant up and running I also added some iocage jails for FAMPP (FreeNAS, Apache, MySQL, PHP and phpMyAdmin), Mosquitto and LetsEncrypt so I got everything running om my FreeNAS machine now instead of the RPi to get the most out of Home Assistant. If you or anyone needs any help with setting up these jails I will gladly share my experience!

First, big thanks to Troy for his write-ups! With his walkthrough and your dialogue I was able to get HA running with an iocage jail. This is my first dive into freenas, programming, and Home Assistant together. I started with HA on Synologoy but it was time to upgrade so here I am.

What I’m looking for now is some guidance with Mosquitto. I was hoping I could just use the mqtt broker in HA but I couldn’t get it to work with Synology or with the iocage jail. Any tips or walkthroughs for mosquitto that you have used or created would be greatly appreciated.

Your very welcome! I’m glad I’m able to help. It’s pretty easy to add mosquitto. I’m running it in a separate jail.

Create your new jail. I called it mosquitto
iocage create -r 11.1-RELEASE -n mosquitto dhcp=on bpf=yes vnet=on boot=on

Enter jail cli
iocage console mosquitto

Install
pkg install mosquitto

Edit config file (if needed)
ee /usr/local/etc/mosquitto/mosquitto.conf

Enable service and start mosquitto
sysrc mosquitto_enable=yes
service mosquitto start

Awesome, that’s what I needed! I’m able to get my sonoff to connect to mosquitto, found out I was editing the wrong configuration.yaml. Whoops! Once I updated the right one I’m in business! Thanks again for sharing the knowledge.

I used version 11.1-U4 and it all worked great once I worked out my inexperience.

Now to play with some more sensors…

What is the best way to upgrade to the latest Home Assistant release, when installed using these instructions?

Thanks!

First get in the jail, stop homeassistant, then become user hass

iocage console homeassistant
service homeassistant stop
su hass

Next activate the VirtualEnv
source /srv/homeassistant/bin/activate

Finally we can update
pip3 install --upgrade homeassistant

And exit the VirtualEnv and restart Homeassistant

exit
service homeassistant start
2 Likes

@troy The emulated_hue component doesn’t seem to work inside of this jail. The hue bridge is running and all but alexa cannot discover any devices. Something to do with upnp or multicast If i had to guess. Did you run into this issue?

EDIT: Nevermind. I had originally created the jail with a static ip instead of using vnet and dhcp. There was an error being thrown when using vnet originally but seems to have been patched in the last few days so I recreated the jail with vnet/dhcp and everything works! Thanks

Ok Im glad you got it sorted. I’ve haven’t had much success myself using a static IP with these iocage jails either. I’d really like to put homeassistant and all IOT devices on their own vlan but last time I tried I screwed it up so bad I had to reinstall FreeNAS to get everything working again :slightly_frowning_face:

Thanks for that guide!

Just a comment for anybody having problems with the change of the name variable in the rc script:
case 1: just don’t do it :wink:
case 2: if you want to change it (e.g., if have my name set to “hass”), you have to adjust the function names homeassistant_precmd and homeassistant_postcmd according to your new name or change the start/stop_precmd assignments.