HASS virtualenv in jail on FreeNAS 11 with auto-start and zwave

Hi! Im still very new to this whole home automation thing. I’m thankful to have found something like Home Assistant to run the show! Hopefully this is in the right place and some can find this helpful. After getting HA running running in a virtualenv on my FreeNAS I wanted to put something together in case I needed to reinstall. Although many great guides are out there none that I came across had all this information in one place and relating to FreeNAS. This is more or less a collection and reorganization of information found in other guides and targeted at using a virtualenv to run HA in a jail on FreeNAS 11 as a non-root user (homeassistant), auto start on jail reboot and working zwave (Aeotec ZW090 Z-Stick GEN5) So here we go!

####Using the FreeNAS GUI, create new jail called Home_Assistant
####From the terminal inside your jail, update and install required packages.

  • python35 py35-sqlite3 - Required to run Home Assistant
  • bash - Needed to active virtualenv
  • gmake - Needed to install Z-Wave

[email protected]_Assistant:/ #  pkg update
[email protected]_Assistant:/ #  pkg upgrade
[email protected]_Assistant:/ #  pkg install python35 py35-sqlite3 bash gmake
[email protected]_Assistant:/ #  python3.5 -m ensurepip
[email protected]_Assistant:/ #  pip3 install --upgrade virtualenv

###Create the homeassistant user
Run adduser and answer questions. Although not required, I recommend changing the default shell to bash for the homeassistant user since bash will be needed for activating the virtualenv created later on. Also I am adding the homeassistant user to the ‘dialer’ group. This is only required for using USB Z-Wave devices such as the Aeotec ZW090 Z-Stick.

Here’s how it all looks below. Questions I marked with an astrick (*) are answers I provided. Other questions I simply pressed ‘enter’ to accept default answer

[email protected]_Assistant:/ #  adduser

* Username: homeassistant
* Full name: Hass
  Uid (Leave empty for default): 
  Login group [homeassistant]: 
* Login group is homeassistant. Invite homeassistant into other groups? []: dialer
  Login class [default]: 
* Shell (sh csh tcsh git-shell bash rbash nologin) [sh]: bash
  Home directory [/home/homeassistant]: 
  Home directory permissions (Leave empty for default): 
  Use password-based authentication? [yes]: 
  se an empty password? (yes/no) [no]: 
  Use a random password? (yes/no) [no]: 
* Enter password: 
* Enter password again: 
  Lock out the account after creation? [no]:

  Username   : homeassistant
  Password   : *****
  Full Name  : Hass
  Uid        : 1001
  Class      : 
  Groups     : homeassistant dialer
  Home       : /home/homeassistant
  Home Mode  : 
  Shell      : /usr/local/bin/bash
  Locked     : no
* OK? (yes/no): y
  adduser: INFO: Successfully added (homeassistant) to the user database.
* Add another user? (yes/no): n

Next create a directory for the virtualenv to live and change permissions so it belongs to the homeassistant user:group created in the previous step. Based on other guides Im going to use /srv/homeassistant

[email protected]_Assistant:/ #  mkdir -p /srv/homeassistant
[email protected]_Assistant:/ #  chown homeassistant:homeassistant /srv/homeassistant

Now we can become the homeassistant user, create the virtualenv and finally install homeassistant.
Notice how “(homeassistant)” appears at the beginning of command prompt after running the ‘source’ command. This indicates we are now operating in our virtualenv.

[email protected]_Assistant:/ #  su homeassistant

[[email protected]_Assistant ~]$ virtualenv -p /usr/local/bin/python3.5 /srv/homeassistant
[[email protected]_Assistant ~]$ source /srv/homeassistant/bin/activate

(homeassistant) [[email protected]_Assistant ~]$ pip3 install --upgrade homeassistant
(homeassistant) [[email protected]_Assistant ~]$ exit

You should now be able test home assistant using the following command. This will run in the terminal and you can stop by either using the Home Assistant web GUI or pressing ‘ctrl+c’. Closing the terminal will also stop homeassistant

[email protected]_Assistant:/ # su - homeassistant -c '/srv/homeassistant/bin/hass'

  • NOTE for the ‘source /srv/homeassistant/bin/activate’ command to work, your homeassistant user will need to be running the bash shell. If you are using a different shell you will need to switch (at least temporarily) to bash. Here’s a few hints:

    pkg install bash - to install bash

    exec bash - to run bash shell

You can also run homeassistant by adding ’ --deamon’. This will run homeassistant in the background allowing you to close your terminal. You would restart or stop homeassistant using either the web GUI. I will use this command to autostart homeassistant later on.
[email protected]_Assistant:/ # su - homeassistant -c '/srv/homeassistant/bin/hass --daemon'

Aeotec ZW090 Z-Stick GEN5

Here we are simply becoming our homeassistant user, entering out virtualenv and install open zwave. I had to specify version of openzwave or home assistant complained about the new version install by default

[email protected]_Assistant:/ # su homeassistant
[[email protected]_Assistant ~]$ source /srv/homeassistant/bin/activate
(homeassistant) [[email protected]_Assistant ~]$ pip3 install python_openzwave==
(homeassistant) [[email protected]_Assistant ~]$ exit

I’ve included my configuration for the Aeotec ZW090 Z-Stick as an example. If you followed this guide the usb_path and config_path should be the same. If not you’ll need to change these to match your system. I’m sorry I cant offer more on this but I’m pretty much a noob myself :stuck_out_tongue:

Become homeassistant user to edit configuration.yaml. We need to enable the zwave component

[email protected]_Assistant:/ # su homeassistant
[[email protected]_Assistant ~]$ edit /home/homeassistant/.homeassistant/configuration.yaml

and add this to the bottom of the file

# Example for Aeotec ZW090 Z-Stick in configuration.yaml
  usb_path: /dev/cuaU0
  config_path: /srv/homeassistant/lib/python3.5/site-packages/python_openzwave/ozw_config

** NOTE for ‘pip3 install python_openzwave==’ to complete successfully ‘gmake’ is required
# pkg install gmake
** NOTE the homeassistant user must be a member of the ‘dailer’ to use the zwave stick
# pw groupmod dialer -m homeassistant

Auto Start: UPDATED

[email protected]_Asistant:/ # edit /usr/local/etc/rc.d/homeassistant

# PROVIDE: homeassistant
# KEYWORD: shutdown
# FreeNAS 11 Jail -- Python VirtualEnv -- Home Assistant Daemon -- Non-Root User
# The following are available to configure this service:
# Change these options in /etc/rc.conf.local or /etc/rc.conf
# EXAMPLE: sysrc homeassistant_enable=yes
# EXAMPLE: sysrc homeassistant_data_dir=/home/homeassistant/.homeassistant
# 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: homeassistant
# 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: homeassistant
# homeassistant_data_dir:   Directory where homeassistant configuration files will stored.
#                           Default: /usr/home/homeassistant/.homeassistant

. /etc/rc.subr
load_rc_config ${name}

: ${homeassistant_enable:="NO"}
: ${homeassistant_user:="homeassistant"}
: ${homeassistant_group:="homeassistant"}
: ${homeassistant_data_dir:="/usr/home/${homeassistant_user}/.homeassistant"}


command_args="-c ${homeassistant_data_dir} --pid-file ${pidfile} --daemon"

  if [ ! -d "${pid_dir}" ]; then
    install -d -g ${homeassistant_group} -o ${homeassistant_user} -- "${pid_dir}";

  if [ ! -d "${homeassistant_data_dir}" ]; then
    install -d -g ${homeassistant_group} -o ${homeassistant_user} -m 775 -- "${homeassistant_data_dir}";


  rm -f -- "${pidfile}"

run_rc_command "$1"

You’ll need to make this file executable
[email protected]_Assistant:/ # chmod +x /usr/local/etc/rc.d/homeassistant

If homeassistant is not yet running you can start with the following command
[email protected]_Assistant:/ # service homeassistant start

The End!

1 Like

Nice guide.

However, I fail to see the reason in using a virtual environment inside a jail, since a jail is already a separate container.

First Off! I Love You! Very easy to follow.

I got one of those Linear HUSBZB-1 Nortek zwave and zigbee combo usb sticks and am having some trouble getting it going. Any idea what this mean?

[[email protected]_Assistant /dev]$ usbconfig list
ugen0.2: <HubZ Smart Home Controller Silicon Labs> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)

2017-10-22 13:00:03 ERROR (MainThread) [homeassistant.setup] Error during setup of component zha
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/serial/serialposix.py", line 323, in _reconfigure_port
    orig_attr = termios.tcgetattr(self.fd)
termios.error: (25, 'Inappropriate ioctl for device')

During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/setup.py", line 191, in _async_setup_component
        result = yield from component.async_setup(hass, processed_config)
      File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/zha/__init__.py", line 87, in async_setup
        yield from ezsp_.connect(usb_path, baudrate)
      File "/srv/homeassistant/lib/python3.5/site-packages/bellows/ezsp.py", line 30, in connect
        self._gw = yield from uart.connect(device, baudrate, self)
      File "/srv/homeassistant/lib/python3.5/site-packages/bellows/uart.py", line 266, in connect
      File "/usr/local/lib/python3.5/asyncio/coroutines.py", line 210, in coro
        res = func(*args, **kw)
      File "/srv/homeassistant/lib/python3.5/site-packages/serial_asyncio/__init__.py", line 410, in create_serial_connection
        ser = serial.serial_for_url(*args, **kwargs)
      File "/srv/homeassistant/lib/python3.5/site-packages/serial/__init__.py", line 88, in serial_for_url
      File "/srv/homeassistant/lib/python3.5/site-packages/serial/serialposix.py", line 272, in open
      File "/srv/homeassistant/lib/python3.5/site-packages/serial/serialposix.py", line 326, in _reconfigure_port
        raise SerialException("Could not configure port: {}".format(msg))
    serial.serialutil.SerialException: Could not configure port: (25, 'Inappropriate ioctl for device')

Nice guide! I got a question though.

Is there any way I relatively simple can share my configuration files through ftp/samba without setting up a ftp/smb server inside the jail? I tried sharing the location of the homeassistant dir through samba while also assigning myself to the same homeassistant group (with the same uid ofcourse) so permission wise it should work, but it doesn’t… I got all kind of permission errors.

How do you edit your configuration? Through SSH?


@Cripplin No the point of the jail is to be segregated from the base OS, which is why setting up a share isn’t a straight forward web gui task. So to me for the time it takes to setup a share i would just ssh in and do my configuration that way. If you do the ssh route at least you don’t have to worry about the whole unix/windows permissions. I use windows, so just install putty to get to the freenas box. then you can run jls to list your jails. Then jexec 6 /bin/tcsh where the number is the jail you are running home assistant under. @stunts1337 I see your argument, however from a developer standpoint virtualenv’s are just common practice. I do agree that I doubt anyone will install any extra packages in the jail so it isn’t really required. Habits, in this case a good one, are hard to break.

you can add storage to the jail, that points to a dataset that is shared out over SMB, that your config resides on and the jail sees it as the default path…

1 Like

Thanks man!

Few quirks here and there but its working now.

I had to change default Python version and to switch to bash manually.


I updated this guide HERE