OpenBSD Home-Automation-Gateway mit Zigbee2MQTT und openHAB
Ein lautloses, isoliertes IoT-Gateway mit Zigbee2MQTT, Mosquitto und openHAB auf lüfterloser x86-Hardware

Wer meine bisherigen Beiträge zum Thema Home Automation verfolgt hat, weiß, dass ich mich seit einiger Zeit mit Zigbee beschäftige. Alles begann mit dem Mitschneiden von Frames im Artikel Zigbee-Sniffing unter OpenBSD: Deep Dive mit dem TI CC2531. Aus Neugier habe ich mir dann einen neueren Zigbee-Koordinator besorgt und im Folgeartikel Zigbee Home Automation auf OpenBSD: Sonoff Dongle-M und openHAB über die Anbindung an eine Automatisierungsplattform berichtet.
Vor Kurzem habe ich einen Posten gebrauchte Thin Clients ergattert, die sich als perfekte Hardware für einen dedizierten Smart-Home-Controller herausgestellt haben. Hier beschreibe ich, wie ich ein stabiles, isoliertes Gateway auf Basis von OpenBSD 7.9-snapshot, Zigbee2MQTT, Mosquitto und openHAB aufgebaut habe.
Der Hardware-Stack
Das Fundament des Setups ist ein Fujitsu Futro S9010n. Diese kleinen Kisten sind hervorragende Heimserver. Für weniger Geld als für ein aktuelles Raspberry-Pi-Kit bekommt man einen vollwertigen, geschlossenen x86-Rechner mit folgender Ausstattung:
- 20 GB RAM (Ausgeliefert mit 8 GB, aber ich konnte ihn auf 20 GB aufrüsten. Mit 32 GB wurde er allerdings unerträglich langsam)
- 64 GB SSD
- Lüfterlose Kühlung (völlig lautlos, ideal für den Wohnbereich oder den Netzwerkschrank)
- Zwei native serielle Anschlüsse
inteldrm aktiviert ist. Da das System bei mir ohnehin komplett headless als Server läuft, stört mich das nicht weiter – man sollte es nur bei der Erstinstallation bedenken.Aus Sicherheitsgründen habe ich den Server in ein eigenes IoT-VLAN gesperrt. Die Netzwerkkommunikation mit dem physischen Zigbee-Mesh läuft über das Netzwerk zu einem SONOFF Zigbee 3.0 USB Dongle Plus (Dongle-M). Dadurch sind die ungesicherten Endgeräte komplett von meinem produktiven Heimnetzwerk isoliert.
Als die Basis stand, habe ich eine Reihe von Smart-Home-Geräten eingebunden:
- Strom: Ein 4er-Pack SONOFF Zigbee Smart Steckdosen (praktisch, um das Mesh-Netzwerk als Router zu erweitern).
- Klima: Ein SONOFF Smart Zigbee 3.0 Thermostat sowie mehrere SONOFF SNZB-02P Temperatur- und Feuchtigkeitssensoren.
- Präsenz & Beleuchtung: Der auf Mikrowellen-Radar basierende SONOFF SNZB-06P Präsenzsensor, der Standard-GU10 Smart Zigbee LED Glühbirnen ansteuert, und eine passende Zigbee Deckenlampe.
Software-Konfiguration
Die Software-Architektur ist klassisch geschichtet: Nginx nimmt den externen Traffic an, übernimmt die Authentifizierung und leitet die Anfragen per Reverse-Proxy an openHAB oder Zigbee2MQTT weiter. Die Dienste kommunizieren untereinander über den Mosquitto MQTT-Broker. Die Verwaltung der Konfiguration erfolgt via OpenVOX, während ein einfaches tägliches Shell-Script die Backups übernimmt.
1. Zigbee2MQTT
Die zentrale Zigbee-Übersetzung läuft auf Port 8080. Die Verbindung zum Adapter wird über TCP aufgebaut, da sich der Sonoff Dongle-M im isolierten IoT-Netzwerksegment befindet.
version: 5
homeassistant:
enabled: true
experimental_event_entities: true
legacy_action_sensor: true
frontend:
enabled: true
host: 127.0.0.1
base_url: /zigbee2mqtt
port: 8080
mqtt:
base_topic: zigbee2mqtt
server: mqtt://localhost
version: 5
serial:
port: tcp://sonoff.example.com:6638
baudrate: 115200
adapter: ember
rtscts: false
advanced:
log_level: info
log_directory: /var/log/zigbee2mqtt
log_file: zigbee2mqtt_%TIMESTAMP%.log
log_rotation: true
log_output:
- file
network_key:
# ... secret key ...2. Mosquitto & openHAB 5.1.3
Mosquitto macht unter OpenBSD keine Arbeit: Einfach das Paket installieren, per rcctl aktivieren und starten.
Die Installation von openHAB verläuft ähnlich unspektakulär. Um Konflikte mit dem Frontend von Zigbee2MQTT zu vermeiden, muss der Standardport in der /etc/openhab.conf auf 8081 umgebogen werden:
OPENHAB_HTTP_PORT=80813. Nginx Reverse Proxy
Über Nginx läuft openHAB direkt auf dem Root-Pfad /, während das Web-Interface von Zigbee2MQTT unter /zigbee2mqtt über eine HTTP-Basic-Auth-Absicherung geschützt wird.
# MANAGED BY OpenHAB
server {
listen *:443 ssl;
listen [::]:443 ssl ipv6only=on;
server_name ha ha.example.com;
http2 off;
ssl_certificate /etc/puppetlabs/puppet/ssl/certs/ha.example.com.pem;
ssl_certificate_key /etc/puppetlabs/puppet/ssl/private_keys/ha.example.com.pem;
index index.html index.htm index.php;
access_log /var/www/logs/ssl-ha.example.com.access.log;
error_log /var/www/logs/ssl-ha.example.com.error.log;
location /zigbee2mqtt {
auth_basic "Home Automation Area";
auth_basic_user_file /conf/.htpasswd;
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 90s;
proxy_send_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
client_body_buffer_size 128k;
client_max_body_size 8m;
proxy_buffers 4 32k;
proxy_redirect http:// https://;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade;
}
location / {
proxy_pass http://127.0.0.1:8081;
proxy_read_timeout 90s;
proxy_send_timeout 90s;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
client_body_buffer_size 128k;
client_max_body_size 8m;
proxy_buffers 4 32k;
proxy_redirect http:// https://;
proxy_set_header Connection "upgrade";
proxy_set_header Content-Type $http_content_type;
proxy_set_header Upgrade $http_upgrade;
}
}Geräte-Pairing & die OpenBSD-Sackgasse
Nach dem Reload von Nginx funktionierte das Anlernen der Endgeräte im Zigbee2MQTT-Dashboard problemlos: Pairing-Modus in der UI aktivieren, Knopf am Sensor drücken und das Gerät wird interviewt. Die Engine liefert eine gute Übersicht des physischen Mesh-Netzwerks:

Das visualisierte Zigbee-Mesh-Netzwerk
Zusätzlich sieht man direkt die aktuellen Sensorwerte im Dashboard:

Das Zigbee2MQTT Geräte-Dashboard
Das automatische Übernehmen dieser erkannten Geräte in openHAB lief dann jedoch gegen die Wand :/
Die Home Assistant Binding Exception
Normalerweise nutzt man in openHAB das Home Assistant Binding, um die von Zigbee2MQTT via MQTT gesendeten Discovery-Topics automatisch einzulesen. Das würde die entsprechenden Things und Channels ohne manuellen Aufwand anlegen. Unter openHAB 5.1 stürzt dieses Binding auf OpenBSD jedoch ab, da es auf native Komponenten via GraalVM setzt, die mit weniger verbreiteten Betriebssystemen Probleme haben.
Ich habe das Problem schließlich im openHAB-Community-Forum geschildert. Der Austausch dort war hervorragend: Ich bekam extrem schnell hilfreiche Antworten und wurde auf das dazugehörige Issue auf GitHub (#19276) hingewiesen.
Der Workaround: Eine eigene Discovery-Bridge
Da ich keine Lust hatte, Dutzende von Channels händisch in der openHAB-UI anzulegen, habe ich ein kleines Python-Hilfsscript geschrieben, das als Daemon läuft. Es lauscht auf die Konfigurationstopics des Mosquitto-Brokers und schreibt daraus automatisch passende .things-Dateien nach /etc/openhab/things/.
Das Script ist aktuell noch stark auf meine spezifischen Geräte zugeschnitten, reicht für den Übergang aber völlig aus und spart viel Klickarbeit. Der Code liegt auf GitHub: github.com/buzzdeee/mqtt_discovery_bridge.
openHAB einrichten: Add-ons und automatische Things
Damit openHAB die über das Script generierten Datenstrukturen auch versteht, müssen zuerst die passenden Erweiterungen installiert werden.
Im openHAB Add-on Store habe ich dafür das grundlegende MQTT Binding sowie die für die Payload-Verarbeitung notwendigen Transformationen Jinja, JSONPath und Regex installiert.

Die benötigten MQTT- und Transformations-Add-ons in openHAB
Nachdem die Add-ons aktiv waren und das Python-Script die Dateien im Konfigurationsverzeichnis abgelegt hatte, wurden die Geräte sofort erkannt. Ein Blick unter Settings -> Things zeigt das Ergebnis: Alle Zigbee-Geräte sind ohne manuelles Anlegen online.

Die automatisch über die Konfigurationsdateien erzeugten Things
Am Beispiel des SONOFF Präsenzsensors (Mikrowellen-Radar) sieht man die Struktur der übertragenen Daten. Die UI listet alle verfügbaren Channels wie Präsenzerkennung, Helligkeitswerte und Bewegungsstatus sauber auf. Diese können nun direkt mit Items verknüpft werden.

Die erzeugten Channels des Präsenzsensors
Items verknüpfen, Pages bauen und die Mobile-App
Um die Kanäle nutzbar zu machen, legt man in openHAB Items an und verknüpft sie mit den entsprechenden Channels der Things.
Ich habe testweise zwei Items erstellt und sie mit dem Effekt sowie der Lichtsteuerung verbunden.

Verknüpfung der Hardware-Channels mit openHAB Items
Nachdem die Items funktionierten, habe ich sie über den integrierten Layout-Manager auf einer neuen Landingpage platziert, um die Bedienung zu testen.

Das erste einfache Test-Dashboard mit zwei Steuerungselementen
Der Vorteil dieses Setups ist die direkte Integration in das openHAB-Ökosystem. Sobald man die offizielle openHAB Mobile-App im lokalen Netzwerk öffnet, wird die neu gebaute Seite ohne zusätzlichen Konfigurationsaufwand synchronisiert.
Die Steuerung funktioniert direkt vom Smartphone aus und erlaubt es mir, die Lampen im Raum verzögerungsfrei zu schalten.

Die Dashboard-Ansicht in der mobilen openHAB-App
Swiss-Army Debugging-Snippets
Beim Entwickeln der Discovery-Bridge und der Analyse der JSON-Payloads waren neben den normalen Logfiles vor allem diese CLI-Befehle sehr nützlich:
MQTT-Traffic analysieren
# Gezielte Einstellungsänderungen überwachen
mosquitto_sub -h 127.0.0.1 -v -t "zigbee2mqtt/Spot am 3D Drucker/set"
# Alle Statusmeldungen eines bestimmten Geräts mitlesen
mosquitto_sub -h 127.0.0.1 -v -t "zigbee2mqtt/Spot am 3D Drucker/+"Test-Payloads manuell senden
mosquitto_pub -h 127.0.0.1 -t "zigbee2mqtt/Spot am 3D Drucker/set" -m '{"effect": "blink"}'Bereinigung über die openHAB Karaf-Konsole
# Mit der lokalen openHAB-Konsole verbinden
ssh openhab@localhost -p 8101
# Aktive Things auflisten
openhab:things list
# Ein fehlerhaftes Thing manuell löschen
openhab:things remove sony:scalar:fcf1523cd795
# Fehlerhafte oder alte Binding-Bundles aufspüren und deinstallieren
openhab> bundle:list | grep -i sony
# 369 | Active | 80 | 4.3.0.202412181559 | openHAB Add-ons :: Bundles :: Sony Binding
openhab> bundle:uninstall 369
# Die automatische Inbox aufräumen
openhab:inbox list
openhab:inbox clearWie geht es weiter?
Das System läuft auf der lüfterlosen Hardware absolut stabil. Die Zeit bis zum Release von openHAB 5.3 (und dem damit erwarteten GraalVM-Fix) kann ich mit meinem Discovery-Script problemlos überbrücken.
Da die Datenübertragung nun zuverlässig funktioniert, stehen als Nächstes die Grundlagen der Strukturierung an. Da ich mich noch in die Basis-Bausteine einarbeite, gibt es noch einiges zu tun:
- Erstellen und Verknüpfen von Items mit Channels: Vertiefung bei komplexeren Item-Typen (Dimmer, Farbe, Zahlenwerte) und der korrekten Anwendung von Transformationen, um Rohdaten sauber darzustellen.
- Gruppieren von Items: Nutzung von Gruppen-Items, um entweder ganze Räume gleichzeitig zu schalten oder Durchschnittswerte (z. B. Temperaturen) zu berechnen.
- Aufbau eines sinnvollen Dashboards: Abseits von reinen Testseiten ein übersichtliches, alltagstaugliches Interface für Smartphone und Desktop entwerfen.
- Das semantische Heim-Modell: Abbildung des Hauses über das Semantic Model von openHAB (Locations, Equipment, Points), damit das System versteht, wo welcher Sensor physisch platziert ist.
- Erste Automatisierungs-Regeln schreiben: Einfache eventbasierte Scripte aufsetzen – beispielsweise, um das Licht am 3D-Drucker automatisch einzuschalten, wenn der Präsenzsensor Bewegung meldet.
- Persistence & Daten-Logging: Einrichtung von rrd4j oder InfluxDB, um Temperatur- und Feuchtigkeitsverläufe langfristig aufzuzeichnen, ohne den Flash-Speicher des Thin Clients unnötig zu belasten.