Home Assistant aus der Dose

Diesen Beitrag schrieb ich 2 Jahre und 5 Monate zuvor; die nachfolgenden Ausführungen müssen heute nicht unbedingt noch genau so funktionieren. Behalte das beim Lesen (und vor allem: beim Nachmachen!) bitte stets im Hinterkopf.

Geschätzte Lesezeit: 4 Minuten

Ich experimentiere fröhlich vor mich hin – diesmal mit Home Assistant, Docker und GitLab.

Wie kam es dazu?

Dabei bin ich weit davon entfernt, das als der Weisheit letzten Schluss zu propagieren – vermutlich gibt es etwa 2000 Dinge, die ich verbessern könnte, aber hey: es geht täglich ein Stückchen vorwärts. Doch erstmal zur Problemstellung: warum eigentlich das Ganze? Nachdem mein openHAB 2-Host gestorben war, zog ich mir Home Assistant auf einem Raspberry auf; als der Rpi4 geliefert wurde, zog ich das Setup auf diesen um, und er lief nur wenige Monate, als seine externe SSD wiederum den Geist aufgab. Woran mag das liegen? Qualitativ sind weder meine SD-Karten noch die SSDs die letzten Heuler, aber einen zuverlässigen, stabilen Betrieb konnte ich letztlich nie sicherstellen. Das Ummumpfen von A nach B erwies sich immer irgendwie als zu zeitraubend – ja, Backups vorhanden, ja, Dokumentation vorhanden… und trotzdem. Geht das nicht besser, schneller, $anders? Der aktuelle Smart Home-Host ist ein ausgedienter Mac Mini mit 8GB RAM, für den es keine macOS-Updates mehr gibt; Debian drauf, Docker drauf und los.

Erstellung .gitignore

Bisher war ich mit Docker schlicht nicht konfrontiert; es galt also erst einmal, sich umfassend einzulesen. Kommt es mir nur so vor, oder ist das wirklich alles ganz schön komplex? Docker, docker-compose, GitLab, CI/CD, Pipelining – eine Weile lang sah ich den Wald vor lauter Bäumen nicht mehr. Aber so nach und nach lichtete sich der Nebel, zumindest so weit, dass ich anfangen konnte, auf regelmäßiger Basis damit zu arbeiten. In meinem jungfräulichen persönlichen GitLab erstellte ich mir also eine frische Ecke für meine HA-Konfiguration – auch im alten Git hatte es die gegeben, aber irgendwie nie „in sauber“. Änderungen an der Konfig zu versionieren ist aber generell keine schlechte Idee, oder? 😇 Eine meiner ersten Amtshandlungen war dann die Erstellung einer .gitignore, denn das Logfile zum Beispiel wollte ich dann doch nicht so gerne regelmäßig sichern.

tts
.storage
home-assistant.log
home-assistant_v2.db

Erstellung .docker-compose.yml und erster Start

Dann ging es los mit dem docker-compose.yml: ich benötige drei Services, nämlich Home Assistant selbst, eine MariaDB für persistierende Daten und einen mosquitto für alle MQTT-sprechenden Geräte. Im Moment laufen die mit network_mode: host, und ich glaube, das ist gar nicht mal so schlau. Der Grund, weshalb ich das so handhabe, ist folgender: diese Instanz schreibt Messwerte in eine InfluxDB. Diese InfluxDB läuft aber auf einem externen Host beim Hoster, und deshalb ist InfluxDB ausschließlich über VPN erreichbar. Der Mac Mini, der Docker bereitstellt, baut auch eine VPN-Verbindung auf. Und die einzige funktionierende Möglichkeit, diese VPN-Verbindung auch dem HA-Container zur Verfügung zu stellen, war eben network_mode: host. Wenn jemand hier eine bessere Idee und/ oder Links zu sinnvoller Dokumentation hat: gerne her damit! Außerdem gebe ich dem Container explizit den internen DNS mit – nur der ist in der Lage, die Namen der Gateways sauber aufzulösen. Aber hier jetzt erstmal der Inhalt meiner docker-compose.yml.

# file: "docker-compose.yml"
version: '3.4'

services:
  ha:
    image: homeassistant/home-assistant:0.103.6
    hostname: homeassistant
    restart: always
    environment:
      - TZ=Europe/Berlin
    network_mode: host
    dns:
      - 192.168.2.70
    volumes:
      - type: bind
        source: /etc/docker/smarthome/ha_conf
        target: /config
    depends_on:
      - mariadb

  mosquitto:
    image: eclipse-mosquitto:1.6.8
    hostname: mosquitto
    network_mode: host
    restart: always
        
  mariadb:
    hostname: mariadb
    image: mariadb:10.4.11
    restart: always
    network_mode: host
    dns:
      - 192.168.2.70
    volumes:
      - type: bind
        source: /var/lib/mariadb_docker
        target: /var/lib/mysql

Damit kann ich schon arbeiten: ein einfaches docker-compose up -d erzeugt mir die Container. Natürlich müssen die Zugriffsrechte auf MariaDB und mosquitto separat geregelt und in die configuration.yaml von Home Assistant eingetragen werden – aber das ist auch schon alles. Ich habe nun also ein Repository, in dem eine .gitignore herumschwirrt, eine docker-compose.yml die das Bauen der Container definiert und einen Ordner ha_config mit den für Home Assistant relevanten Daten. Damit bin ich schon x-fach weiter, als ich es vorher je war: theoretisch könnte ich das Repository nun auf einem beliebigen neuen Docker-Host auschecken und die Maschinerie durchstarten – um das Rückspielen von Datenbankinhalten müsste ich mich separat kümmern, aber zumindest wäre mein Smart Home unmittelbar operabel und die Dusche nicht mehr dunkel.

Einrichtung gitlab-runner

Auf dem Mac Mini richte ich mir dann einen gitlab-runner ein – einen specific runner vom Typ shell executor, um genau zu sein. Was meinem Repository dann noch fehlt, ist eine hübsche gitlab-ci.yml, und für meine ersten zaghaften Tests sieht meine jetzt mal folgendermaßen aus:

image: docker:stable

services:
  - docker:stable-dind

stages:
  - deploy
   
before_script:
  - docker info
  - python --version

put-to-production:
  stage: deploy
  cache: {}
  script:
    - sudo apt-get install -y python3 python3-dev python3-pip
    - python3 -m pip install -U --force-reinstall pip --user
    - python3 -m pip install docker-compose --user
    - docker-compose up -d --build
  environment:
    name: production
    url: http://10.8.0.28:8123/
  when: manual
  only:
    - tags

Ich kann nun in Branches rumkritzeln, bis ich schwarz werde, und das in den Master mergen, wann immer mir danach ist. Aber in dem Moment, in dem ich ein neues Tag vergebe („tags“), erscheint meine put-to-production-Pipeline – die ich dann allerdings durch Klick („manual“) antreten muss. Und im Idealfall rennt die durch, zieht sich gegebenenfalls neue Versionen der Container, wirft sie an Ort und Stelle und startet sie anschließend direkt durch. Drei Upgrades hat mein HA-Smart Home bislang auf diese Art mitgemacht, und alle liefen problemlos – es fühlt sich sogar deutlich weniger nach „schwarze Katze schwenken“ an als vorher. openHAB 2 ist dann als nächstes dran – davor hab ich mich bislang gedrückt, weil das auf der Synology eigentlich ziemlich stressfrei läuft, never touch und so.

Fazit

Wie gesagt: ich stehe da noch sehr am Anfang und versuche derzeit, jeden Tag mindestens eine neue Sache für mich zu erschließen. Für Testumgebungen und zum Rumspielen finde ich das alles ganz großartig, für den Produktivbetrieb1 habe ich viele, sehr viele Fragezeichen überm Kopf.

  1. stabil, zuverlässig, sicher ↩︎