Voraussetzung: ein eingerichteter Server – einmaliger Aufbau in Server-Basis, wegwerfen & identisch neu in Snapshot & Restore. Was die Bausteine hier kosten: Kosten & Budget.
Was überwachen
Zwei Blickrichtungen, zwei Werkzeuge:
| Blackbox | Whitebox | |
|---|---|---|
| Frage | „kommt ein Nutzer an?“ | „warum ist es langsam / voll?“ |
| Werkzeug | Uptime Kuma | Netdata |
| prüft | HTTP-Status, Keyword auf der Seite, TCP-Port, Ping, Zertifikat, DNS (Domain Name System) | CPU (Central Processing Unit), RAM (Random Access Memory), Disk, IO, Netz, Container, systemd-Dienste, Load |
| von wo | von außen (anderer Host!) | auf dem Server selbst |
blog.seb4u.com, Zert-Ablauf, DNS …status.seb4u.comDen Monitor auf demselben Server laufen lassen, den er überwacht. Fällt der Server aus, fällt der Monitor mit – und niemand merkt es. Netdata darf lokal sein (es meldet vor dem Ausfall), Uptime Kuma und der Totmann-Schalter gehören woanders hin (Abschnitt 10).
1 ntfy: Push-Kanal
ntfy schiebt eine HTTP-Nachricht als Push-Benachrichtigung aufs Telefon. Ein Topic ist der Kanal – wer den Namen kennt, kann mitlesen und senden. Also unratbar wählen (oder Auth aktivieren).
Variante A: ntfy.sh nutzen (0 Aufwand)
curl -H "Title: Test" -H "Tags: warning" \
-d "Hallo vom Server" ntfy.sh/alerts-9f3k2p
ntfy-App (iOS/Android/Desktop) installieren → Topic alerts-9f3k2p
abonnieren. Die Test-Nachricht kommt an.
Variante B: ntfy selbst hosten (empfohlen)
services:
ntfy:
image: binwiederhier/ntfy:v2
command: serve
restart: unless-stopped
environment:
NTFY_BASE_URL: https://ntfy.seb4u.com
NTFY_BEHIND_PROXY: "true"
NTFY_AUTH_FILE: /var/lib/ntfy/user.db
NTFY_AUTH_DEFAULT_ACCESS: "deny-all"
volumes: [ ntfy:/var/lib/ntfy ]
networks: [ web ]
volumes: { ntfy: {} }
networks: { web: { name: web, external: true } }
docker compose exec ntfy ntfy user add --role=admin alarm
docker compose exec ntfy ntfy token add alarm # Token fuer Kuma/Netdata/Cron
ntfy.seb4u.com per Traefik oder
Cloudflare Tunnel
veröffentlichen (ohne Access – die App muss ohne Login pushen können, Schutz
läuft über das Token). Alle folgenden Beispiele nutzen ntfy.sh/<topic> –
ersetze das durch https://ntfy.seb4u.com/<topic>
+ Header Authorization: Bearer <token>.
2 Uptime Kuma aufsetzen
services:
kuma:
image: louislam/uptime-kuma:1
restart: unless-stopped
volumes: [ kuma:/app/data ]
networks: [ web ]
volumes: { kuma: {} }
networks: { web: { name: web, external: true } }
- Starten,
http://<host>:3001öffnen, Admin-Konto anlegen (nur beim ersten Mal offen). - → Typ ntfy → Server-URL + Topic + (falls self-hosted) Token. Test drücken.
- Pro Monitor die Benachrichtigung ankreuzen. Retries: 2, Heartbeat Interval: 60 s, Resend nach 30 min solange down.
3 Sinnvolle Checks
| Monitor-Typ | Ziel | meldet |
|---|---|---|
| HTTP (Hypertext Transfer Protocol) – Keyword | https://blog.seb4u.com, Keyword z. B. </html> | 500er, Timeout, WordPress-Fehlerseite (200 aber falscher Inhalt) |
| HTTP(s) – Zert-Ablauf | jede HTTPS-URL | Zertifikat läuft in < 14 Tagen ab (Kuma-Option „Certificate Expiry“) |
| TCP (Transmission Control Protocol) Port | podman-host:6443 / :5432 | API-Server / DB nicht mehr erreichbar (übers Tailnet prüfen) |
| DNS | seb4u.com Typ A | DNS-Auflösung falsch/weg (z. B. cf-dns.ps1-Hook vergessen) |
| HTTP | https://ntfy.seb4u.com | der Alarmkanal selbst ist tot – wichtig, sonst schweigt alles |
| Push (Heartbeat) | Backup-Job / cron pingt Kuma | ein Job läuft nicht mehr (wie healthchecks.io, nur in Kuma) |
Ein 200 OK heißt nicht, dass die Seite funktioniert – eine
Datenbank-Fehlerseite ist auch 200. Prüfe ein Wort, das nur auf der
heilen Seite steht (Titel, Footer-Text).
4 Status-Seite
Uptime Kuma bringt eine öffentliche Status-Seite mit – für dich selbst („liegt's an mir?“) oder für Nutzer.
-
→ Slug
public, Monitore auswählen, die drauf sollen (nicht die internen). - Domain zuweisen: in Kuma Domain Names →
status.seb4u.com, dann in Cloudflare/Traefik dorthin routen. - Alternativ ganz ohne eigenen Server: eine Status-Seite bei Better Stack / Instatus (Free-Tier), oder eine statische Seite auf Cloudflare Pages.
5 Netdata: Server-Metriken
Eine Zeile Installation, danach ein Live-Dashboard mit Sekunden-Auflösung: CPU, RAM, Disk, IO, Netz, jeder Container, jeder systemd-Dienst.
services:
netdata:
image: netdata/netdata:stable
restart: unless-stopped
hostname: podman-host
pid: host
cap_add: [ SYS_PTRACE, SYS_ADMIN ]
security_opt: [ apparmor:unconfined ]
volumes:
- netdataconfig:/etc/netdata
- netdatalib:/var/lib/netdata
- netdatacache:/var/cache/netdata
- /:/host/root:ro,rslave
- /etc/passwd:/host/etc/passwd:ro
- /etc/group:/host/etc/group:ro
- /etc/os-release:/host/etc/os-release:ro
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks: [ web ]
volumes: { netdataconfig: {}, netdatalib: {}, netdatacache: {} }
networks: { web: { name: web, external: true } }
- Dashboard:
http://<server>:19999– nicht öffentlich stellen, entweder nur übers Tailnet oder hinter Cloudflare Access. - Netdata Cloud (Free-Tier) verbindet mehrere Nodes in ein Dashboard, hat eine Mobile-App und zentrale Alarme – optional, geht auch komplett lokal.
- Aufbewahrung: Standard ~1 h hochauflösend + Tage in
dbengine. Für längere Historiestorage tiershochsetzen oder Metriken zu Prometheus exportieren (Abschnitt 12).
6 Netdata-Alarme → ntfy
Netdata bringt Hunderte Alarme mit (Disk füllt sich, RAM, Load, Container-Neustart-Schleife …). Sie müssen nur einen Weg zu dir finden.
SEND_CUSTOM="YES"
DEFAULT_RECIPIENT_CUSTOM="ntfy"
custom_sender() {
prio="default"; [ "${status}" = "CRITICAL" ] && prio="urgent"
[ "${status}" = "CLEAR" ] && prio="min"
curl -fsS -m 10 \
-H "Title: ${host}: ${name}" \
-H "Priority: ${prio}" \
-H "Tags: ${status}" \
-d "${status}: ${chart}.${name} = ${value} ${units} -- ${info}" \
"https://ntfy.seb4u.com/alerts-9f3k2p" >/dev/null || true
}
docker compose exec netdata /etc/netdata/edit-config health_alarm_notify.conf
docker compose exec netdata netdatacli reload-health
# Test: einen Alarm kuenstlich ausloesen
docker compose exec netdata /usr/libexec/netdata/plugins.d/alarm-notify.sh test ntfy
Sinnvoll nachschärfen (in /etc/netdata/health.d/)
- Disk: Warnung bei 80 %, kritisch bei 90 % – ein volles
/legt Docker und die DB lahm. - Ein bestimmter Container/Dienst weg (
systemd-Unit failed,docker-Healthunhealthy). - Alarme runterdrehen, die dich nicht interessieren (kurze CPU-Spitzen, IPv6 …) – sonst Alarm-Müdigkeit (Abschnitt 11).
7 Totmann-Schalter
Uptime Kuma prüft die Dienste. Ein Totmann-Schalter prüft, dass der Server überhaupt noch lebt – und deckt den Fall ab, dass Server und Monitor gleichzeitig weg sind.
# minuetlich "ich lebe" an healthchecks.io (Free, 20 Checks); bleibt es 5 Min aus -> deren Alarm
* * * * * curl -fsS -m 10 --retry 3 https://hc-ping.com/DEIN-UUID >/dev/null
# der Backup-Job pingt einen ZWEITEN Check (siehe Backup-Anleitung)
Dort ebenfalls ntfy als Integration hinterlegen – oder E-Mail. So landet auch dieser Alarm im selben Kanal. healthchecks.io kann man auch selbst hosten, dann aber wieder auf einem anderen Host als dem überwachten.
8 Logs im Blick
- Docker-Logs begrenzen (sonst läuft
/voll):/etc/docker/daemon.json→{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}, dannsystemctl restart docker. - journald begrenzen:
/etc/systemd/journald.conf→SystemMaxUse=500M. - Schnell reingucken:
journalctl -u docker -p err --since -1h,docker compose logs -f --tail 100, oderlnavfür mehrere Logdateien. - Nächster Schritt (wenn ein Server nicht mehr reicht): zentrale Logs
mit Grafana Loki + Alloy/Promtail, Alarme auf Log-Muster
(„5×
OutOfMemoryin 10 min“). Für einen Server meist Overkill –journalctl+ Netdata-Log-Charts reichen.
9 Wo läuft der Monitor?
| Komponente | wohin | warum |
|---|---|---|
| Netdata | auf jeden überwachten Server | misst lokal, meldet vor dem Ausfall |
| Uptime Kuma | separater Mini-Host (CPX22 ~19,5 €, CAX11 ARM ~6 falls frei) oder daheim (Raspi/NAS) | muss laufen, wenn der Hauptserver nicht läuft |
| ntfy | am besten auf dem Kuma-Host (nicht dem überwachten) | der Alarmkanal darf nicht mit dem Problem sterben |
| Totmann-Schalter | externer Dienst (healthchecks.io) | letzte Instanz, wenn alles Eigene weg ist |
Netdata lokal + healthchecks.io (Totmann) + ein externer Free-Monitor (UptimeRobot, 50 Checks gratis) für die öffentlichen URLs (Uniform Resource Locators). Kostet 0 € und deckt den Ausfall des Hauptservers ab. Uptime Kuma selbst hosten lohnt ab ~3–4 zu überwachenden Systemen.
10 Betrieb & Alarm-Hygiene
- Jeder Alarm muss eine Handlung auslösen. Löst er nichts aus → Schwelle hochsetzen oder Alarm abschalten. Rauschen macht, dass du den einen wichtigen übersiehst.
- Prioritäten trennen:
urgent(Dienst down, Disk voll) darf nachts klingeln.default/low(CPU-Spitze, Zert in 14 Tagen) nur tagsüber. In ntfy per Topic oder Priority steuerbar. - Ruhezeiten: ntfy-App hat „Do Not Disturb“ pro Topic. Kritische Sachen auf ein eigenes Topic mit Ton.
- Nach jedem Vorfall: gab es einen Alarm? kam er schnell genug? war er eindeutig? – und die Regeln entsprechend anpassen.
- Updates:
docker compose pull && up -dfür Kuma/ntfy/Netdata (Tags gepinnt, siehe Mehrere Dienste). - Test: ein-, zweimal im Jahr einen Dienst absichtlich stoppen und prüfen, dass der Alarm ankommt – wie der Restore-Test beim Backup.
+ Grafana + Prometheus
Wenn Netdata nicht reicht: mehrere Server in einem Dashboard, lange Historie, eigene Alarmregeln (PromQL), Dashboards teilbar.
services:
prometheus: { image: prom/prometheus:v3.1.0, volumes: [ ./prometheus.yml:/etc/prometheus/prometheus.yml, prom:/prometheus ], networks: [ mon ] }
node-exporter:{ image: prom/node-exporter:v1.8.2, pid: host, volumes: [ /:/host:ro,rslave ], command: [ "--path.rootfs=/host" ], networks: [ mon ] }
cadvisor: { image: gcr.io/cadvisor/cadvisor:v0.49.1, volumes: [ /:/rootfs:ro, /var/run:/var/run:ro, /sys:/sys:ro, /var/lib/docker/:/var/lib/docker:ro ], networks: [ mon ] }
grafana: { image: grafana/grafana:11.4.0, volumes: [ graf:/var/lib/grafana ], networks: [ mon, web ] }
alertmanager: { image: prom/alertmanager:v0.28.0, volumes: [ ./alertmanager.yml:/etc/alertmanager/alertmanager.yml ], networks: [ mon ] }
volumes: { prom: {}, graf: {}, }
networks: { mon: {}, web: { name: web, external: true } }
Alertmanager → ntfy per Webhook-Brücke (alertmanager-ntfy) oder einem
kleinen Empfänger-Skript. Grafana bringt fertige Dashboards für node-exporter (ID
1860) und cadvisor mit. Erst wenn Netdata + Uptime Kuma wirklich zu wenig
sind – das ist deutlich mehr Pflege.
+ Kosten
Preise sind Richtwerte. Hetzner hat 2026 zweimal erhöht (zuletzt 15. Juni: CX/CAX +30–40 %, CPX/CCX über 100 %). Aktuelle Server-Preise, alle Nebenposten, ein Rechner und Beispielrechnungen stehen zentral in Kosten & Budget.
| Posten | €/Tag | €/Monat |
|---|---|---|
| Netdata (lokal, auf vorhandenem Server) | 0 | 0 |
| ntfy (self-hosted, auf vorhandenem Server) / ntfy.sh | 0 | 0 |
| healthchecks.io / UptimeRobot (Free-Tier) | 0 | 0 |
Separater Mini-Host für Uptime Kuma + ntfy (CPX22, CAX11 falls frei) – optional | ~0,2 | ~6–20 |
| Netdata Cloud (Free-Tier) | 0 | 0 |
| Minimal / mit eigenem Monitor-Host | 0 / ~0,17 | 0 / ~5 |
Wenn du schon einen anderen Server hast (z. B. den privaten Projekt-Host), läuft Uptime Kuma dort mit – dann 0 €.