Ich nutze für regelmäßige Backups von Daten (z.B. Nextcloud) ein kleines Script, das Restic verwendet. Ich hatte allerdings schon mehrfach den Fall, dass ein Backup nicht sauber durchlief und das Backup-Repository damit gesperrt war und weitere Backups fehlschlugen, was ich dann natürlich erst Wochen (okay, Monate) später bemerkt habe.

Abhilfe schafft hier das Tool Healthchecks (https://github.com/healthchecks/healthchecks). Das funktioniert so, dass man Checks einrichtet und dafür eine Webhook-URL bekommt. In einem Script ruft man dann diese URL auf und setzt damit den Timer zurück. Sofern der Webhook nicht innerhalb der richtigen Zeit aufgerufen wird, wird ein Alert ausgelöst. Insgesamt also recht simpel.

Installation

Ich nutze hier, wie üblich, Docker. Hier meine docker-compose.yml:

services:
  healthchecks:
    image: healthchecks/healthchecks:latest
    container_name: healthchecks
    environment:
      - DB=sqlite
      - DB_NAME=/data/hc.sqlite
      - DEBUG=False
      - DEFAULT_FROM_EMAIL=me@example.com
      - EMAIL_HOST=smtp.example.com
      - EMAIL_HOST_PASSWORD=MyMailPassword
      - EMAIL_HOST_USER=me@example.com
      - EMAIL_PORT=587
      - EMAIL_USE_TLS=True
      - SECRET_KEY=Hok4K0Va6EwaYltk4ah7muc223rUVmz3
      - SITE_ROOT=https://checks.example.com
      - DISCORD_CLIENT_ID=123123
      - DISCORD_CLIENT_SECRET=123123
      - REGISTRATION_OPEN=False
    ports:
      - 8000:8000
    volumes:
      - ./data:/data
    restart: unless-stopped

REGISTRATION_OPEN muss initial auf True gestellt werden, damit man sich selbst registrieren kann, danach sollte das allerdings wieder auf False gesetzt werden, damit sich keine fremden User registrieren können. Ich habe hier direkt die Discord-Integration eingerichtet, damit ich auf dem Weg auch Notifications verschicken kann. Die beiden Variablen sind aber natürlich optional.

Das Datenverzeichnis muss die richtigen Zugriffsrechte haben, damit der Container starten kann. Das geht schnell mittels

mkdir ./data
chown -R 999:999 ./data

Danach lässt sich der Stack mit docker compose up -d starten und die Seite aufrufen. Dort kann man sich dann mit einer E-Mail-Adresse registrieren.

Einbindung in ein Script

Um jetzt einen Check einzurichten, muss zuerst im Webinterface ein neuer Check erstellt werden. Dabei wird auch das normale Intervall (z.B. täglich) sowie eine Karenzzeit eingestellt.

Nun wird eine Check-URL angezeigt, ich nehme hier https://checks.example.com/ping/bla-bla-blub als Beispiel.

Simpler Check

Für einen einfachen Check, ob das Script gelaufen ist, reicht es, einen Befehl wie z.B.

curl -fsS -m 10 --retry 5 https://checks.example.com/ping/bla-bla-blub

mit der Check-URL auszuführen. Der Befehl sollte im Script als letztes ausgeführt werden, damit er erst ausgeführt wird, wenn alles andere funktioniert hat.

Check mit Laufzeitberechnung

Healthchecks kann auch die Laufzeit eines Scripts mit prüfen. Dazu wird erst der Endpunkt https://checks.example.com/ping/bla-bla-blub/start aufgerufen und nach Fertigstellung dann https://checks.example.com/ping/bla-bla-blub. Hierbei sollte auch noch eine Request-ID mitgegeben werden, um die einzelnen Ausführungen voneinander unterscheiden zu können.

Ich habe das bspw. so umgesetzt:

RID=`uuidgen`
HEALTHCHECK_ID=bla-bla-blub
curl -fsS -m 10 --retry 5 https://checks.example.com/ping/$HEALTHCHECK_ID/start?rid=$RID

# do backup

curl -fsS -m 10 --retry 5 https://checks.example.com/ping/$HEALTHCHECK_ID?rid=$RID

Nachdem das Script ausgeführt wurde, sieht das im Webinterface so aus:

Ausgeführter Check

Sollte ein Check nicht innerhalb der eingestellten Zeit aufgerufen werden, wird eine Notification ausgelöst. So sollte ich in Zukunft fehlschlagende Backups schneller bemerken.