A friend of mine, who is into home automation, wanted to install the domoticz system with drivers for the Aeotec Z-Stick Z-Wave USB stick into FreeNAS 11.1. I took as a challenge to find out, how difficult would it be to write a fairly complex, but fully automatic installation script of a FreeNAS jail.
This script is based on the wiki article at https://www.domoticz.com/wiki/FreeNAS
Also, man iocage and the FreeBSD iocage documentation at https://www.freebsd.org/cgi/man.cgi?query=iocage&sektion=8 are great resources.
This was originally done for a warden jail. The code that has to do with devfs rules was necessary there, but now that this script creates the domoticz jail in iocage, some of that code is superfluous. Also, some other services are installed in my friend's domoticz jail, so some settings in this script are not necessary just for domoticz.
The jail needs access to the Z-Wave USB device /dev/cuaU0 in the host system. In the iocage jail I could not access this device until I set devfs_ruleset=0. This basically gives the jail potentially access to everything in the host's /dev. I think the correct way would be to give access to only those devices that the jail really needs access to. I just couldn't figure out the correct devfs settings. Feel free to experiment with the iocage jail settings.
At the start of the script you will find some settings, which you should set before running the script.
JAIL_IP is the ip4_addr property. That is, the interface name and the ipv4 address and netmask you want to give for the jail. You can use e.g. vnet0 for the interface. If the start of this string is "vnet", the script will set vnet=on for the jail automatically. Note: to use vnet in iocage, you may need to set some tunables in FreeNAS. You can find many threads about that topic on this forum.
DEFAULT_ROUTER is the default router's ipv4 address.
For DOMOTICZ_DB_DIR you may enter a directory or a dataset on the FreeNAS side to be used as the database directory for domoticz. If this directory does not exist when you run this script, then this setting will not be applied, and domoticz will have it's database only in /var/db/domoticz/ in the jail.
If AUTOBOOT=1, then the script will set boot=on for the jail. If AUTOBOOT=0, then the boot property will not be set.
That's all you need to do. When you start the script, everything will be automatic. It takes about 15 minutes for the script to do this installation in my Freenas 11.1 VM. When the script has finished, it will show you the URL to access domoticz. Note: if domoticz seems unresponsive, turn off adblocking in your browser.
Obviously, this installation is of little use, if you don't have the Z-Wave USB stick or any other compatible device. You can still install domoticz, but there isn't much to to do in domoticz, if you don't have any hardware to play with.
With this script I want to show that it is quite possible to write "one click" installation scripts for iocage jails in FreeNAS 11.1.
To undo everything this script does, just type
and delete user "domoticz" and group "domoticz" from FreeNAS.
The code is just ONE script file.
edit: simplified code by removing unnecessary sed usage
This script is based on the wiki article at https://www.domoticz.com/wiki/FreeNAS
Also, man iocage and the FreeBSD iocage documentation at https://www.freebsd.org/cgi/man.cgi?query=iocage&sektion=8 are great resources.
This was originally done for a warden jail. The code that has to do with devfs rules was necessary there, but now that this script creates the domoticz jail in iocage, some of that code is superfluous. Also, some other services are installed in my friend's domoticz jail, so some settings in this script are not necessary just for domoticz.
The jail needs access to the Z-Wave USB device /dev/cuaU0 in the host system. In the iocage jail I could not access this device until I set devfs_ruleset=0. This basically gives the jail potentially access to everything in the host's /dev. I think the correct way would be to give access to only those devices that the jail really needs access to. I just couldn't figure out the correct devfs settings. Feel free to experiment with the iocage jail settings.
At the start of the script you will find some settings, which you should set before running the script.
JAIL_IP is the ip4_addr property. That is, the interface name and the ipv4 address and netmask you want to give for the jail. You can use e.g. vnet0 for the interface. If the start of this string is "vnet", the script will set vnet=on for the jail automatically. Note: to use vnet in iocage, you may need to set some tunables in FreeNAS. You can find many threads about that topic on this forum.
DEFAULT_ROUTER is the default router's ipv4 address.
For DOMOTICZ_DB_DIR you may enter a directory or a dataset on the FreeNAS side to be used as the database directory for domoticz. If this directory does not exist when you run this script, then this setting will not be applied, and domoticz will have it's database only in /var/db/domoticz/ in the jail.
If AUTOBOOT=1, then the script will set boot=on for the jail. If AUTOBOOT=0, then the boot property will not be set.
That's all you need to do. When you start the script, everything will be automatic. It takes about 15 minutes for the script to do this installation in my Freenas 11.1 VM. When the script has finished, it will show you the URL to access domoticz. Note: if domoticz seems unresponsive, turn off adblocking in your browser.
Obviously, this installation is of little use, if you don't have the Z-Wave USB stick or any other compatible device. You can still install domoticz, but there isn't much to to do in domoticz, if you don't have any hardware to play with.
With this script I want to show that it is quite possible to write "one click" installation scripts for iocage jails in FreeNAS 11.1.
To undo everything this script does, just type
iocage destroy domoticz
and delete user "domoticz" and group "domoticz" from FreeNAS.
The code is just ONE script file.
Code:
#!/bin/bash # Network settings: JAIL_IP="em0|192.168.0.102/24" DEFAULT_ROUTER="192.168.0.1" # Domoticz database directory in the host. Set to "" if you don't want to use this feature: DOMOTICZ_DB_DIR="/mnt/Volume1/db/domoticz" AUTOBOOT=1 ############################################################################################################ if [ "$(id -u)" != "$(id -u root)" ]; then # could do: # eval "sudo $0" echo "You must be root to run this installer." exit 1 fi show_msg() { echo "**************************************************************" echo "*" while (( "$#" )); do echo "* $1" shift done echo "*" echo "**************************************************************" } fn="$(basename $0)" TMPFILE="$(mktemp -q '/tmp/'"$fn"'.XXXX')" [ -e $TMPFILE ] || exit 1 # Detect or create user domoticz in the host DOMOTICZ_UID="$(id -u domoticz)" if [ -z "$DOMOTICZ_UID" ]; then pw useradd -q -n domoticz -s /sbin/nologin -h - DOMOTICZ_UID="$(id -u domoticz)" fi DOMOTICZ_GID="$(id -g domoticz)" # Detect Z-Wave device and set /etc/devfs.rules addr="$(dmesg | sed -rn 's/.*umodem.*addr ([0-9]+).*/\1/p' | tail -n 1)" if [ -n "$addr" ]; then if [ -n "$(grep 'devfsrules_jail_allow_usb' /etc/devfs.rules)" ]; then sed -r "s/(devfsrules_jail_allow_usb=)([0-9]+)/\1${addr}/" /etc/devfs.rules >$TMPFILE mv -f $TMPFILE /etc/devfs.rules else echo "[devfsrules_jail_allow_usb=${addr}]" >> /etc/devfs.rules echo "add path 'cu*' unhide" >> /etc/devfs.rules fi fi JROOT="$(jls | awk '$3 ~ /domoticz/ {print $4}')" if [ -z "$JROOT" ]; then show_msg "Creating domoticz jail..." printf '{ "pkgs": [ "python3", "openssl", "sqlite3", "expat", "curl", "libiconv", ' >$TMPFILE printf '"gmake", "cmake", "subversion", "git", "devel/boost-libs", ' >> $TMPFILE printf '"devel/boost-python-libs", "devel/boost-all" ]}' >> $TMPFILE VNET="" [ "${JAIL_IP:0:4}" == "vnet" ] && VNET="vnet=on" BOOTFLAG="" [ $AUTOBOOT -ne 0 ] && BOOTFLAG="boot=on" iocage create -n "domoticz" -r 11.1-RELEASE -p $TMPFILE ip4_addr="$JAIL_IP" \ defaultrouter="$DEFAULT_ROUTER" $VNET allow_raw_sockets="1" $BOOTFLAG [ $? -eq 0 ] || exit 1 iocage set allow_mount="1" allow_mount_devfs="1" enforce_statfs="1" domoticz iocage set mount_devfs="1" allow_mount_nullfs="1" allow_mount_tmpfs="1" domoticz iocage set devfs_ruleset="0" domoticz JROOT="$(jls | awk '$3 ~ /domoticz/ {print $4}')" sed '1,/--divider--$/d' "$0" > $TMPFILE [ -s "$TMPFILE" ] && dbdir="$(sed -rn 's/.*_dbdir:=(\/.*)}.*/\1/p' $TMPFILE)" [ -n "$dbdir" ] || dbdir="/var/db/domoticz" if [ "$(iocage get state domoticz)" != "up" ]; then iocage start domoticz &> /dev/null if [ $? -ne 0 ]; then show_msg "Error: The domoticz jail has been created," "but it does not start." exit 1 fi fi # Build the domoticz jail cat << EOF | iocage chroot domoticz pw groupadd -n domoticz -g $DOMOTICZ_GID pw useradd -n domoticz -u $DOMOTICZ_UID -g $DOMOTICZ_GID -m -s /sbin/nologin -h - pw groupmod dialer -m domoticz git clone https://github.com/OpenZWave/open-zwave.git /home/domoticz/open-zwave-read-only gmake -C /home/domoticz/open-zwave-read-only git clone https://github.com/domoticz/domoticz.git /home/domoticz/domoticz cmake -DCMAKE_BUILD_TYPE=Release /home/domoticz/domoticz/CMakeLists.txt make -j 2 -C /home/domoticz/domoticz chown -R domoticz:domoticz /home/domoticz/domoticz [ ! -d "$dbdir" ] && mkdir -p "$dbdir" chown domoticz: "$dbdir" mkdir /var/run/domoticz chown :domoticz /var/run/domoticz chmod 770 /var/run/domoticz echo "" >>/etc/rc.conf echo "# Lines added by domoticz" >> /etc/rc.conf echo 'hostname="domoticz"' >> /etc/rc.conf echo 'devfs_enable="YES"' >> /etc/rc.conf echo 'devfs_system_ruleset="devfsrules_common"' >> /etc/rc.conf echo 'domoticz_enable="YES"' >> /etc/rc.conf EOF if [ -d "$DOMOTICZ_DB_DIR" ]; then iocage fstab -a domoticz "$DOMOTICZ_DB_DIR" "$dbdir" nullfs rw 0 0 else show_msg "Warning: Database directory not outside of the jail." fi fi # Trying to install the domoticz service in the jail if [ ! -s $TMPFILE ]; then sed '1,/--divider--$/d' "$0" > $TMPFILE fi if [ -s $TMPFILE ]; then cp -f $TMPFILE "${JROOT}/etc/rc.d/domoticz" chmod 555 "${JROOT}/etc/rc.d/domoticz" fi if [ $AUTOBOOT -eq 0 ]; then iocage stop domoticz &> /dev/null else iocage restart domoticz &> /dev/null fi # Creating the ttyUSB# device(es) and setting permissions for cua in $(ls /dev/cuaU* 2>/dev/null); do ln -sf "$cua" "${JROOT}/dev/ttyUSB${cua: -1}" done chown root:domoticz "${JROOT}/dev/ttyU"* &> /dev/null chmod 660 "${JROOT}/dev/ttyU"* &> /dev/null domoip="$(jls | awk '$3 ~ /domoticz/ {print $2}')" if [ "$(iocage get state domoticz)" == "up" ]; then show_msg "Domoticz is now running." "" \ "The web user interface is at:" "" "http://$domoip:8080" else show_msg "Domoticz is now installed. Start it from" \ "the FreeNAS new UI Jails section," \ "or by running:" "" "iocage start domoticz" "" \ "The web user interface will be at:" "http://$domoip:8080" fi rm "$TMPFILE" &> /dev/null exit 0 # Do not remove or alter the divider line below! # --divider-- #! /bin/sh # # # PROVIDE: domoticz # REQUIRE: LOGIN cleanvar # KEYWORD: shutdown # # Add the following lines to /etc/rc.conf to enable domoticz: # #domoticz_enable (bool): set to "YES" to start domotics at boot #domoticz_dbdir (str): Default to "/var/db/domoticz" # domoticz database directory #domoticz_user (str): Default to www, user for starting domoticz #domoticz_group (str): Default to www, group for stating domoticz #domoticz_pidfile (str): Custum PID file path and name # Default to "/var/run/domoticz/${hostname}.pid". #domoticz_args (str): Custom additional arguments to be passed # . /etc/rc.subr name="domoticz" rcvar="domoticz_enable" stop_cmd="${name}_stop" load_rc_config $name : ${domoticz_dbdir:=/var/db/domoticz} : ${domoticz_user:=domoticz} : ${domoticz_group:=domoticz} : ${domoticz_enable:=no} : ${domoticz_directory:="/home/domoticz/domoticz/"} : ${domoticz_args:="-syslog -daemon"} pidfile=${domoticz_pidfile:-"/var/run/domoticz/${hostname}.pid"} command="/home/domoticz/domoticz/domoticz" command_args="-dbase ${domoticz_dbdir}/domoticz.db -pidfile ${pidfile} ${domoticz_args}" domoticz_stop() { if [ -e "${pidfile}" ]; then echo "Stopping ${name}..." kill -9 `cat ${pidfile}` rm ${pidfile} fi } run_rc_command "$1"
edit: simplified code by removing unnecessary sed usage
Last edited: