From 080c7c29bf24938cf926a183c60acd4de2e2a95d Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Fri, 28 Aug 2026 10:06:04 -0700 Subject: [PATCH] monitoring: doorbell-listener heartbeat + systemd timer --- .../scripts/kuma-heartbeat.sh | 46 +++++++++++++++++++ infra/systemd/doorbell-kuma-heartbeat.service | 8 ++++ infra/systemd/doorbell-kuma-heartbeat.timer | 10 ++++ 3 files changed, 64 insertions(+) create mode 100755 infra/doorbell-listener/scripts/kuma-heartbeat.sh create mode 100644 infra/systemd/doorbell-kuma-heartbeat.service create mode 100644 infra/systemd/doorbell-kuma-heartbeat.timer diff --git a/infra/doorbell-listener/scripts/kuma-heartbeat.sh b/infra/doorbell-listener/scripts/kuma-heartbeat.sh new file mode 100755 index 0000000..9626d65 --- /dev/null +++ b/infra/doorbell-listener/scripts/kuma-heartbeat.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -u + +KUMA_BASE="${KUMA_BASE:-https://up.notsosm.art}" +TOKEN_FILE="${KUMA_TOKEN_FILE:-/root/nr-flow-validator/infra/.secrets/doorbell-kuma-push-token}" +CANARY_TOPIC="${CANARY_TOPIC:-ALERT_klubhaus_health}" +CONTAINER="${DB_CONTAINER:-doorbell-listener}" + +[ -s "$TOKEN_FILE" ] || exit 1 +TOKEN="$(tr -d '[:space:]' < "$TOKEN_FILE")" + +reason="" + +# 1. listener container liveness +running=$(docker inspect "$CONTAINER" --format '{{.State.Running}}' 2>/dev/null) +if [ "$running" != "true" ]; then + reason="container_running=${running:-unknown}" +else + # 2. ntfy.sh round-trip: publish a unique canary, read it back. + # Proves the ntfy.sh leg we depend on (publish + subscribe) works, + # without us owning the service. + marker="canary-$(date +%s)-$$" + url="https://ntfy.sh/${CANARY_TOPIC}" + if ! curl -fsS -m 10 -o /dev/null -X POST "$url" -d "$marker" 2>/dev/null; then + reason="${reason}ntfy_publish_failed" + else + sleep 1 + body=$(curl -fsS -m 10 "$url/json" 2>/dev/null) + if [ -z "$body" ] || ! printf '%s' "$body" | grep -qF "$marker"; then + reason="${reason}ntfy_echo_missing" + fi + fi +fi + +if [ -n "$reason" ]; then + status="down" + msg="doorbell: ${reason}" +else + status="up" + msg="doorbell ok" +fi + +curl -fsS -m 10 -o /dev/null --get \ + --data-urlencode "status=$status" \ + --data-urlencode "msg=$msg" \ + "$KUMA_BASE/api/push/$TOKEN" diff --git a/infra/systemd/doorbell-kuma-heartbeat.service b/infra/systemd/doorbell-kuma-heartbeat.service new file mode 100644 index 0000000..c396178 --- /dev/null +++ b/infra/systemd/doorbell-kuma-heartbeat.service @@ -0,0 +1,8 @@ +[Unit] +Description=Doorbell listener heartbeat to Uptime Kuma +After=docker.service +Requires=docker.service + +[Service] +Type=oneshot +ExecStart=/root/nr-flow-validator/infra/doorbell-listener/scripts/kuma-heartbeat.sh diff --git a/infra/systemd/doorbell-kuma-heartbeat.timer b/infra/systemd/doorbell-kuma-heartbeat.timer new file mode 100644 index 0000000..b3089c2 --- /dev/null +++ b/infra/systemd/doorbell-kuma-heartbeat.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Run doorbell listener heartbeat every minute + +[Timer] +OnCalendar=*-*-* *:*:00 +AccuracySec=5s +Persistent=true + +[Install] +WantedBy=timers.target