From 801015cb2899b472b86d82876a2e20c9f9b529c5 Mon Sep 17 00:00:00 2001 From: buanet Date: Sat, 28 Aug 2021 20:36:46 +0200 Subject: [PATCH] testing for slim image --- .github/workflows/build-image-dev-slim.yml | 101 ++++ slim/Dockerfile-slim-amd64 | 85 +++ slim/scripts/healthcheck.sh | 20 + slim/scripts/iobroker_startup.sh | 517 ++++++++++++++++++ slim/scripts/maintenance.sh | 110 ++++ slim/scripts/setup_avahi.sh | 35 ++ slim/scripts/setup_packages.sh | 22 + slim/scripts/setup_zwave.sh | 19 + .../userscript_everystart_example.sh | 13 + .../userscript_firststart_example.sh | 12 + 10 files changed, 934 insertions(+) create mode 100644 .github/workflows/build-image-dev-slim.yml create mode 100644 slim/Dockerfile-slim-amd64 create mode 100644 slim/scripts/healthcheck.sh create mode 100644 slim/scripts/iobroker_startup.sh create mode 100644 slim/scripts/maintenance.sh create mode 100644 slim/scripts/setup_avahi.sh create mode 100644 slim/scripts/setup_packages.sh create mode 100644 slim/scripts/setup_zwave.sh create mode 100644 slim/userscripts/userscript_everystart_example.sh create mode 100644 slim/userscripts/userscript_firststart_example.sh diff --git a/.github/workflows/build-image-dev-slim.yml b/.github/workflows/build-image-dev-slim.yml new file mode 100644 index 0000000..8b71f58 --- /dev/null +++ b/.github/workflows/build-image-dev-slim.yml @@ -0,0 +1,101 @@ +# Github action to build Docker image from dev branch (tag: dev) + +name: Build slim image from dev + +on: + workflow_dispatch: +# push: +# branches: +# - dev + +jobs: + bulid-dev-slim: + runs-on: ubuntu-latest + steps: + - name: Checkout repo (dev) + uses: actions/checkout@v2.3.4 + with: + repository: 'buanet/ioBroker.docker' + ref: 'dev' + + - name: Get and write version and date + id: version + run: | + VERSION="$(cat .VERSION)" + MAJORVERSION="$(cat .VERSION | cut -c 1-2 | sed -r 's#^(.{0})#\1latest-#')" + DATI="$(date --rfc-3339=seconds | sed 's/ /T/')" + echo "This is the Version: $VERSION" + echo "version=$VERSION" >> $GITHUB_ENV + echo "This is the Major Version: $MAJORVERSION" + echo "majorversion=$MAJORVERSION" >> $GITHUB_ENV + echo "This is the Buildnumber/Timestamp: $DATI" + echo "dati=$DATI" >> $GITHUB_ENV + # startup script + sed -e "s/\${VERSION}/$VERSION-slim-dev/" -e "s/\${BUILD}/$DATI/" ./slim/scripts/iobroker_startup.sh > ./slim/scripts/iobroker_startup.tmp + mv -f ./slim/scripts/iobroker_startup.tmp ./slim/scripts/iobroker_startup.sh + # amd64 + sed -e "s/\${VERSION}/$VERSION-slim-dev/" -e "s/\${DATI}/$DATI/" ./slim/Dockerfile-slim-amd64 > ./slim/Dockerfile-slim-amd64.tmp + mv -f ./slim/Dockerfile-slim-amd64.tmp ./slim/Dockerfile-slim-amd64 + + - name: Set up manifest tool + run: | + wget https://github.com/estesp/manifest-tool/releases/download/v0.7.0/manifest-tool-linux-amd64 -O manifest-tool + chmod +x manifest-tool + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1.2.0 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1.5.1 + + - name: Login to DockerHub + uses: docker/login-action@v1.10.0 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1.10.0 + with: + registry: ghcr.io + username: ${{ secrets.PACKAGES_USER }} + password: ${{ secrets.PACKAGES_PASS }} + + - name: Build Docker image (slim-amd64) + uses: docker/build-push-action@v2.6.1 + with: + context: ./slim + file: ./slim/Dockerfile-slim-amd64 + push: true + platforms: linux/amd64 + tags: | + buanet/iobroker:dev-slim-amd64, + ghcr.io/buanet/iobroker:dev-slim-amd64 + + - name: Create and push manifests + run: | + sed -e "s/\${VERSION}/dev-slim/g" -e "s/\${DOCKERTAG}/dev-slim/g" ./manifest.yml > manifest_dev-slim.yaml + ./manifest-tool --username ${{ secrets.DOCKER_USER }} --password ${{ secrets.DOCKER_PASS }} push from-spec manifest_dev-slim.yaml + sed -e "s/\${VERSION}/dev-slim/g" -e "s/\${DOCKERTAG}/dev-slim/g" ./manifest_ghcr.yml > manifest_ghcr_dev-slim.yaml + ./manifest-tool --username ${{ secrets.PACKAGES_USER }} --password ${{ secrets.PACKAGES_PASS }} push from-spec manifest_ghcr_dev-slim.yaml + + - name: Delete untagged images from GitHub packages + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.PACKAGES_PASS }} + script: | + const response = await github.request("GET /users/${{ env.OWNER }}/packages/container/${{ env.PACKAGE_NAME }}/versions", + { per_page: ${{ env.PER_PAGE }} + }); + for(version of response.data) { + if (version.metadata.container.tags.length == 0) { + console.log("delete " + version.id) + const deleteResponse = await github.request("DELETE /user/packages/container/${{ env.PACKAGE_NAME }}/versions/" + version.id, { }); + console.log("status " + deleteResponse.status) + } + } + env: + OWNER: buanet + PACKAGE_NAME: iobroker + PER_PAGE: 100 diff --git a/slim/Dockerfile-slim-amd64 b/slim/Dockerfile-slim-amd64 new file mode 100644 index 0000000..560cc20 --- /dev/null +++ b/slim/Dockerfile-slim-amd64 @@ -0,0 +1,85 @@ +FROM debian:bullseye-slim + +LABEL org.opencontainers.image.title="ioBroker Docker Image" \ + org.opencontainers.image.description="Docker image for ioBroker smarthome software" \ + org.opencontainers.image.authors="info@buanet.de" \ + org.opencontainers.image.url="https://github.com/buanet/ioBroker.docker" \ + org.opencontainers.image.version="${VERSION}" \ + org.opencontainers.image.created="${DATI}" + +ENV DEBIAN_FRONTEND noninteractive + +# Install prerequisites +RUN apt-get update && apt-get install -y \ + curl \ + gosu \ + jq \ + locales \ + sudo \ + udev \ + && rm -rf /var/lib/apt/lists/* + +# Install node +RUN curl -sL https://deb.nodesource.com/setup_12.x | bash \ + && apt-get update && apt-get install -y nodejs \ + && rm -rf /var/lib/apt/lists/* + +# Generating locales +RUN sed -i 's/^# *\(de_DE.UTF-8\)/\1/' /etc/locale.gen \ + && sed -i 's/^# *\(en_US.UTF-8\)/\1/' /etc/locale.gen \ + && locale-gen + +# Create scripts directorys and copy scripts +RUN mkdir -p /opt/scripts/ \ + && mkdir -p /opt/userscripts/ \ + && chmod 777 /opt/scripts/ \ + && chmod 777 /opt/userscripts/ +WORKDIR /opt/scripts/ +COPY scripts/*.sh *.sh +RUN chmod +x *.sh +WORKDIR /opt/userscripts/ +COPY scripts/*.sh *.sh +RUN chmod +x *.sh + +# Install ioBroker +WORKDIR / +RUN apt-get update \ + && curl -sL https://iobroker.net/install.sh | bash - \ + && mkdir -p /opt/scripts/.docker_config/ \ + && echo $(hostname) > /opt/scripts/.docker_config/.install_host \ + && echo "starting" > /opt/scripts/.docker_config/.healthcheck \ + && echo $(hostname) > /opt/.firstrun \ + && rm -rf /var/lib/apt/lists/* + +# Install node-gyp +# WORKDIR /opt/iobroker/ +# RUN npm install -g node-gyp + +# Backup initial ioBroker and userscript folder +RUN tar -cf /opt/initial_iobroker.tar /opt/iobroker \ + && tar -cf /opt/initial_userscripts.tar /opt/userscripts + +# Setting up iobroker-user (shell and home directory) +RUN chsh -s /bin/bash iobroker \ + && usermod --home /opt/iobroker iobroker \ + && usermod -u 1000 iobroker \ + && groupmod -g 1000 iobroker + +# Setting up ENVs +ENV DEBIAN_FRONTEND="teletype" \ + LANG="de_DE.UTF-8" \ + LANGUAGE="de_DE:de" \ + LC_ALL="de_DE.UTF-8" \ + SETGID=1000 \ + SETUID=1000 \ + TZ="Europe/Berlin" + +# Expose default admin ui port +EXPOSE 8081 + +# Healthcheck +HEALTHCHECK --interval=15s --timeout=5s --retries=5 \ + CMD ["/bin/bash", "-c", "/opt/scripts/healthcheck.sh"] + +# Run startup-script +ENTRYPOINT ["/bin/bash", "-c", "/opt/scripts/iobroker_startup.sh"] diff --git a/slim/scripts/healthcheck.sh b/slim/scripts/healthcheck.sh new file mode 100644 index 0000000..072f9c0 --- /dev/null +++ b/slim/scripts/healthcheck.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Script checks health of running container + +if [ "$(cat /opt/scripts/.docker_config/.healthcheck)" == "starting" ] +then + echo 'Health status: OK - Startup script is still running.' + exit 0 +elif [ "$(cat /opt/scripts/.docker_config/.healthcheck)" == "maintenance" ] +then + echo 'Health status: OK - Container is running in maintenance mode.' + exit 0 +elif [ "$(ps -fe|grep "[i]obroker.js-controller"|awk '{print $2}')" != "" ] +then + echo 'Health status: OK - Main process (js-controller) is running.' + exit 0 +fi + +echo 'Health status: !!! NOT OK !!! - Something went wrong. Please see container logs for more details and/or try restarting the container.' +exit 1 diff --git a/slim/scripts/iobroker_startup.sh b/slim/scripts/iobroker_startup.sh new file mode 100644 index 0000000..2962c87 --- /dev/null +++ b/slim/scripts/iobroker_startup.sh @@ -0,0 +1,517 @@ +#!/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 "----- Docker-Image -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" image: ${VERSION})" && echo " -----" +echo -n "----- " && echo -n "$(printf "%-10s %-23s" build: ${BUILD})" && echo " -----" +echo "----- -----" +echo "----- Versions -----" +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 ' ' + +# Adding ckeck file for easy docker detection by ioBroker +echo "$VERSION" > /opt/scripts/.docker_config/.thisisdocker + +# Installing/ updating 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 [ -f /opt/.firstrun ] + then + echo "Updating Linux packages on first run..." + bash /opt/scripts/setup_packages.sh -update + echo "Done." + echo ' ' + echo "Registering maintenance script as command..." + echo "alias maintenance=\'/opt/scripts/maintenance.sh\'" >> /root/.bashrc + echo "alias maint=\'/opt/scripts/maintenance.sh\'" >> /root/.bashrc + echo "Done." + echo ' ' + fi + 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 -install + 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 +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/ioBroker.docker)." + 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/ioBroker.docker)." + 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/ioBroker.docker)." + 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/ioBroker.docker)." + 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/ioBroker.docker)." + 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/ioBroker.docker)." + 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/ioBroker.docker)." + 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 diff --git a/slim/scripts/maintenance.sh b/slim/scripts/maintenance.sh new file mode 100644 index 0000000..bacd49b --- /dev/null +++ b/slim/scripts/maintenance.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# function to display help text +display_help() { + echo "This script is build to manage your ioBroker container!" + echo "Usage: maintenance [ COMMAND ] [ OPTIONS ]" + echo " maint [ COMMAND ] [ OPTIONS ]" + echo '' + echo "COMMANDS" + echo "------------------" + echo " status > gives the current state of maintenance mode" + echo " on > switches mantenance mode ON" + echo " off > switches mantenance mode OFF and shuts down/ restarts container" + echo " upgrade > will put container to maintenance mode and upgrade iobroker" + echo '' + echo "OPTIONS" + echo "------------------" + echo " -h|--help > shows this help" + echo " -y|--yes > confirms the used command without asking" + echo '' + exit 0 +} + +while getopts h opt +do + case $opt in + h | --help) + display_help ;; + esac +exit 0; +done + +if [ "$1" == "status" ] +then + if [ $(cat /opt/scripts/.docker_config/.healthcheck) == 'maintenance' ] + then + echo 'Maintenance mode is ON.' + exit 0 + elif [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ] + then + echo 'Maintenance mode is OFF.' + exit 0 + fi +elif [ "$1" == "on" ] +then + echo 'You are now going to stop ioBroker and activating maintenance mode for this container.' + read -p 'Do you want to continue [yes/no]? ' A + if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ] + then + echo 'Activating maintenance mode...' + echo "maintenance" > /opt/scripts/.docker_config/.healthcheck + sleep 1 + echo 'Done.' + echo 'Stopping ioBroker...' + pkill -u iobroker + sleep 1 + echo 'Done.' + exit 0 + else + exit 0 + fi +elif [ "$1" == "off" ] +then + echo 'You are now going to deactivate maintenance mode for this container.' + echo 'Depending on the restart policy, your container will be stopped/ restarted immediately.' + read -p 'Do you want to continue [yes/no]? ' A + if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ] + then + echo 'Deactivating maintenance mode and forcing container to stop/ restart...' + echo "stopping" > /opt/scripts/.docker_config/.healthcheck + pkill -u root + exit 0 + else + exit 0 + fi +elif [ "$1" == "upgrade" ] +then + echo 'You are now going to upgrade your js-controller.' + echo 'As this will change data in /opt/iobroker, make sure you have a backup!' + echo 'During the upgrade process the container will automatically switch into maintenance mode and stop ioBroker.' + echo 'Depending of the restart policy, you container will be stoped/ restarted automatically after the upgrade.' + read -p 'Do you want to continue [yes/no]? ' A + if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ] + then + echo 'Activating maintenance mode...' + echo "maintenance" > /opt/scripts/.docker_config/.healthcheck + sleep 1 + echo 'Done.' + echo 'Stopping ioBroker...' + pkill -u iobroker + sleep 1 + echo 'Done.' + echo 'Upgrading js-controller...' + iobroker update + iobroker upgrade self + sleep 1 + echo 'Done.' + echo 'Container will be stopped/ restarted in 5 seconds...' + sleep 5 + echo "stopping" > /opt/scripts/.docker_config/.healthcheck + pkill -u root + exit 0 + else + exit 0 + fi +else + echo 'Invalid command. Please try again.' +fi + +exit 0 diff --git a/slim/scripts/setup_avahi.sh b/slim/scripts/setup_avahi.sh new file mode 100644 index 0000000..4fd1ab1 --- /dev/null +++ b/slim/scripts/setup_avahi.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +echo "Checking avahi-daemon installation state..." + +if [ -e /usr/sbin/avahi-daemon ] && [ -e /var/run/dbus ] +then + echo "Avahi is already installed..." +else + echo "Avahi-daemon is NOT installed. Going to install it now..." + apt-get update > /opt/scripts/avahi_startup.log 2>&1 + apt-get install -y libavahi-compat-libdnssd-dev avahi-daemon >> /opt/scripts/avahi_startup.log 2>&1 + rm -rf /var/lib/apt/lists/* >> /opt/scripts/avahi_startup.log 2>&1 + echo "Configuring avahi-daemon..." + sed -i '/^rlimit-nproc/s/^\(.*\)/#\1/g' /etc/avahi/avahi-daemon.conf + echo "Configuring dbus..." + mkdir /var/run/dbus/ +fi + +if [ -f /var/run/dbus/pid ]; +then + rm -f /var/run/dbus/pid +fi + +if [ -f /var/run/avahi-daemon//pid ]; +then + rm -f /var/run/avahi-daemon//pid +fi + +echo "Starting dbus..." +dbus-daemon --system + +echo "Starting avahi-daemon..." +/etc/init.d/avahi-daemon start + +exit 0 diff --git a/slim/scripts/setup_packages.sh b/slim/scripts/setup_packages.sh new file mode 100644 index 0000000..d959a5b --- /dev/null +++ b/slim/scripts/setup_packages.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ $1 == "-install" ] +then + apt-get -qq update + packages=$(cat /opt/scripts/.packages) + for i in $packages; do + sudo apt-get -qq -y install $i + done +elif [ $1 == "-update" ] +then + apt-get -qq update + apt-get -qq -y upgrade +else + echo "No paramerter found!" + exit 1 +fi + +rm -rf /var/lib/apt/lists/* +rm -f /opt/scripts/.packages + +exit 0 diff --git a/slim/scripts/setup_zwave.sh b/slim/scripts/setup_zwave.sh new file mode 100644 index 0000000..11d8024 --- /dev/null +++ b/slim/scripts/setup_zwave.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +echo "Checking openzwave installation state..." + +if [ -e /usr/local/lib64 ] +then + echo "Openzwave is already installed..." +else + echo "Openzwave is NOT installed. Going to install it now..." + cd /opt + curl -s -L -O http://old.openzwave.com/downloads/openzwave-1.6.1007.tar.gz + tar -xf openzwave-1.6.1007.tar.gz && rm openzwave-1.6.1007.tar.gz + cd openzwave-1.6.1007 && make > /dev/null 2>&1 && make install > /dev/null 2>&1 + ldconfig /usr/local/lib64 + cd /opt/iobroker + # echo "Openzwave is now installed..." +fi + +exit 0 diff --git a/slim/userscripts/userscript_everystart_example.sh b/slim/userscripts/userscript_everystart_example.sh new file mode 100644 index 0000000..9023677 --- /dev/null +++ b/slim/userscripts/userscript_everystart_example.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# This is an example script file. +# To run the Script on every start of the container you have to rename it to userscript_everystart.sh. + +# You can add your advanced script code here! + +echo ' ' +echo "I'm your startscript userscript_everystart.sh. I will run on EVERY container startup." +echo ' ' + + +exit 0 diff --git a/slim/userscripts/userscript_firststart_example.sh b/slim/userscripts/userscript_firststart_example.sh new file mode 100644 index 0000000..4fef50d --- /dev/null +++ b/slim/userscripts/userscript_firststart_example.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# This is an example script file. +# To run the Script on the first start of a new container you have to rename it to userscript_firststart.sh. + +# You can add your advanced script code here! + +echo ' ' +echo "I'm your startscript userscript_firststart.sh. I will run only on the FIRST startup of the container." +echo ' ' + +exit 0