diff --git a/docs/ALERTING_MAP.md b/docs/ALERTING_MAP.md new file mode 100644 index 0000000..b9e96cd --- /dev/null +++ b/docs/ALERTING_MAP.md @@ -0,0 +1,30 @@ +# Alerting Map + +Stand: 2026-05-17 + +Ziel: Alle problemrelevanten Homelab-Meldungen landen auf einem Handy-Topic. + +## ntfy Topics + +| Topic | Zweck | +|---|---| +| `homelab-alerts` | Alles, was Aufmerksamkeit braucht: Prometheus, Docker-Events, Posture, Zertifikate/Token, Compose-Drift, Borg-Pre-Hook-Fehler und Restore-Fehler | +| `homelab-info` | Optionale Erfolgsmeldungen, z. B. erfolgreiche Restore-Testlaeufe | + +## Sender + +| Sender | Pfad | Problem-Topic | Hinweis | +|---|---|---|---| +| Prometheus / Alertmanager | `monitoring/alertmanager/alertmanager.yml`, `monitoring/alertmanager-ntfy-bridge/bridge.py` | `homelab-alerts` | Zentrale Monitoring-Alerts via Bridge | +| Posture Check | `services/posture-check/posture-check.sh` | `homelab-alerts` | Warning und Critical gehen auf dasselbe Handy-Topic | +| Cert / Token Check | `services/posture-check/cert-token-check.sh` | `homelab-alerts` | Prueft produktive HTTPS-Domains und Cloudflare Token | +| Compose Runtime Drift | `services/posture-check/compose-runtime-drift.sh` | `homelab-alerts` | Meldet Abweichungen zwischen Repo-Compose und Runtime-Image | +| Docker Critical Events | `services/posture-check/docker-critical-events.sh` | `homelab-alerts` | Meldet Docker `die`, `oom` und `kill` Events | +| Borg Pre-Hook | `ops/borg-ui/scripts/pre-borg.sh` | `homelab-alerts` | Meldet Fehler vor Borg, z. B. Posture-, Dump- oder Restore-Freshness-Fehler | +| Restore Jobs | `ops/restore-tests/run-restore-job-with-ntfy.sh` | `homelab-alerts` | Erfolg geht an `homelab-info`, Fehler immer an `homelab-alerts` | + +## Konvention + +- `NTFY_BASE_URL` zeigt standardmaessig auf `https://ntfy.kaleschke.info`. +- Neue Problem-Alerts sollen `homelab-alerts` nutzen. +- Erfolgsmeldungen sind optional und sollen nicht in `homelab-alerts` landen, ausser sie sind bewusst als Lebenszeichen gewuenscht. diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md index e810afe..6d4edf2 100644 --- a/docs/REPO_MAP.md +++ b/docs/REPO_MAP.md @@ -31,6 +31,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam | `docs/GITOPS_DRIFT_RUNBOOK.md` | Pflichtmatrix fuer Git/Gitea/Komodo/Docker/Host-Drift | | `docs/DISASTER_RECOVERY.md` | Wiederanlauf nach Host-/Systemausfall | | `docs/RESTORE_MATRIX.md` | Restore-Quellen, Dump-Artefakte und Smoke-Tests je Dienst | +| `docs/ALERTING_MAP.md` | ntfy Topic-Konvention und Sender-Mapping fuer Homelab-Alerts | | `docs/ROLLBACK.md` | Rueckweg bei Fehlern im GitOps-Betrieb | | `docs/SECRETS_MAP.md` | Secret-Namen, Pfade und Einbindungsarten ohne Werte | | `docs/HOME_ASSISTANT_INFLUXDB_ECOWITT.md` | Home Assistant -> InfluxDB 3 -> Grafana Ablauf | @@ -230,7 +231,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam |---|---|---| | `ops/borg-ui/scripts/pre-backup-dumps.sh` | Unraid Host, nicht Borg-UI Inline-Hook | erzeugt aktuelle Dumps unter `/mnt/user/backups/borg/dumps/latest` | | `services/posture-check/posture-check.sh` | Unraid Host | schreibt `/mnt/user/services/posture-check/last.json` und alarmiert via ntfy bei Warning/Critical | -| `services/posture-check/docker-critical-events.sh` | Unraid Host | beobachtet Docker `die`/`oom`/`kill` Events und alarmiert via `kallilab-critical` | +| `services/posture-check/docker-critical-events.sh` | Unraid Host | beobachtet Docker `die`/`oom`/`kill` Events und alarmiert via `homelab-alerts` | Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei Analyse niemals Secret-Inhalte ausgeben. diff --git a/docs/RESTORE_HANDBOOK.md b/docs/RESTORE_HANDBOOK.md index 08d7736..9e4eff3 100644 --- a/docs/RESTORE_HANDBOOK.md +++ b/docs/RESTORE_HANDBOOK.md @@ -193,7 +193,7 @@ bash /mnt/user/services/homelab/ops/restore-tests/run-restore-checks.sh paperles ### Optional mit `ntfy` ```bash -bash /mnt/user/services/homelab/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-restore +bash /mnt/user/services/homelab/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-info ``` --- diff --git a/docs/SERVICE_CATALOG.md b/docs/SERVICE_CATALOG.md index aa19d56..59aacfb 100644 --- a/docs/SERVICE_CATALOG.md +++ b/docs/SERVICE_CATALOG.md @@ -47,7 +47,7 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und | `nextcloud` | Datei-/Cloud-Dienst | `apps/nextcloud/docker-compose.yml` | `https://cloud.kaleschke.info` | eigene PostgreSQL, eigene Redis, Traefik | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data` | Tier 2, `nextcloud.dump` + Share | ja | native App-Auth ohne zentrale ForwardAuth; WebDAV/CardDAV beachten | | `nextcloud-postgres` | Nextcloud-Datenbank | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/postgres`, `nextcloud_postgres_password.txt` | `nextcloud.dump`, raw DB nicht primaerer Restore-Weg | nein | interne DB | | `nextcloud-redis` | Nextcloud Cache/Locking | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/redis` | Teil von Nextcloud-Restore | nein | interne Redis | -| `ntfy` | Push-Benachrichtigungen | `apps/ntfy/docker-compose.yml` | `https://ntfy.kaleschke.info` | Traefik, upstream mobile push | `/mnt/user/appdata/ntfy` | Tier 2 | ja | `NTFY_BEHIND_PROXY=true`; Monitoring/Borg-Benachrichtigungen | +| `ntfy` | Push-Benachrichtigungen | `apps/ntfy/docker-compose.yml` | `https://ntfy.kaleschke.info` | Traefik, upstream mobile push | `/mnt/user/appdata/ntfy` | Tier 2 | ja | `NTFY_BEHIND_PROXY=true`; Problem-Alerts gehen gebuendelt an `homelab-alerts`, optionale Erfolgsmeldungen an `homelab-info` | | `bentopdf` | PDF-Tooling / Ersatz fuer Stirling-PDF | `apps/bentopdf/docker-compose.yml` | `https://pdf.kaleschke.info` | Traefik + Authelia | keine kritische Persistenz im Compose | Tier 3, rebuildbar | ja + Authelia | COOP/COEP per Middleware; fachliche Abnahme/Live-Status pruefen | ## Operations / Monitoring / Admin @@ -87,7 +87,7 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und | Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs | |---|---|---|---|---|---|---|---|---| | `posture-check` | Host-Posture-Audit fuer Filesystem, Mover-Drift, NVMe-SMART und Fuellstand | `services/posture-check/posture-check.sh` | Unraid User-Script / Cron / Borg Pre-Hook | `findmnt`, `df`, `nvme`, optional `curl` fuer ntfy | `/mnt/user/services/posture-check/last.json` | Repo-Skript + letzter JSON-Status | nein | Muss auf dem Unraid-Host bei Boot, stuendlich und vor Borg laufen; `ALLOW_DISK1_NTFS=1` ist die dokumentierte Uebergangsausnahme bis Disk1-Migration Phase 2; Warning/Critical alarmieren via ntfy | -| `docker-critical-events` | Live-Alarmierung fuer Docker `die`/`oom`/`kill` Events | `services/posture-check/docker-critical-events.sh` | Unraid User-Script / Hintergrundprozess | Docker CLI, ntfy | `/mnt/user/services/posture-check/docker-critical-events-last.log` | Repo-Skript + letzter Event-Log | nein | Optional als Unraid User-Script `at array start` starten; sendet nach `kallilab-critical` | +| `docker-critical-events` | Live-Alarmierung fuer Docker `die`/`oom`/`kill` Events | `services/posture-check/docker-critical-events.sh` | Unraid User-Script / Hintergrundprozess | Docker CLI, ntfy | `/mnt/user/services/posture-check/docker-critical-events-last.log` | Repo-Skript + letzter Event-Log | nein | Optional als Unraid User-Script `at array start` starten; sendet nach `homelab-alerts` | ## Backup- und Restore-Hinweise diff --git a/docs/STORAGE_LAYOUT.draft.md b/docs/STORAGE_LAYOUT.draft.md index 2860d8d..1236873 100644 --- a/docs/STORAGE_LAYOUT.draft.md +++ b/docs/STORAGE_LAYOUT.draft.md @@ -253,7 +253,7 @@ Automatisierter Check, der mindestens täglich läuft (z. B. via User-Script ode - **Nach jedem Mover-Lauf** als Post-Hook — verifiziert, dass Mover keine `cache: only`-Shares angefasst hat - **Vor jeder strukturellen Änderung** (Disk-Tausch, Pool-Umzug, Format-Aktion) manuell — Soll-Ist-Abgleich vor destruktiven Aktionen -**Alarmziel (Operator-Entscheidung 2026-05-15): ntfy.** Selbst gehosteter ntfy-Server oder ntfy.sh, Topic-Konvention `kallilab-` (z. B. `kallilab-critical`, `kallilab-warning`). Push-Empfänger sind die Mobil-Geräte des Operators. Optional als Folge-Erweiterung: E-Mail-Fallback über mail-archiver-Stack als persistente Trail für historische Auswertung — nicht jetzt entscheiden, kann später dazukommen. +**Alarmziel (Operator-Entscheidung 2026-05-15, normalisiert 2026-05-17): ntfy.** Problem-Alerts gehen an den selbst gehosteten ntfy-Server `https://ntfy.kaleschke.info` mit dem Topic `homelab-alerts`. Optionale Erfolgsmeldungen gehen an `homelab-info`. Push-Empfänger sind die Mobil-Geräte des Operators. Optional als Folge-Erweiterung: E-Mail-Fallback über mail-archiver-Stack als persistente Trail für historische Auswertung — nicht jetzt entscheiden, kann später dazukommen. **Pflichtprüfungen:** diff --git a/ops/borg-ui/scripts/pre-borg.sh b/ops/borg-ui/scripts/pre-borg.sh index 8712be1..a913a4a 100755 --- a/ops/borg-ui/scripts/pre-borg.sh +++ b/ops/borg-ui/scripts/pre-borg.sh @@ -7,7 +7,7 @@ POSTURE_CHECK="${POSTURE_CHECK:-$REPO_ROOT/services/posture-check/posture-check. FRESHNESS_CHECK="${FRESHNESS_CHECK:-$REPO_ROOT/ops/restore-tests/check-restore-freshness.sh}" PRE_BACKUP_DUMPS="${PRE_BACKUP_DUMPS:-$SCRIPT_DIR/pre-backup-dumps.sh}" NTFY_SCRIPT="${NTFY_SCRIPT:-$REPO_ROOT/ops/restore-tests/send-ntfy.sh}" -NTFY_TOPIC="${NTFY_TOPIC:-kallilab-critical}" +NTFY_TOPIC="${NTFY_TOPIC:-homelab-alerts}" ALLOW_POSTURE_WARNING="${ALLOW_POSTURE_WARNING:-1}" notify_failure() { diff --git a/ops/restore-tests/monthly-random-restore.sh b/ops/restore-tests/monthly-random-restore.sh index 57d2a0d..0cf35d6 100755 --- a/ops/restore-tests/monthly-random-restore.sh +++ b/ops/restore-tests/monthly-random-restore.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -TOPIC="${TOPIC:-kallilab-info}" +TOPIC="${TOPIC:-homelab-info}" TESTS="${TESTS:-vaultwarden gitea paperless}" pick_random() { diff --git a/ops/restore-tests/run-restore-job-with-ntfy.sh b/ops/restore-tests/run-restore-job-with-ntfy.sh index 76d0feb..39beb92 100644 --- a/ops/restore-tests/run-restore-job-with-ntfy.sh +++ b/ops/restore-tests/run-restore-job-with-ntfy.sh @@ -3,10 +3,11 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" MODE="${1:-}" -TOPIC="${2:-homelab-restore}" +SUCCESS_TOPIC="${2:-${RESTORE_SUCCESS_TOPIC:-homelab-info}}" +FAILURE_TOPIC="${RESTORE_FAILURE_TOPIC:-homelab-alerts}" if [ -z "$MODE" ]; then - echo "Usage: $0 [topic]" >&2 + echo "Usage: $0 [success_topic]" >&2 exit 1 fi @@ -20,10 +21,10 @@ echo "Report target: $REPORT_FILE" if "$SCRIPT_DIR/run-restore-checks.sh" "$MODE" > "$REPORT_FILE"; then echo "Restore job succeeded, sending ntfy..." - "$SCRIPT_DIR/send-ntfy.sh" "$TOPIC" "Restore job ok: $MODE" "Restore job succeeded. Report: $REPORT_FILE" default || true + "$SCRIPT_DIR/send-ntfy.sh" "$SUCCESS_TOPIC" "Restore job ok: $MODE" "Restore job succeeded. Report: $REPORT_FILE" default || true echo "Done" else echo "Restore job failed, sending ntfy..." - "$SCRIPT_DIR/send-ntfy.sh" "$TOPIC" "Restore job failed: $MODE" "Restore job failed. Report: $REPORT_FILE" high || true + "$SCRIPT_DIR/send-ntfy.sh" "$FAILURE_TOPIC" "Restore job failed: $MODE" "Restore job failed. Report: $REPORT_FILE" high || true exit 1 fi diff --git a/ops/restore-tests/unraid-user-scripts.md b/ops/restore-tests/unraid-user-scripts.md index c61839f..899d40d 100644 --- a/ops/restore-tests/unraid-user-scripts.md +++ b/ops/restore-tests/unraid-user-scripts.md @@ -97,9 +97,11 @@ Beispiel: ```bash #!/bin/bash -bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-restore +bash /mnt/user/services/homelab-infra/ops/restore-tests/run-restore-job-with-ntfy.sh freshness homelab-info ``` +Fehler gehen unabhaengig vom Erfolgstopic nach `homelab-alerts`, damit Restore-Probleme auf dem gleichen Handy-Topic landen wie Prometheus-, Docker-, Borg- und Posture-Alarme. + Verwendete Hilfsskripte: - `ops/restore-tests/send-ntfy.sh` diff --git a/services/posture-check/cert-token-check.sh b/services/posture-check/cert-token-check.sh index 89d83d9..128f77c 100755 --- a/services/posture-check/cert-token-check.sh +++ b/services/posture-check/cert-token-check.sh @@ -2,14 +2,14 @@ set -euo pipefail OUTPUT_PATH="${OUTPUT_PATH:-/mnt/user/services/posture-check/cert-token-last.json}" -NTFY_BASE_URL="${NTFY_BASE_URL:-https://ntfy.sh}" -WARNING_TOPIC="${WARNING_TOPIC:-kallilab-warning}" -CRITICAL_TOPIC="${CRITICAL_TOPIC:-kallilab-critical}" +NTFY_BASE_URL="${NTFY_BASE_URL:-https://ntfy.kaleschke.info}" +WARNING_TOPIC="${WARNING_TOPIC:-homelab-alerts}" +CRITICAL_TOPIC="${CRITICAL_TOPIC:-homelab-alerts}" SEND_NTFY="${SEND_NTFY:-1}" CLOUDFLARE_TOKEN_FILE="${CLOUDFLARE_TOKEN_FILE:-/mnt/user/appdata/traefik/secrets/cloudflare_dns_api_token}" WARN_DAYS="${WARN_DAYS:-14}" CRITICAL_DAYS="${CRITICAL_DAYS:-7}" -DOMAINS="${DOMAINS:-traefik.kaleschke.info auth.kaleschke.info vault.kaleschke.info git.kaleschke.info cloud.kaleschke.info home.kaleschke.info borg.kaleschke.info grafana.kaleschke.info}" +DOMAINS="${DOMAINS:-traefik.kaleschke.info auth.kaleschke.info vault.kaleschke.info git.kaleschke.info cloud.kaleschke.info home.kaleschke.info borg.kaleschke.info monitoring.kaleschke.info ntfy.kaleschke.info}" TMP_DIR="${TMP_DIR:-/tmp/kallilab-cert-token-check}" mkdir -p "$TMP_DIR" diff --git a/services/posture-check/compose-runtime-drift.sh b/services/posture-check/compose-runtime-drift.sh index f02bcd5..39a5a2f 100755 --- a/services/posture-check/compose-runtime-drift.sh +++ b/services/posture-check/compose-runtime-drift.sh @@ -4,7 +4,7 @@ set -euo pipefail REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" OUTPUT_PATH="${OUTPUT_PATH:-/mnt/user/services/posture-check/compose-runtime-drift-last.json}" NTFY_SCRIPT="${NTFY_SCRIPT:-$REPO_ROOT/ops/restore-tests/send-ntfy.sh}" -NTFY_TOPIC="${NTFY_TOPIC:-kallilab-warning}" +NTFY_TOPIC="${NTFY_TOPIC:-homelab-alerts}" SEND_NTFY="${SEND_NTFY:-1}" TMP_DIR="${TMP_DIR:-/tmp/kallilab-compose-runtime-drift}" diff --git a/services/posture-check/docker-critical-events.sh b/services/posture-check/docker-critical-events.sh index 95de57f..da68831 100755 --- a/services/posture-check/docker-critical-events.sh +++ b/services/posture-check/docker-critical-events.sh @@ -2,7 +2,7 @@ set -euo pipefail NTFY_SCRIPT="${NTFY_SCRIPT:-/mnt/user/services/homelab-infra/ops/restore-tests/send-ntfy.sh}" -NTFY_TOPIC="${NTFY_TOPIC:-kallilab-critical}" +NTFY_TOPIC="${NTFY_TOPIC:-homelab-alerts}" SEND_NTFY="${SEND_NTFY:-1}" OUTPUT_PATH="${OUTPUT_PATH:-/mnt/user/services/posture-check/docker-critical-events-last.log}" EVENT_FILTERS="${EVENT_FILTERS:---filter event=die --filter event=oom --filter event=kill}" diff --git a/services/posture-check/posture-check.sh b/services/posture-check/posture-check.sh index d89cf73..bf55ce5 100755 --- a/services/posture-check/posture-check.sh +++ b/services/posture-check/posture-check.sh @@ -2,9 +2,9 @@ set -euo pipefail OUTPUT_PATH="${OUTPUT_PATH:-/mnt/user/services/posture-check/last.json}" -NTFY_BASE_URL="${NTFY_BASE_URL:-https://ntfy.sh}" -WARNING_TOPIC="${WARNING_TOPIC:-kallilab-warning}" -CRITICAL_TOPIC="${CRITICAL_TOPIC:-kallilab-critical}" +NTFY_BASE_URL="${NTFY_BASE_URL:-https://ntfy.kaleschke.info}" +WARNING_TOPIC="${WARNING_TOPIC:-homelab-alerts}" +CRITICAL_TOPIC="${CRITICAL_TOPIC:-homelab-alerts}" SEND_NTFY="${SEND_NTFY:-1}" TMP_DIR="${TMP_DIR:-/tmp/kallilab-posture-check}" ALLOW_DISK1_NTFS="${ALLOW_DISK1_NTFS:-1}"