Homeassistant + Monit = 🖤

Jag fick för mig att testa monit då jag sett namnet dyka upp här och där på sistone, och kom på att jag verkligen behövde sätta upp monitorering för min HomeAssistant-instans. Då det var en förvånadsvärt trevlig upplevelse att sätta upp tänkte jag dela med mig hur det blev. Innehållet nedan är förresten applicerbart för att köra alla möjliga tjänster med.

Hade jag kört på ett Linux-system hade jag satt upp en systemd-tjänst istället för att använda monit, men den datorn som används för att köra HomeAssistant hemma hos mig kör OpenBSD. Om du skulle använda något av de uppskattningsvis tre distributioner som inte använder systemd är nedan relevant för dig. :)

Vi börjar med ett start- och stoppskript för att styra HomeAssistant. Detta för att slippa definiera allt för mycket i den systemglobala monitrc-filen senare, även om det öppnar upp för en liten möjlighet att någon illvillig att stöka runt senare1.

Spara innehållet nedan i en fil (jag kallade min fil hasse) och ge den exekveringsrättigheter (chmod u+x hasse).

#!/usr/bin/env bash

PIDFILE=$HOME/.homeassistant/hasse.pid

case $1 in
   start)
       # Jag använder virtualenv (typ) enligt denna instruktion:
       # https://www.home-assistant.io/docs/installation/virtualenv/
       source  $HOME/venv/bin/activate
       hass --pid-file $PIDFILE
   ;;
   stop)
      kill `cat $PIDFILE`
      rm $PIDFILE
   ;;
   *)
      echo "usage: hasse {start|stop}" ;;
esac
exit 0

Testa att manuellt slå ihjäl din HomeAssistant-process och starta den med hjälp av skriptet, nedan antar jag att du sparade skriptet som $HOME/hasse:

pkill -f hass
$HOME/hasse start

Inga felmeddelanden? Bra! Kolla även att processen körs:

cat $HOME/.homeassistant/hasse.pid
pgrep -f hass

Ovan borde ge samma process-id två gånger, även om det kommer vara andra siffror när du kör det:

$ pgrep -f hass
57614
$ cat .homeassistant/hassio.pid
57614

När detta skript är på plats är det väldigt enkelt att sätta upp en övervakning för din HomeAssistant-process, lägg in följande definition i din /etc/monitrc-fil:

check process homeassistant with pidfile /home/homeassistant/.homeassistant/hassio.pid
  start program = "/home/homeassistant/hasse start" as uid "homeassistant" and gid "homeassistant"
  stop program = "/home/homeassistant/hasse stop" as uid "homeassistant" and gid "homeassistant"

Med detta på plats har du precis satt upp en övervakning för din HomeAssistant, som kommer starta tjänsten om den inte redan körs. Utöver det kan du instruera monit att mejla dig om något händer, du kan be monit att kontrollera att HomeAssistant fungerar utöver att den körs (se nedan) eller har varit igång för länge2.

En lite mer komplett monitrc-fil kan du hitta exempelvis här. Manualen hittar du här.


Överkurs

För att kolla om HomeAssistants API svarar på anrop, spara nedan som ett skript och ge det lämpliga exekveringsrättigheter:

#!/usr/bin/env bash

api_key=$(gawk 'match($0, /^http: (.*)$/, m) { print m[1] }'\
               $HOME/.homeassistant/secrets.yaml)
status=$?

if [ $status -eq 0 ];
then
    curl -m 2 -sf -X GET -H "x-ha-access: ${api_key}"\
         -H "Content-Type: application/json"\
         http://localhost:8123/api/ &> /dev/null || exit 1
else
    echo "No API key found in secrets.yaml"
    exit 1
fi

Skriptet ovan extraherar API-lösenordet från din $HOME/.homeassistant/secrets.yaml, givet att den ser ut ungefär såhär:

http: mitt superhemliga och säkra lösenord

Avsluta med att lägga in nedan i din /etc/monitrc-fil:

check program homeassistant-api with path /home/homeassistant/check_api.sh as uid "homeassistant" and gid "homeassistant"
  with timeout 5 seconds
  if status != 0 for 6 cycles then exec "/home/homeassistant/hasse stop" as uid "homeassistant" and gid "homeassistant"

  1. Detta då jag p.g.a. lättja valde att placera detta skript i hemmappen för min HomeAssistant-användare. Vi kommer dock sätta upp monit så att den kör detta skript med samma uid/gid som min HomeAssistant-användare, vilket borde begränsa eventuell skada något.

    [return]
  2. Lägg till if uptime > 3 days then restart efter stop program-definitionen. [return]