From 84215747d8b5570e5264c5200168b435d595c55b Mon Sep 17 00:00:00 2001 From: Max Winterstein Date: Wed, 30 Dec 2020 02:01:16 +0100 Subject: [PATCH] inital add --- ioBroker/CHANGELOG.md | 10 + ioBroker/Dockerfile | 4 + ioBroker/README.md | 21 ++ ioBroker/config.json | 20 ++ ioBroker/icon.png | Bin 0 -> 3948 bytes ioBroker/iobroker_startup.sh | 520 +++++++++++++++++++++++++++++++ ioBroker/iobroker_startup_ori.sh | 506 ++++++++++++++++++++++++++++++ ioBroker/logo.png | Bin 0 -> 5584 bytes 8 files changed, 1081 insertions(+) create mode 100644 ioBroker/CHANGELOG.md create mode 100644 ioBroker/Dockerfile create mode 100644 ioBroker/README.md create mode 100644 ioBroker/config.json create mode 100644 ioBroker/icon.png create mode 100644 ioBroker/iobroker_startup.sh create mode 100644 ioBroker/iobroker_startup_ori.sh create mode 100644 ioBroker/logo.png diff --git a/ioBroker/CHANGELOG.md b/ioBroker/CHANGELOG.md new file mode 100644 index 0000000..3902655 --- /dev/null +++ b/ioBroker/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.0.1] - 2020-12-30 +- Initial release \ No newline at end of file diff --git a/ioBroker/Dockerfile b/ioBroker/Dockerfile new file mode 100644 index 0000000..53866ad --- /dev/null +++ b/ioBroker/Dockerfile @@ -0,0 +1,4 @@ +FROM buanet/iobroker@sha256:f3ea64a0a2e32768f77b707d739448636bd179580fee787f4b2610068edcb014 + +# copy over the patched iobroker_startup.sh +COPY iobroker_startup.sh /opt/scripts/iobroker_startup.sh \ No newline at end of file diff --git a/ioBroker/README.md b/ioBroker/README.md new file mode 100644 index 0000000..e64cea2 --- /dev/null +++ b/ioBroker/README.md @@ -0,0 +1,21 @@ +# Home Assistant Add-on: ioBroker + +--- +## 🚨 I do not guarantee that your ioBroker configuration will not get deleted! This is some early stage release! 🚨 +--- + +This is a pretty basic implementation of ioBroker as Home Assistant Add-on. +It is ment to provide some playground. + +**This is no official add-on, neither from Home Assisant, nor from ioBroker.** + +## Installation +After installation, and successfull startup, the ioBroker instance should be avaiable at port `8081`. +If your HA instance is running with SSL support, the `OPEN WEB UI` button might not work correctly. + +## Technical notes +The `buanet` docker image contains some startup script that is pretty useful. + +To ensure data stays persistent across restarts i simply softlink `/data` to `/opt/iobroker`. +I removed some check that was not compatible with the symlink and not needed in our case. +I added the unmodified version as reference. \ No newline at end of file diff --git a/ioBroker/config.json b/ioBroker/config.json new file mode 100644 index 0000000..000a0c5 --- /dev/null +++ b/ioBroker/config.json @@ -0,0 +1,20 @@ +{ + "name": "ioBroker", + "version": "0.1.0", + "webui": "http://[HOST]:[PORT:8081]/", + "slug": "iobroker", + "description": "Open source automation platform", + "ingress": false, + "ingress_port": 8081, + "panel_icon": "mdi:iobroker", + "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], + "startup": "application", + "boot": "auto", + "options": {}, + "schema": {}, + "ports": { + "8081/tcp": 8081 + }, + "stage": "experimental" + + } \ No newline at end of file diff --git a/ioBroker/icon.png b/ioBroker/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..793e1d280d62443d23c9756c73db81bd3598e402 GIT binary patch literal 3948 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 a_^OPYjDq|RVdvL$AwU;xgetpf6Y@V`!9FDb literal 0 HcmV?d00001 diff --git a/ioBroker/iobroker_startup.sh b/ioBroker/iobroker_startup.sh new file mode 100644 index 0000000..5642837 --- /dev/null +++ b/ioBroker/iobroker_startup.sh @@ -0,0 +1,520 @@ +#!/bin/bash + +# begin hass addon custom mount block +echo "Symlinking data dir" +mv /opt/iobroker /opt/iobroker_ori # move image brought folder away +mkdir /data/iobroker || echo 'Thats fine, data folder already exists' +ln -s /data/iobroker /opt/iobroker # symlink /data mount +if find /data/iobroker -maxdepth 0 -empty | read v; then + echo "Data folder looks unused, will copy initial stuff" + cp -r -v /opt/iobroker_ori/* /opt/iobroker/ + chown -R $SETUID:$SETGID /data/iobroker/ +fi +## some debugging stuff +#echo --- +#ls -liah /opt/ +#echo --- +#ls -liah /data/iobroker +#echo --- +#ls -liah /opt/iobroker/ +# end hass addon custom mount block + +# Setting healthcheck status to "starting" +echo "starting" > /opt/scripts/.docker_config/.healthcheck + +# Reading ENV +adminport=$IOB_ADMINPORT +avahi=$AVAHI +multihost=$IOB_MULTIHOST +objectsdbhost=$IOB_OBJECTSDB_HOST +objectsdbport=$IOB_OBJECTSDB_PORT +objectsdbtype=$IOB_OBJECTSDB_TYPE +packages=$PACKAGES +setgid=$SETGID +setuid=$SETUID +statesdbhost=$IOB_STATESDB_HOST +statesdbport=$IOB_STATESDB_PORT +statesdbtype=$IOB_STATESDB_TYPE +usbdevices=$USBDEVICES +zwave=$ZWAVE + +# Getting date and time for logging +dati=`date '+%Y-%m-%d %H:%M:%S'` + +# Logging header +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo -n "$(printf -- '-%.0s' {1..15})" && echo -n " "$dati" " && echo "$(printf -- '-%.0s' {1..15})" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Welcome to your ioBroker-container! -----" +echo "----- Startupscript is now running. -----" +echo "----- Please be patient! -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Debugging information -----" +echo "----- -----" +echo "----- System -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" arch: $(uname -m))" && echo " -----" +echo "----- -----" +echo "----- Versions -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" image: $VERSION)" && echo " -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" node: $(node -v))" && echo " -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" npm: $(npm -v))" && echo " -----" +echo "----- -----" +echo "----- ENV -----" +if [ "$adminport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_ADMINPORT: $adminport)" && echo " -----"; fi +if [ "$avahi" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" AVAHI: $avahi)" && echo " -----"; fi +if [ "$multihost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_MULTIHOST: $multihost)" && echo " -----"; fi +if [ "$objectsdbhost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_HOST: $objectsdbhost)" && echo " -----"; fi +if [ "$objectsdbport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_PORT: $objectsdbport)" && echo " -----"; fi +if [ "$objectsdbtype" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_TYPE: $objectsdbtype)" && echo " -----"; fi +if [ "$packages" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" PACKAGES: $packages)" && echo " -----"; fi +if [ "$setgid" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" SETGID: $setgid)" && echo " -----"; fi +if [ "$setuid" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" SETUID: $setuid)" && echo " -----"; fi +if [ "$statesdbhost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_HOST: $statesdbhost)" && echo " -----"; fi +if [ "$statesdbport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_PORT: $statesdbport)" && echo " -----"; fi +if [ "$statesdbtype" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_TYPE: $statesdbtype)" && echo " -----"; fi +if [ "$usbdevices" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" USBDEVICES: $usbdevices)" && echo " -----"; fi +if [ "$zwave" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" ZWAVE: $zwave)" && echo " -----"; fi +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +##### +# STEP 1 - Preparing container +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 1 of 5: Preparing container -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +# Installing additional packages and setting uid/gid +if [ "$packages" != "" ] || [ $(cat /etc/group | grep 'iobroker:' | cut -d':' -f3) != $setgid ] || [ $(cat /etc/passwd | grep 'iobroker:' | cut -d':' -f3) != $setuid ] || [ -f /opt/.firstrun ] +then + if [ "$packages" != "" ] + then + echo "Installing additional packages is set by ENV." + echo "The following packages will be installed:" $packages"..." + echo $packages > /opt/scripts/.packages + bash /opt/scripts/setup_packages.sh + echo "Done." + echo ' ' + fi + if [ $(cat /etc/group | grep 'iobroker:' | cut -d':' -f3) != $setgid ] || [ $(cat /etc/passwd | grep 'iobroker:' | cut -d':' -f3) != $setuid ] + then + echo "Different UID and/ or GID is set by ENV." + echo "Changing UID to "$setuid" and GID to "$setgid"..." + usermod -u $setuid iobroker + groupmod -g $setgid iobroker + echo "Done." + echo ' ' + fi + if [ -f /opt/.firstrun ] + then + echo "Registering maintenance script as command." + echo "alias maintenance=\'/opt/scripts/maintenance.sh\'" >> /root/.bashrc + echo "Done." + echo ' ' + fi +else + echo "Nothing to do here." + echo ' ' +fi + +# Change directory for next steps +cd /opt/iobroker + + +##### +# Detecting ioBroker-Installation +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 2 of 5: Detecting ioBroker installation -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +if [ -f /opt/iobroker/iobroker ] +then + echo "Existing installation of ioBroker detected in /opt/iobroker." + rm -f /opt/scripts/.docker_config/.install_host +elif [ $(ls *_backupiobroker.tar.gz 2> /dev/null | wc -l) != "0" ] && [ $(tar -ztvf /opt/iobroker/*_backupiobroker.tar.gz "backup/backup.json" 2> /dev/null | wc -l) != "0" ] +then + if [ "$multihost" = "slave" ] + then + echo "IoBroker backup file detected in /opt/iobroker. But Multihost is set to \"slave\"." + echo "Restoring a backup is not supported on Multihost slaves. Please check configuration and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 + else + echo "IoBroker backup file detected in /opt/iobroker. Preparing restore..." + mv /opt/iobroker/*.tar.gz /opt/ + tar -xf /opt/initial_iobroker.tar -C / + mkdir /opt/iobroker/backups + mv /opt/*.tar.gz /opt/iobroker/backups/ + chown -R $setuid:$setgid /opt/iobroker # fixes permission error during restore + echo "Done." + echo "Restoring ioBroker..." + iobroker restore 0 > /opt/iobroker/log/restore.log 2>&1 + echo "Done." + echo ' ' + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo "!!!!! IMPORTANT NOTE !!!!!" + echo "!!!!! The sartup script restored iobroker from a backup file. !!!!!" + echo "!!!!! Check /opt/iobroker/log/restore.log to see if restore was successful. !!!!!" + echo "!!!!! When ioBroker now starts it will reinstall all Adapters automatically. !!!!!" + echo "!!!!! This might be take a looooong time! Please be patient! !!!!!" + echo "!!!!! You can view installation process by taking a look at ioBroker log. !!!!!" + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + fi +else + echo "There is data detected in /opt/iobroker but it looks like it is no instance of ioBroker or a valid backup file!" + echo "Please check/ recreate mounted folder/ volume and start over." + exit 1 +fi +echo ' ' + + +##### +# Checking ioBroker-Installation +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 3 of 5: Checking ioBroker installation -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +# (Re)Setting permissions to "/opt/iobroker" and "/opt/scripts" +echo "(Re)Setting folder permissions (This might take a while! Please be patient!)..." + chown -R $setuid:$setgid /opt/iobroker + chown -R $setuid:$setgid /opt/scripts +echo "Done." +echo ' ' + +# Backing up original iobroker-file and changing sudo to gosu +echo "Fixing \"sudo-bug\" by replacing sudo in iobroker with gosu..." + cp -a /opt/iobroker/iobroker /opt/iobroker/iobroker.bak + chmod 755 /opt/iobroker/iobroker + sed -i 's/sudo -H -u/gosu/g' /opt/iobroker/iobroker +echo "Done." +echo ' ' + +# Checking for first run of a new installation and renaming ioBroker +if [ -f /opt/scripts/.docker_config/.install_host ] +then + echo "Looks like this is a new and empty installation of ioBroker." + echo "Hostname needs to be updated to " $(hostname)"..." + bash iobroker host $(cat /opt/scripts/.docker_config/.install_host) + rm -f /opt/scripts/.docker_config/.install_host + echo "Done." + echo ' ' +elif [ $(bash iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="host": ")[^"]*') != $(hostname) ] +then + echo "Hostname in ioBroker does not match the hostname of this container." + echo "Updating hostname to " $(hostname)"..." + bash iobroker host $(iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="host": ")[^"]*') + echo "Done." + echo ' ' +fi + + +##### +# Setting up prerequisites for some ioBroker-adapters +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 4 of 5: Applying special settings -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +echo "Some adapters have special requirements/ settings which can be activated by the use of environment variables." +echo "For more information take a look at readme.md on Github!" +echo ' ' + + +# Checking ENV for Adminport +if [ "$adminport" != "" ] +then + if [ "$adminport" != $(bash iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="port": )[^,]*') ] + then + echo "Adminport set by ENV does not match port configured in ioBroker installation." + echo "Setting Adminport to \""$adminport"\"..." + bash iobroker set admin.0 --port $adminport + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for AVAHI +if [ "$avahi" != "" ] +then + if [ "$avahi" = "true" ] + then + echo "Avahi-daemon is activated by ENV." + chmod 755 /opt/scripts/setup_avahi.sh + bash /opt/scripts/setup_avahi.sh + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for Z-WAVE +if [ "$zwave" != "" ] +then + if [ "$zwave" = "true" ] + then + echo "Z-Wave is activated by ENV." + chmod 755 /opt/scripts/setup_zwave.sh + bash /opt/scripts/setup_zwave.sh + echo "Done." + echo ' ' + fi +fi + + +# checking ENV for USBDEVICES +if [ "$usbdevices" != "" ] +then + if [ "$usbdevices" != "none" ] + then + echo "Usb-device-support is activated by ENV." + IFS=';' read -ra devicearray <<< "$usbdevices" + for i in "${devicearray[@]}" + do + echo "Setting permissions for" $i"..." + chown root:dialout $i + chmod g+rw $i + done + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for multihost setup +# Configuring objects db host +if [ "$multihost" = "master" ] && [ "$objectsdbtype" = "" ] && [ "$objectsdbhost" = "" ] && [ "$objectsdbport" = "" ] +then + echo "Multihost is set as \"master\" by ENV and no external objects db is set." + echo "Setting host of objects db to \"0.0.0.0\" to allow external communication..." + jq --arg objectsdbhost "0.0.0.0" '.objects.host = $objectsdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + echo ' ' +elif [ "$multihost" = "master" ] && [ "$objectsdbhost" = "127.0.0.1" ] +then + echo "Multihost is set as \"master\" by ENV. But objects db host is set to \"127.0.0.1\" by ENV too." + echo "This configuration will not work! Please change or remove ENV \"IOB_OBJECTSDB_HOST\" and start over!" + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "master" ] && [ "$objectsdbtype" != "" ] && [ "$objectsdbhost" != "" ] && [ "$objectsdbport" != "" ] +then + echo "Multihost is set as \"master\" by ENV and external objects db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif ([ "$multihost" = "slave" ] && [ "$objectsdbtype" = "" ]) || ([ "$multihost" = "slave" ] && [ "$objectsdbhost" = "" ]) || ([ "$multihost" = "slave" ] && [ "$objectsdbport" = "" ]) +then + echo "Multihost is set as \"slave\" by ENV. But no external objects db is set." + echo "You have to configure ENVs \"IOB_OBJECTSDB_TYPE\", \"IOB_OBJECTSDB_HOST\" and \"IOB_OBJECTSDB_PORT\" to connect to a maser objects db." + echo "Please check your settings and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "slave" ] && [ "$objectsdbtype" != "" ] && [ "$objectsdbhost" != "" ] && [ "$objectsdbport" != "" ] +then + echo "Multihost is set as \"slave\" by ENV and external objects db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif [ "$multihost" != "" ] +then + echo "Multihost is set but it seems like some configuration is missing." + echo "Please checke if you have configured the ENVs \"MULTIHOST\", \"IOB_OBJECTSDB_TYPE\", \"IOB_OBJECTSDB_HOST\" and \"IOB_OBJECTSDB_PORT\" correctly and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +fi +#Configuring states db host +if [ "$multihost" = "master" ] && [ "$statesdbtype" = "" ] && [ "$statesdbhost" = "" ] && [ "$statesdbport" = "" ] +then + echo "Multihost is set as \"master\" by ENV and no external states db is set." + echo "Setting host of states db to \"0.0.0.0\" to allow external communication..." + jq --arg statesdbhost "0.0.0.0" '.states.host = $statesdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + echo ' ' +elif [ "$multihost" = "master" ] && [ "$statesdbhost" = "127.0.0.1" ] +then + echo "Multihost is set as \"master\" by ENV. But states db host is set to \"127.0.0.1\" by ENV too." + echo "This configuration will not work! Please change or remove ENV \"IOB_STATESDB_HOST\" and start over!" + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "master" ] && [ "$statesdbtype" != "" ] && [ "$statesdbhost" != "" ] && [ "$statesdbport" != "" ] +then + echo "Multihost is set as \"master\" by ENV and external states db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif ([ "$multihost" = "slave" ] && [ "$statesdbtype" = "" ]) || ([ "$multihost" = "slave" ] && [ "$statesdbhost" = "" ]) || ([ "$multihost" = "slave" ] && [ "$statesdbport" = "" ]) +then + echo "Multihost is set as \"slave\" by ENV. But no external states db is set." + echo "You have to configure ENVs \"IOB_STATESDB_TYPE\", \"IOB_STATESDB_HOST\" and \"IOB_STATESDB_PORT\" to connect to a maser states db." + echo "Please check your settings and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "slave" ] && [ "$statesdbtype" != "" ] && [ "$statesdbhost" != "" ] && [ "$statesdbport" != "" ] +then + echo "Multihost is set as \"slave\" by ENV and external states db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif [ "$multihost" != "" ] +then + echo "Multihost is set but it seems like some configuration is missing." + echo "Please checke if you have configured the ENVs \"MULTIHOST\", \"IOB_STATESDB_TYPE\", \"IOB_STATESDB_HOST\" and \"IOB_STATESTDB_PORT\" correctly and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +fi + + +# Checking ENVs for custom setup of objects db +if [ "$objectsdbtype" != "" ] || [ "$objectsdbhost" != "" ] || [ "$objectsdbport" != "" ] +then + if [ "$objectsdbtype" != $(jq -r '.objects.type' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_TYPE is set and value is different from detected ioBroker installation." + echo "Setting type of objects db to \""$objectsdbtype"\"..." + jq --arg objectsdbtype "$objectsdbtype" '.objects.type = $objectsdbtype' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_TYPE is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$objectsdbhost" != $(jq -r '.objects.host' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_HOST is set and value is different from detected ioBroker installation." + echo "Setting host of objects db to \""$objectsdbhost"\"..." + jq --arg objectsdbhost "$objectsdbhost" '.objects.host = $objectsdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_HOST is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$objectsdbport" != $(jq -r '.objects.port' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_PORT is set and value is different from detected ioBroker installation." + echo "Setting port of objects db to \""$objectsdbport"\"..." + jq --arg objectsdbport $objectsdbport '.objects.port = $objectsdbport' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_PORT is set and value meets detected ioBroker installation. Nothing to do here." + fi + echo ' ' +fi + + +# Checking ENVs for custom setup of states db# +if [ "$statesdbtype" != "" ] || [ "$statesdbhost" != "" ] || [ "$statesdbport" != "" ] +then + if [ "$statesdbtype" != $(jq -r '.states.type' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_TYPE is set and value is different from detected ioBroker installation." + echo "Setting type of states db to \""$statesdbtype"\"..." + jq --arg statesdbtype "$statesdbtype" '.states.type = $statesdbtype' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_TYPE is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$statesdbhost" != $(jq -r '.states.host' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_HOST is set and value is different from detected ioBroker installation." + echo "Setting host of states db to \""$statesdbhost"\"..." + jq --arg statesdbhost "$statesdbhost" '.states.host = $statesdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_HOST is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$statesdbport" != $(jq -r '.states.port' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_PORT is set and value is different from detected ioBroker installation." + echo "Setting port of states db to \""$statesdbport"\"..." + jq --arg statesdbport $statesdbport '.states.port = $statesdbport' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_PORT is set and value meets detected ioBroker installation. Nothing to do here." + fi + echo ' ' +fi + + +# Checking for Userscripts in /opt/userscripts +if [ `find /opt/userscripts -type f | wc -l` -lt 1 ] +then + echo "There is no data detected in /opt/userscripts. Restoring exapmple userscripts..." + tar -xf /opt/initial_userscripts.tar -C / + chmod 755 /opt/userscripts/userscript_firststart_example.sh + chmod 755 /opt/userscripts/userscript_everystart_example.sh + echo "Done." + echo ' ' +elif [ -f /opt/userscripts/userscript_firststart.sh ] || [ -f /opt/userscripts/userscript_everystart.sh ] +then + if [ -f /opt/userscripts/userscript_firststart.sh ] && [ -f /opt/.firstrun ] + then + echo "Userscript for first start detected and this is the first start of a new container." + echo "Running userscript_firststart.sh..." + chmod 755 /opt/userscripts/userscript_firststart.sh + bash /opt/userscripts/userscript_firststart.sh + echo "Done." + echo ' ' + fi + if [ -f /opt/userscripts/userscript_everystart.sh ] + then + echo "Userscript for every start detected. Running userscript_everystart.sh..." + chmod 755 /opt/userscripts/userscript_everystart.sh + bash /opt/userscripts/userscript_everystart.sh + echo "Done." + echo ' ' + fi +fi + +# Removing first run marker when exists +if [ -f /opt/.firstrun ] +then +rm -f /opt/.firstrun +fi + +##### +# Starting ioBroker +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 5 of 5: ioBroker startup -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "Starting ioBroker..." +echo ' ' + +# Setting healthcheck status to "running" +echo "running" > /opt/scripts/.docker_config/.healthcheck + +# Function for graceful shutdown by SIGTERM signal +shut_down() { + echo ' ' + echo "Recived termination signal (SIGTERM)." + echo "Shutting down ioBroker..." + pid=$(ps -ef | awk '/[j]s.controller/{print $2}') + kill -SIGTERM "$pid" + exit +} + +# Trap to get signal for graceful shutdown +trap 'shut_down' SIGTERM + +# IoBroker start +gosu iobroker node node_modules/iobroker.js-controller/controller.js & wait + +# Fallback process for keeping container running when ioBroker is stopped for maintenance (e.g. js-controller update) +tail -f /dev/null \ No newline at end of file diff --git a/ioBroker/iobroker_startup_ori.sh b/ioBroker/iobroker_startup_ori.sh new file mode 100644 index 0000000..2fadcd2 --- /dev/null +++ b/ioBroker/iobroker_startup_ori.sh @@ -0,0 +1,506 @@ +#!/bin/bash + +# Setting healthcheck status to "starting" +echo "starting" > /opt/scripts/.docker_config/.healthcheck + +# Reading ENV +adminport=$IOB_ADMINPORT +avahi=$AVAHI +multihost=$IOB_MULTIHOST +objectsdbhost=$IOB_OBJECTSDB_HOST +objectsdbport=$IOB_OBJECTSDB_PORT +objectsdbtype=$IOB_OBJECTSDB_TYPE +packages=$PACKAGES +setgid=$SETGID +setuid=$SETUID +statesdbhost=$IOB_STATESDB_HOST +statesdbport=$IOB_STATESDB_PORT +statesdbtype=$IOB_STATESDB_TYPE +usbdevices=$USBDEVICES +zwave=$ZWAVE + +# Getting date and time for logging +dati=`date '+%Y-%m-%d %H:%M:%S'` + +# Logging header +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo -n "$(printf -- '-%.0s' {1..15})" && echo -n " "$dati" " && echo "$(printf -- '-%.0s' {1..15})" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Welcome to your ioBroker-container! -----" +echo "----- Startupscript is now running. -----" +echo "----- Please be patient! -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Debugging information -----" +echo "----- -----" +echo "----- System -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" arch: $(uname -m))" && echo " -----" +echo "----- -----" +echo "----- Versions -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" image: $VERSION)" && echo " -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" node: $(node -v))" && echo " -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" npm: $(npm -v))" && echo " -----" +echo "----- -----" +echo "----- ENV -----" +if [ "$adminport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_ADMINPORT: $adminport)" && echo " -----"; fi +if [ "$avahi" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" AVAHI: $avahi)" && echo " -----"; fi +if [ "$multihost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_MULTIHOST: $multihost)" && echo " -----"; fi +if [ "$objectsdbhost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_HOST: $objectsdbhost)" && echo " -----"; fi +if [ "$objectsdbport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_PORT: $objectsdbport)" && echo " -----"; fi +if [ "$objectsdbtype" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_OBJECTSDB_TYPE: $objectsdbtype)" && echo " -----"; fi +if [ "$packages" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" PACKAGES: $packages)" && echo " -----"; fi +if [ "$setgid" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" SETGID: $setgid)" && echo " -----"; fi +if [ "$setuid" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" SETUID: $setuid)" && echo " -----"; fi +if [ "$statesdbhost" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_HOST: $statesdbhost)" && echo " -----"; fi +if [ "$statesdbport" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_PORT: $statesdbport)" && echo " -----"; fi +if [ "$statesdbtype" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" IOB_STATESDB_TYPE: $statesdbtype)" && echo " -----"; fi +if [ "$usbdevices" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" USBDEVICES: $usbdevices)" && echo " -----"; fi +if [ "$zwave" != "" ]; then echo -n "----- " && echo -n "$(printf "%-10s %-23s" ZWAVE: $zwave)" && echo " -----"; fi +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +##### +# STEP 1 - Preparing container +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 1 of 5: Preparing container -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +# Installing additional packages and setting uid/gid +if [ "$packages" != "" ] || [ $(cat /etc/group | grep 'iobroker:' | cut -d':' -f3) != $setgid ] || [ $(cat /etc/passwd | grep 'iobroker:' | cut -d':' -f3) != $setuid ] || [ -f /opt/.firstrun ] +then + if [ "$packages" != "" ] + then + echo "Installing additional packages is set by ENV." + echo "The following packages will be installed:" $packages"..." + echo $packages > /opt/scripts/.packages + bash /opt/scripts/setup_packages.sh + echo "Done." + echo ' ' + fi + if [ $(cat /etc/group | grep 'iobroker:' | cut -d':' -f3) != $setgid ] || [ $(cat /etc/passwd | grep 'iobroker:' | cut -d':' -f3) != $setuid ] + then + echo "Different UID and/ or GID is set by ENV." + echo "Changing UID to "$setuid" and GID to "$setgid"..." + usermod -u $setuid iobroker + groupmod -g $setgid iobroker + echo "Done." + echo ' ' + fi + if [ -f /opt/.firstrun ] + then + echo "Registering maintenance script as command." + echo "alias maintenance=\'/opt/scripts/maintenance.sh\'" >> /root/.bashrc + echo "Done." + echo ' ' + fi +else + echo "Nothing to do here." + echo ' ' +fi + +# Change directory for next steps +cd /opt/iobroker + + +##### +# Detecting ioBroker-Installation +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 2 of 5: Detecting ioBroker installation -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +if [ `find /opt/iobroker -type f | wc -l` -lt 1 ] +then + echo "There is no data detected in /opt/iobroker. Restoring initial ioBroker installation..." + tar -xf /opt/initial_iobroker.tar -C / + echo "Done." +elif [ -f /opt/iobroker/iobroker ] +then + echo "Existing installation of ioBroker detected in /opt/iobroker." + rm -f /opt/scripts/.docker_config/.install_host +elif [ $(ls *_backupiobroker.tar.gz 2> /dev/null | wc -l) != "0" ] && [ $(tar -ztvf /opt/iobroker/*_backupiobroker.tar.gz "backup/backup.json" 2> /dev/null | wc -l) != "0" ] +then + if [ "$multihost" = "slave" ] + then + echo "IoBroker backup file detected in /opt/iobroker. But Multihost is set to \"slave\"." + echo "Restoring a backup is not supported on Multihost slaves. Please check configuration and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 + else + echo "IoBroker backup file detected in /opt/iobroker. Preparing restore..." + mv /opt/iobroker/*.tar.gz /opt/ + tar -xf /opt/initial_iobroker.tar -C / + mkdir /opt/iobroker/backups + mv /opt/*.tar.gz /opt/iobroker/backups/ + chown -R $setuid:$setgid /opt/iobroker # fixes permission error during restore + echo "Done." + echo "Restoring ioBroker..." + iobroker restore 0 > /opt/iobroker/log/restore.log 2>&1 + echo "Done." + echo ' ' + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo "!!!!! IMPORTANT NOTE !!!!!" + echo "!!!!! The sartup script restored iobroker from a backup file. !!!!!" + echo "!!!!! Check /opt/iobroker/log/restore.log to see if restore was successful. !!!!!" + echo "!!!!! When ioBroker now starts it will reinstall all Adapters automatically. !!!!!" + echo "!!!!! This might be take a looooong time! Please be patient! !!!!!" + echo "!!!!! You can view installation process by taking a look at ioBroker log. !!!!!" + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + fi +else + echo "There is data detected in /opt/iobroker but it looks like it is no instance of ioBroker or a valid backup file!" + echo "Please check/ recreate mounted folder/ volume and start over." + exit 1 +fi +echo ' ' + + +##### +# Checking ioBroker-Installation +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 3 of 5: Checking ioBroker installation -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +# (Re)Setting permissions to "/opt/iobroker" and "/opt/scripts" +echo "(Re)Setting folder permissions (This might take a while! Please be patient!)..." + chown -R $setuid:$setgid /opt/iobroker + chown -R $setuid:$setgid /opt/scripts +echo "Done." +echo ' ' + +# Backing up original iobroker-file and changing sudo to gosu +echo "Fixing \"sudo-bug\" by replacing sudo in iobroker with gosu..." + cp -a /opt/iobroker/iobroker /opt/iobroker/iobroker.bak + chmod 755 /opt/iobroker/iobroker + sed -i 's/sudo -H -u/gosu/g' /opt/iobroker/iobroker +echo "Done." +echo ' ' + +# Checking for first run of a new installation and renaming ioBroker +if [ -f /opt/scripts/.docker_config/.install_host ] +then + echo "Looks like this is a new and empty installation of ioBroker." + echo "Hostname needs to be updated to " $(hostname)"..." + bash iobroker host $(cat /opt/scripts/.docker_config/.install_host) + rm -f /opt/scripts/.docker_config/.install_host + echo "Done." + echo ' ' +elif [ $(bash iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="host": ")[^"]*') != $(hostname) ] +then + echo "Hostname in ioBroker does not match the hostname of this container." + echo "Updating hostname to " $(hostname)"..." + bash iobroker host $(iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="host": ")[^"]*') + echo "Done." + echo ' ' +fi + + +##### +# Setting up prerequisites for some ioBroker-adapters +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 4 of 5: Applying special settings -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' + +echo "Some adapters have special requirements/ settings which can be activated by the use of environment variables." +echo "For more information take a look at readme.md on Github!" +echo ' ' + + +# Checking ENV for Adminport +if [ "$adminport" != "" ] +then + if [ "$adminport" != $(bash iobroker object get system.adapter.admin.0 --pretty | grep -oP '(?<="port": )[^,]*') ] + then + echo "Adminport set by ENV does not match port configured in ioBroker installation." + echo "Setting Adminport to \""$adminport"\"..." + bash iobroker set admin.0 --port $adminport + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for AVAHI +if [ "$avahi" != "" ] +then + if [ "$avahi" = "true" ] + then + echo "Avahi-daemon is activated by ENV." + chmod 755 /opt/scripts/setup_avahi.sh + bash /opt/scripts/setup_avahi.sh + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for Z-WAVE +if [ "$zwave" != "" ] +then + if [ "$zwave" = "true" ] + then + echo "Z-Wave is activated by ENV." + chmod 755 /opt/scripts/setup_zwave.sh + bash /opt/scripts/setup_zwave.sh + echo "Done." + echo ' ' + fi +fi + + +# checking ENV for USBDEVICES +if [ "$usbdevices" != "" ] +then + if [ "$usbdevices" != "none" ] + then + echo "Usb-device-support is activated by ENV." + IFS=';' read -ra devicearray <<< "$usbdevices" + for i in "${devicearray[@]}" + do + echo "Setting permissions for" $i"..." + chown root:dialout $i + chmod g+rw $i + done + echo "Done." + echo ' ' + fi +fi + + +# Checking ENV for multihost setup +# Configuring objects db host +if [ "$multihost" = "master" ] && [ "$objectsdbtype" = "" ] && [ "$objectsdbhost" = "" ] && [ "$objectsdbport" = "" ] +then + echo "Multihost is set as \"master\" by ENV and no external objects db is set." + echo "Setting host of objects db to \"0.0.0.0\" to allow external communication..." + jq --arg objectsdbhost "0.0.0.0" '.objects.host = $objectsdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + echo ' ' +elif [ "$multihost" = "master" ] && [ "$objectsdbhost" = "127.0.0.1" ] +then + echo "Multihost is set as \"master\" by ENV. But objects db host is set to \"127.0.0.1\" by ENV too." + echo "This configuration will not work! Please change or remove ENV \"IOB_OBJECTSDB_HOST\" and start over!" + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "master" ] && [ "$objectsdbtype" != "" ] && [ "$objectsdbhost" != "" ] && [ "$objectsdbport" != "" ] +then + echo "Multihost is set as \"master\" by ENV and external objects db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif ([ "$multihost" = "slave" ] && [ "$objectsdbtype" = "" ]) || ([ "$multihost" = "slave" ] && [ "$objectsdbhost" = "" ]) || ([ "$multihost" = "slave" ] && [ "$objectsdbport" = "" ]) +then + echo "Multihost is set as \"slave\" by ENV. But no external objects db is set." + echo "You have to configure ENVs \"IOB_OBJECTSDB_TYPE\", \"IOB_OBJECTSDB_HOST\" and \"IOB_OBJECTSDB_PORT\" to connect to a maser objects db." + echo "Please check your settings and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "slave" ] && [ "$objectsdbtype" != "" ] && [ "$objectsdbhost" != "" ] && [ "$objectsdbport" != "" ] +then + echo "Multihost is set as \"slave\" by ENV and external objects db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif [ "$multihost" != "" ] +then + echo "Multihost is set but it seems like some configuration is missing." + echo "Please checke if you have configured the ENVs \"MULTIHOST\", \"IOB_OBJECTSDB_TYPE\", \"IOB_OBJECTSDB_HOST\" and \"IOB_OBJECTSDB_PORT\" correctly and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +fi +#Configuring states db host +if [ "$multihost" = "master" ] && [ "$statesdbtype" = "" ] && [ "$statesdbhost" = "" ] && [ "$statesdbport" = "" ] +then + echo "Multihost is set as \"master\" by ENV and no external states db is set." + echo "Setting host of states db to \"0.0.0.0\" to allow external communication..." + jq --arg statesdbhost "0.0.0.0" '.states.host = $statesdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + echo ' ' +elif [ "$multihost" = "master" ] && [ "$statesdbhost" = "127.0.0.1" ] +then + echo "Multihost is set as \"master\" by ENV. But states db host is set to \"127.0.0.1\" by ENV too." + echo "This configuration will not work! Please change or remove ENV \"IOB_STATESDB_HOST\" and start over!" + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "master" ] && [ "$statesdbtype" != "" ] && [ "$statesdbhost" != "" ] && [ "$statesdbport" != "" ] +then + echo "Multihost is set as \"master\" by ENV and external states db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif ([ "$multihost" = "slave" ] && [ "$statesdbtype" = "" ]) || ([ "$multihost" = "slave" ] && [ "$statesdbhost" = "" ]) || ([ "$multihost" = "slave" ] && [ "$statesdbport" = "" ]) +then + echo "Multihost is set as \"slave\" by ENV. But no external states db is set." + echo "You have to configure ENVs \"IOB_STATESDB_TYPE\", \"IOB_STATESDB_HOST\" and \"IOB_STATESDB_PORT\" to connect to a maser states db." + echo "Please check your settings and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +elif [ "$multihost" = "slave" ] && [ "$statesdbtype" != "" ] && [ "$statesdbhost" != "" ] && [ "$statesdbport" != "" ] +then + echo "Multihost is set as \"slave\" by ENV and external states db is set." + echo "Skipping this step..." + echo "Done." + echo ' ' +elif [ "$multihost" != "" ] +then + echo "Multihost is set but it seems like some configuration is missing." + echo "Please checke if you have configured the ENVs \"MULTIHOST\", \"IOB_STATESDB_TYPE\", \"IOB_STATESDB_HOST\" and \"IOB_STATESTDB_PORT\" correctly and start over." + echo "For more information see readme.md on Github (https://github.com/buanet/docker-iobroker)." + exit 1 +fi + + +# Checking ENVs for custom setup of objects db +if [ "$objectsdbtype" != "" ] || [ "$objectsdbhost" != "" ] || [ "$objectsdbport" != "" ] +then + if [ "$objectsdbtype" != $(jq -r '.objects.type' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_TYPE is set and value is different from detected ioBroker installation." + echo "Setting type of objects db to \""$objectsdbtype"\"..." + jq --arg objectsdbtype "$objectsdbtype" '.objects.type = $objectsdbtype' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_TYPE is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$objectsdbhost" != $(jq -r '.objects.host' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_HOST is set and value is different from detected ioBroker installation." + echo "Setting host of objects db to \""$objectsdbhost"\"..." + jq --arg objectsdbhost "$objectsdbhost" '.objects.host = $objectsdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_HOST is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$objectsdbport" != $(jq -r '.objects.port' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_OBJECTSDB_PORT is set and value is different from detected ioBroker installation." + echo "Setting port of objects db to \""$objectsdbport"\"..." + jq --arg objectsdbport $objectsdbport '.objects.port = $objectsdbport' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_OBJECTSDB_PORT is set and value meets detected ioBroker installation. Nothing to do here." + fi + echo ' ' +fi + + +# Checking ENVs for custom setup of states db# +if [ "$statesdbtype" != "" ] || [ "$statesdbhost" != "" ] || [ "$statesdbport" != "" ] +then + if [ "$statesdbtype" != $(jq -r '.states.type' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_TYPE is set and value is different from detected ioBroker installation." + echo "Setting type of states db to \""$statesdbtype"\"..." + jq --arg statesdbtype "$statesdbtype" '.states.type = $statesdbtype' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_TYPE is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$statesdbhost" != $(jq -r '.states.host' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_HOST is set and value is different from detected ioBroker installation." + echo "Setting host of states db to \""$statesdbhost"\"..." + jq --arg statesdbhost "$statesdbhost" '.states.host = $statesdbhost' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_HOST is set and value meets detected ioBroker installation. Nothing to do here." + fi + if [ "$statesdbport" != $(jq -r '.states.port' /opt/iobroker/iobroker-data/iobroker.json) ] + then + echo "ENV IOB_STATESDB_PORT is set and value is different from detected ioBroker installation." + echo "Setting port of states db to \""$statesdbport"\"..." + jq --arg statesdbport $statesdbport '.states.port = $statesdbport' /opt/iobroker/iobroker-data/iobroker.json > /opt/iobroker/iobroker-data/iobroker.json.tmp && mv /opt/iobroker/iobroker-data/iobroker.json.tmp /opt/iobroker/iobroker-data/iobroker.json + chown -R $setuid:$setgid /opt/iobroker/iobroker-data/iobroker.json && chmod 674 /opt/iobroker/iobroker-data/iobroker.json + echo "Done." + else + echo "ENV IOB_STATESDB_PORT is set and value meets detected ioBroker installation. Nothing to do here." + fi + echo ' ' +fi + + +# Checking for Userscripts in /opt/userscripts +if [ `find /opt/userscripts -type f | wc -l` -lt 1 ] +then + echo "There is no data detected in /opt/userscripts. Restoring exapmple userscripts..." + tar -xf /opt/initial_userscripts.tar -C / + chmod 755 /opt/userscripts/userscript_firststart_example.sh + chmod 755 /opt/userscripts/userscript_everystart_example.sh + echo "Done." + echo ' ' +elif [ -f /opt/userscripts/userscript_firststart.sh ] || [ -f /opt/userscripts/userscript_everystart.sh ] +then + if [ -f /opt/userscripts/userscript_firststart.sh ] && [ -f /opt/.firstrun ] + then + echo "Userscript for first start detected and this is the first start of a new container." + echo "Running userscript_firststart.sh..." + chmod 755 /opt/userscripts/userscript_firststart.sh + bash /opt/userscripts/userscript_firststart.sh + echo "Done." + echo ' ' + fi + if [ -f /opt/userscripts/userscript_everystart.sh ] + then + echo "Userscript for every start detected. Running userscript_everystart.sh..." + chmod 755 /opt/userscripts/userscript_everystart.sh + bash /opt/userscripts/userscript_everystart.sh + echo "Done." + echo ' ' + fi +fi + +# Removing first run marker when exists +if [ -f /opt/.firstrun ] +then +rm -f /opt/.firstrun +fi + +##### +# Starting ioBroker +##### +echo "$(printf -- '-%.0s' {1..60})" +echo "----- Step 5 of 5: ioBroker startup -----" +echo "$(printf -- '-%.0s' {1..60})" +echo ' ' +echo "Starting ioBroker..." +echo ' ' + +# Setting healthcheck status to "running" +echo "running" > /opt/scripts/.docker_config/.healthcheck + +# Function for graceful shutdown by SIGTERM signal +shut_down() { + echo ' ' + echo "Recived termination signal (SIGTERM)." + echo "Shutting down ioBroker..." + pid=$(ps -ef | awk '/[j]s.controller/{print $2}') + kill -SIGTERM "$pid" + exit +} + +# Trap to get signal for graceful shutdown +trap 'shut_down' SIGTERM + +# IoBroker start +gosu iobroker node node_modules/iobroker.js-controller/controller.js & wait + +# Fallback process for keeping container running when ioBroker is stopped for maintenance (e.g. js-controller update) +tail -f /dev/null \ No newline at end of file diff --git a/ioBroker/logo.png b/ioBroker/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d3526e578f703b6ca5c0adcfbcfce6e6953516 GIT binary patch literal 5584 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 VpI`%CBwP~!byY2ua%GFq{{j2oRb~JH literal 0 HcmV?d00001