I started with openHAB with the fabulous openHABian, but am now since ~1,5 years running openHAB on a Raspi 3 B+ in a Docker environment. I like this setup, because it can be set up easily (e.g. in case of hardware failure) and I can install and try out new software with limited effort.
Below is my step-by-step instruction which I wrote for myself with the help of a friend, to a) set up the system initially or b) restore my system from my daily Duplicati-Backups in case of a failure. Last time I tried it out, getting from a āblank SD cardā to a ārestored installation based on last nightās last Duplicati backupā took me around 45-60 minutes.
Disclaimer 1: Iām not a pro, but I got this running / it works. In case I missed something / something can be improved, let me know.
Disclaimer 2: As you can read in this thread, running all of the below on Docker requires more than 1 GB of RAM. It also runs with just 1 GB of RAM, but Raspbian then starts to swap, which reduces speed and lifetime of the SD card.
The following softwares are included in my instruction in addition to openHAB:
- Portainer (for easier Docker Maintenance)
- influxDB (as a data base for openHAB, instead of the default RRD4j)
- Duplicati (for daily backups of the entire system, in my case to Google Drive)
- Frontail (for log analysis of openHAB)
- Mosquitto (for MQTT-devices, e.g. all sorts of Tasmota devices)
- Samba (for easier access to the relevant files of the containers)
- wmbusmeters (to receive data sent by my water and heating meters via wireless M-Bus)
Step 1: Install Raspberry Pi OS
- Install the Raspberry Pi Imager on your PC (Linux or Windows) and launch it
- Chose āRaspberry Pi OS Lite (32-bit)ā as the OS
- Under āAdvanced Optionsā activate SSHā¦
- ā¦ set a username (in my case:
pi
) and passwordā¦ - and configure the wireless LAN (SSID & Password)
- Click āWriteā to write the OS to the SD card
- When youāre done, plug your SD card in to the raspi and boot the raspi (no monitor, mouse or keyboard need to be connected)
- Afterwards, you should be able to reach the Raspi via a SSH software (in Linux:
Terminal
) by enteringssh pi@192.168.0.xxx
followed by your password. If you donāt know the IP address which got assigned to the Raspi, check your router.
Step 2: Prepare Raspbian OS and install Docker
- Increase the Raspian OS swapfile. Without this, things were somewhat unstable for me under load. You can check this yourself when, after youāre done with everything, you run
htop
and will see that Raspbian starts to swap.
Entersudo nano /etc/dphys-swapfile
and increasing the swap file to 1240 (CONF_SWAPSIZE=1240
). Exit with Ctrl + X. - Update the system by entering
sudo apt-get update && sudo apt-get upgrade
. - Define the desired IP-address by entering
sudo nano /etc/dhcpcd.conf
. In the file include / uncomment
interface wlan0
static ip_address=192.168.0.xxx/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
If you want to use the ethernet interface instead of wifi, write eth0 instead of wlan0
. Exit with Ctrl + X.
- Perform a reboot via
sudo reboot
- Install Docker by entering
curl -sSL https://get.docker.com | sh
- Add the pi-user to the Docker Group by entering
sudo usermod -aG docker pi
- Perform a reboot via
sudo reboot
- Install Portainer by entering
sudo docker pull portainer/portainer-ce:linux-arm
- Run and configure Portainer by entering
sudo docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:linux-arm
- Access Portainer by opening a Browser and entering
http://192.168.0.xxx:9000
. Define your Portainer Password. - In case you wonder: Portainer is a GUI for Docker, which makes it easier to work with Docker containers.
Step 3: Deploy the docker containers
- Access Portainer by opening a Browser and entering
http://192.168.0.xxx:9000
. - Go to āhomeā ā ālocalā ā āStacksā.
- Use the āAdd Stackā-button to add the following Stack and deploy the respective containers defined in that stack.
- You can either paste the stack-definition code (below) into the Web Editor or (what I would recommend) save the code into local files and use the āUploadā function. Give the stack a meaningful name (I chose
openhab
as a stack name).
version: '3.8'
services:
openhab:
image: openhab/openhab:latest
container_name: openhab
depends_on:
- influxdb
- mosquitto
restart: always
privileged: true
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "/etc/timezone:/etc/timezone:ro"
- data_openhab_conf:/openhab/conf
- data_openhab_addons:/openhab/addons
- data_openhab_userdata:/openhab/userdata
environment:
TZ: ${TZ}
OPENHAB_HTTP_PORT: ${OPENHAB_HTTP_PORT}
OPENHAB_HTTPS_PORT: ${OPENHAB_HTTPS_PORT}
CRYPTO_POLICY: "unlimited"
EXTRA_JAVA_OPTS: "-Duser.timezone=${TZ}"
USER_ID: 999
GROUP_ID: 994
# Run openHAB with German number format
# Can be tested by entering "locale" after "docker exec -t -i openhab /bin/bash"
LANG: de_DE.UTF-8
LANGUAGE: de_DE.UTF-8
LC_ALL: de_DE.UTF-8
devices:
# Aeotec Z-Wave Stick
- /dev/ttyACM0:/dev/ttyACM0
# SONOFF Zigbee 3.0 USB_Dongle Plus V2
- /dev/ttyACM1:/dev/ttyACM1
network_mode: host
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
restart: always
volumes:
- data_mosquitto_config:/mosquitto/config
- data_mosquitto_data:/mosquitto/data
- data_mosquitto_log:/mosquitto/log
ports:
- ${MOSQUITTO_MQTT_PORT}:1883
- ${MOSQUITTO_MQTTS_PORT}:8883
environment:
TZ: ${TZ}
networks:
app-nw:
aliases:
- mqtt
influxdb:
image: influxdb:1.8
container_name: influxdb
restart: always
volumes:
- data_influxdb:/var/lib/influxdb
- data_influxdb_config:/etc/influxdb
ports:
- ${INFLUXDB_DB_PORT}:8086
environment:
- INFLUXDB_DATA_ENGINE=tsm1
- INFLUXDB_REPORTING_DISABLED=false
- INFLUXDB_ADMIN_USER=${INFLUXDB_ADMIN_USER}
- INFLUXDB_ADMIN_PASSWORD=${INFLUXDB_ADMIN_PASSWORD}
- INFLUXDB_USER=${INFLUXDB_USER}
- INFLUXDB_USER_PASSWORD=${INFLUXDB_USER_PASSWORD}
- INFLUXDB_READ_USER=${INFLUXDB_READ_USER}
- INFLUXDB_READ_USER_PASSWORD=${INFLUXDB_READ_USER_PASSWORD}
- INFLUXDB_DB=${INFLUXDB_OPENHAB_DB}
- TZ=${TZ}
networks:
app-nw:
backend-nw:
aliases:
- db
wmbusmeters:
image: weetmuts/wmbusmeters
container_name: wmbusmeters
privileged: true
# Needs to be changed depending on platform (see https://github.com/weetmuts/wmbusmeters/tree/master/docker)
# platform: linux/arm64
# platform: linux/amd64
platform: linux/arm64
restart: always
volumes:
- data_wmbusmeters_data:/wmbusmeters_data
- /etc/localtime:/etc/localtime:ro
- /dev/:/dev/
networks:
- app-nw
- backend-nw
duplicati:
image: duplicati/duplicati
container_name: duplicati
environment:
- PUID=0
- PGID=0
- TZ=Europe/Berlin
- CLI_ARGS= #optional
volumes:
- /var/lib/docker/volumes/duplicati_config/_data:/config
- /var/lib/docker/volumes/duplicati_backups/_data:/backups
- /var/lib/docker/volumes/duplicati_source/_data:/source
- /var/lib/docker/volumes/openhab_data_openhab_conf:/source/openhab_conf
- /var/lib/docker/volumes/openhab_data_openhab_addons:/source/openhab_addons
- /var/lib/docker/volumes/openhab_data_openhab_userdata:/source/openhab_userdata
- /var/lib/docker/volumes/openhab_data_mosquitto_config:/source/mosquitto_config
- /var/lib/docker/volumes/openhab_data_mosquitto_data:/source/mosquitto_data
- /var/lib/docker/volumes/openhab_data_mosquitto_log:/source/mosquitto_log
- /var/lib/docker/volumes/openhab_data_influxdb:/source/influxdb
- /var/lib/docker/volumes/openhab_data_influxdb_config:/source/influxdb_config
- /var/lib/docker/volumes/openhab_data_wmbusmeters_data:/source/wmbusmeters_data
ports:
- 8200:8200
restart: unless-stopped
frontail:
image: welteki/frontail-openhab:latest
container_name: frontail
restart: always
ports:
- "9001:9001"
volumes:
- /var/lib/docker/volumes/openhab_data_openhab_userdata/_data:/openhab/userdata:ro \
samba:
image: dperson/samba
container_name: samba
restart: always
ports:
- "137:137/udp"
- "138:138/udp"
- "139:139/tcp"
- "445:445/tcp"
read_only: false
stdin_open: true
healthcheck:
disable: true
environment:
- TZ='Europe/Berlin'
- PUID=9001
- PGID=9001
- WORKGROUP=workgroup
- PERMISSIONS=true
- RECYCLE=false
- SHARE1=openhab_conf;/shares/openhab_conf;yes;no;yes;all;all;all;
- SHARE2=openhab_addons;/shares/openhab_addons;yes;no;yes;all;all;all;
- SHARE3=openhab_userdata;/shares/openhab_userdata;yes;no;yes;all;all;all;
- SHARE4=mosquitto_config;/shares/mosquitto_config;yes;no;yes;all;all;all;
- SHARE5=mosquitto_log;/shares/mosquitto_log;yes;no;yes;all;all;all;
- SHARE6=wmbusmeters_data;/shares/wmbusmeters_data;yes;no;yes;all;all;all;
- SHARE7=influxdb;/shares/influxdb;yes;no;yes;all;all;all;
- SHARE8=docker;/shares/docker;yes;no;yes;all;all;all;
- SHARE9=log;/shares/log;yes;no;yes;all;all;all;
volumes:
- data_openhab_conf:/shares/openhab_conf
- data_openhab_addons:/shares/openhab_addons
- data_openhab_userdata:/shares/openhab_userdata
- data_mosquitto_config:/shares/mosquitto_config
- data_mosquitto_log:/shares/mosquitto_log
- data_wmbusmeters_data:/shares/wmbusmeters_data
- data_influxdb:/shares/influxdb
- /docker:/shares/docker
- /var/log:/shares/log
chronograf:
image: chronograf:latest
container_name: chronograf
restart: unless-stopped
ports:
- '8888:8888'
volumes:
- /var/lib/docker/volumes/openhab_data_influxdb/_data:/influxdb
environment:
- INFLUXDB_URL=http://db:8086
- INFLUXDB_USERNAME=$INFLUXDB_USER
- INFLUXDB_PASSWORD=$INFLUXDB_USER_PASSWORD
networks:
app-nw:
backend-nw:
volumes:
data_openhab_conf:
data_openhab_addons:
data_openhab_userdata:
data_mosquitto_config:
data_mosquitto_data:
data_mosquitto_log:
data_influxdb:
data_influxdb_config:
data_wmbusmeters_data:
networks:
app-nw:
internal: false
driver: bridge
driver_opts:
com.docker.network.bridge.name: app-${PROJECT_NAME}
backend-nw:
internal: true
driver: bridge
driver_opts:
com.docker.network.bridge.name: be-${PROJECT_NAME}
Include the following enviroment variables (define your own passwords first) by saving the following code into a local .env-file on your computre and select this file by clicking on āLoad variables from .env fileā. Make sure that you define the respective passwords for you (<password>
).
# Config File for openHAB Application
# Docker Compose Project Name
# max length 11 characters
PROJECT_NAME=openhab3
# InfluxDB Configuration
INFLUXDB_ADMIN_USER=admin
INFLUXDB_ADMIN_PASSWORD=<password>
INFLUXDB_USER=openhab
INFLUXDB_USER_PASSWORD=<password>
INFLUXDB_READ_USER=openhab_ro
INFLUXDB_READ_USER_PASSWORD=<password>
INFLUXDB_OPENHAB_DB=openhab_db
# Port Configuration openHab
OPENHAB_HTTP_PORT=8080
OPENHAB_HTTPS_PORT=8443
# Port Configuration InfluxDB
INFLUXDB_DB_PORT=8086
# Port Configuration Grafana
GRAFANA_HTTP_PORT=3000
# Port Configuration Chronograf
CHRONOGRAF_HTTP_PORT=8888
# Port Configuration Mosquitto
MOSQUITTO_MQTT_PORT=1883
MOSQUITTO_MQTTS_PORT=8883
# Timezone
TZ=Europe/Berlin
Deploy the respective containers by clicking āDeploy the stackā. This will take some time (10 - 15 minutes) an should end with the message āStack deployedā.
Step 4: 1st launch of openHAB
- Perform a reboot via
sudo reboot
- Launch openHAB for the first time by accessing it in a browser via
192.168.0.xxx:8080
- If everything worked correctly, you should be able to access and configure openHAB.
Important first step before doing anything else: Configure influxDB
- Install the influxDB-Binding (Settings ā Bindings ā influxDB Persistence)
- Activate influxDB (Settings ā Persistence ā inxluxDB Persistence Layer)
- Configure influxDB (Settings ā influxDB Persistence Layer): Database URL: http://localhost:8086; Database version: influxDB 1; username and password: as defined above).
If influxDB version 2 is to be chosen, also influxDB 2 has to be deployed (see docker-compose.yml file: image: influxdb:1.8
)
Step 5: Configure Duplicati
This step is not needed but highly recommended to run daily backups. Without this step, if your SD card breaks, everything is gone. Duplicati allows you to backup everything (e.g. every night) to e.g. Google Drive).
- Launch Duplicati by accessing it in a browser via
192.168.0.xxx:8200
. - Create a new backup (in my case scheduled daily) which saves all essential folders of your installation (combined in the
/source/
folder, see pre-configuration above) to a destination of your choice (in my case Google Drive). So in a worst case scenario, you can fall back to last nightās state of your entire installation (in case of daily backups). - If you want to backup your data to a thumb drive (which I would definitely not recommend because a) if itās always plugged in, it can break alongside the Raspi in case of an electrical failure or b) if it is not always plugged in, then thereās no point in having Duplicati run for regular updates) make the thumb drive accessible to the Duplicati container similarly than the Wireless M-BUS USB Stick is made available to the openHAB container, by including the following section into the Duplicati stack, with the respective address of the thumb drive (perform
ls
in/dev/
and search for your thumb drive). The part on the left is the physical address as seen to the Raspbian, the part on the right is the one that will be visible to Duplicati in its container.
devices:
- /dev/ttyACM0:/dev/ttyACM0
- Export your configuration (Configuration ā Export) and save it locally, so that you still have your Duplicati configuration in case your SD card fails.
Step 6 (optional): Configure Mosquitto
This step is only needed if you want to hook up devices to openHAB via MQTT (e.g. Tasmota devices or wmbusmeters). The configuration is text-only, but if youāve followed the docker-compose.yml you should see a share mosquitto_config if you open the samba share via smb://192.168.0.xxx.
1) Prepare mosquitto.conf
- Open the mosquitto.conf file by accessing the samba share
smb://192.168.0.150/mosquitto_config/
(either via Terminal or via your normal PC). - Uncomment (or include if not already in there by default) the following lines
# =================================================================
# Listeners
# =================================================================
listener 1883
listener 8883
# =================================================================
# Persistence
# =================================================================
persistence true
persistence_location /mosquitto/data
# =================================================================
# Logging
# =================================================================
log_dest stderr
# =================================================================
# Security
# =================================================================
allow_anonymous false
# -----------------------------------------------------------------
# Default authentication and topic access control
# -----------------------------------------------------------------
password_file /mosquitto/config/mosquitto.passwd
Save the file.
2) Define username and password
- Create a file
mosquitto.passwd
in the same drivesmb://192.168.0.148/mosquitto_config/
- Your file should contain your username and your password in the following format:
- Log into your mosquitto-container via Terminal ā
docker exec -it mosquitto /bin/sh
- Convert the plain-txt-password into a hashed version
via mosquitto_passwd -U mosquitto.passwd
With the example above, the file now looks like this:
Afterwards the openHAB MQTT-binding can be installed (Settings ā Bindings ā MQTT Binding). Afterwards, in openHAB an MQTT Broker-Thing can be created. The following settings are proven to work (most of them should be default, though).
UID: mqtt:broker:7519737e0f
label: MQTT Broker
thingTypeUID: mqtt:broker
configuration:
lwtQos: 0
publickeypin: true
clientID: openhab
keepAlive: 60
hostnameValidated: true
secure: false
birthRetain: true
certificatepin: true
shutdownRetain: false
password: <yourpassword>
protocol: TCP
qos: 0
reconnectTime: 60000
port: 1883
mqttVersion: V3
host: localhost
lwtRetain: true
enableDiscovery: true
username: openhab
Done.
Step 7 (only relevant for restoring from a Duplicati backup, e.g. in case of hardware failure)
- Perform Steps 1 - 3 on a fresh SD card.
- Stop all containers except Duplicati
- Launch Duplicati by accessing it in a browser via
192.168.0.xxx:8200
. - Click āAdd backupā
- Select āImport from fileā. Select the Duplicati configuration file (.json) which you have stored locally. Uncheck the box āImport Metadataā and check the box āSave immediatelyā. Confirm with āImportā.
- Select āRepairā in the overlay (your Config file which you saved some time back does not match the backup anymore ā this is normal). Recreating the database might take some minutes.
- Click āRestoreā ā then the last option (the name of your backup). Select the time and the folders of the backup which you want to restore. Check the boxes āOriginal Locationā, āOverwriteā and āRestore read/write permissionsā and press āRestoreā. This might take some minutes.
- Afterwards (you should see no error messages), restart your containers in Portainer.
- If everything worked correctly, you should be able to access openHAB again from the state saved in your backup.
Step 8 (only relevant if you want to use Raspberrymatic for Homematic IP-devices)
- In terminal, enter
sudo su
- Enter
wget -qO - https://raspberrymatic.de/install-docker.sh | bash -
to install Raspberrymatic - You are being prompted some configuration entries during the installation. Enter
eth0
(if your Raspi runs via Ethernet / should be reached on eth0)
192.168.0.0/24
192.168.0.1
(if this is your Router-IP)
192.168.0.171
(the primary IP address under which the CCU will be reached, can be chosen freely)
192.168.0.172
(the secondary IP address) - Access portainer (192.168.0.150:9000) and run the ccu-container
- Your Raspberrymatic can now be reached unter 192.168.0.171
Maintenance
Update openHAB within Docker
Since the image is specified via image: openhab/openhab:latest
, clicking on āUpdate the Stackā in the stack-definition and confirming āRe-pull image and redeployā in the popup should do the trick and pull the latest version of openHAB. Make sure you do a backup before.
Alternatively, if to be done via Terminal
- Terminal ā
ssh pi@192.168.0.xxx
docker stop openhab
to stock openHABdocker rm openhab
to remove the current openHAB containerdocker pull openhab/openhab:latest
to pull the latest update of openHAB- In Docker re-deploy the openHAB stack
Update Portainer
To update Portainer (in contrast to Docker itself, Portainer is not updated automaticially via the regular sudo apt-get update && sudo apt-get upgrade
) do the following:
- Terminal ā
ssh pi@192.168.0.xxx
docker stop portainer
to stop the Portainer containerdocker rm portainer
to remove the Portainer imagedocker pull portainer/portainer-ce
to pull the latest Portainer imagedocker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
to run the new version
Additional notes:
- I highly recommend to try the entire cycle (incl. the restore) once in a while on a second SD card, to see whether a) it runs through without problems and b) whether the backup & restore works correctly.
- As mentioned, in my case, this takes ~45 - 60 minutes (not too bad)
- As a test, I used this protocol to install everything on an x86/debian system. So far everything seems to work smoothly
Potential problems after upgrading from 3.x to 4.x
- If you encounter the following problem
2023-09-12 22:55:33.583 [WARN ] [org.apache.felix.fileinstall ] - /usr/share/openhab/addons does not exist, please create it.
2023-09-12 22:55:33.590 [ERROR] [org.apache.felix.fileinstall ] - Cannot create folder /var/lib/openhab/tmp/bundles. Is the folder write-protected?
2023-09-12 22:55:33.591 [ERROR] [org.apache.felix.configadmin ] - [org.osgi.service.cm.ManagedServiceFactory, id=50, bundle=18/mvn:org.apache.felix/org.apache.felix.fileinstall/3.7.4]: Unexpected problem updating configuration org.apache.felix.fileinstall.4a5be290-c3c5-4491-a66c-0c0d3dbd032a
java.lang.RuntimeException: Cannot create folder: /var/lib/openhab/tmp/bundles
at org.apache.felix.fileinstall.internal.DirectoryWatcher.prepareDir(DirectoryWatcher.java:647) ~[?:?]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.prepareTempDir(DirectoryWatcher.java:627) ~[?:?]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.<init>(DirectoryWatcher.java:179) ~[?:?]
at org.apache.felix.fileinstall.internal.FileInstall.updated(FileInstall.java:250) ~[?:?]
at org.apache.felix.fileinstall.internal.FileInstall$ConfigAdminSupport$Tracker.updated(FileInstall.java:380) ~[?:?]
at org.apache.felix.cm.impl.helper.ManagedServiceFactoryTracker.updated(ManagedServiceFactoryTracker.java:159) ~[?:?]
at org.apache.felix.cm.impl.helper.ManagedServiceFactoryTracker.provideConfiguration(ManagedServiceFactoryTracker.java:93) ~[?:?]
at org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceFactoryUpdate.provide(ConfigurationManager.java:1266) ~[?:?]
at org.apache.felix.cm.impl.ConfigurationManager$ManagedServiceFactoryUpdate.run(ConfigurationManager.java:1210) ~[?:?]
at org.apache.felix.cm.impl.UpdateThread.run0(UpdateThread.java:122) ~[?:?]
at org.apache.felix.cm.impl.UpdateThread.run(UpdateThread.java:84) ~[?:?]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
refer to this post [openHAB Docker] "/usr/share/openhab/addons does not exist" after upgrade to OH 3.3.0 - #7 by wborn for a fix.