Server-Monitoring einrichten: Wissen wenn der Server ausfällt
Uptime-Monitoring, Alerts und Prometheus + Grafana Stack einrichten. Kostenlose und kostenpflichtige Optionen.
Kurzfassung
Nutze kostenlose externe Monitoring-Dienste (UptimeRobot oder HetrixTools) für Erreichbarkeits-Checks und sofortige Benachrichtigungen. Für tiefere Einblicke in CPU, RAM, Festplatte und Container-Zustand setzt du Prometheus + Grafana per Docker Compose auf. Die Kombination beider Ansätze liefert umfassende Abdeckung: Externes Monitoring erkennt Ausfälle, die du von innerhalb deiner eigenen Infrastruktur nicht sehen kannst, während Prometheus dir die Metriken liefert, um Ursachen zu diagnostizieren und Probleme vorherzusagen, bevor sie auftreten.
Voraussetzungen
- Ein Linux-Server (Ubuntu 22.04/24.04 oder Debian 12 empfohlen) mit Root- oder Sudo-Zugang
- Docker und Docker Compose installiert (
docker compose versionsollte v2.x+ ausgeben) - Ein Domainname, der auf deinen Server zeigt (für SSL-Überwachung und Status-Seite)
- Grundlegende Vertrautheit mit der Linux-Kommandozeile
- Eine E-Mail-Adresse für Benachrichtigungen
- Optional: Ein Slack-Workspace für Slack-Benachrichtigungen
Was sollte überwacht werden
Bevor du irgendwelche Tools einrichtest, ist es wichtig zu verstehen, worauf es für die Server-Zuverlässigkeit ankommt:
Infrastruktur-Metriken
- CPU-Auslastung — dauerhaft über 80% deutet auf Kapazitätsprobleme hin
- RAM-Auslastung — Speichererschöpfung führt zu OOM-Kills und Service-Abstürzen
- Festplattenbelegung — eine volle Festplatte legt Datenbanken, Logging und oft das gesamte System lahm
- Festplatten-I/O — hohe Wartezeiten deuten auf Storage-Engpässe hin
- Netzwerkverkehr — unerwartete Spitzen können auf Angriffe oder Fehlkonfigurationen hinweisen
Anwendungs-Metriken
- HTTP-Statuscodes — auf 5xx-Fehler überwachen
- Antwortzeiten — Performance-Verschlechterung erkennen, bevor Nutzer sich beschweren
- SSL-Zertifikatsablauf — abgelaufene Zertifikate unterbrechen Vertrauen und Zugang
- Docker-Container-Status — abgestürzte oder fehlerhafte Container erkennen
- Service-spezifische Health-Endpoints — Datenbanken, Queues, Caches
Schritt 1: Kostenlose Uptime-Überwachung
Externe Uptime-Monitore prüfen deinen Server von außerhalb deines Netzwerks. Das ist entscheidend, weil internes Monitoring netzwerkbedingte Ausfälle oder Routing-Probleme nicht erkennen kann, die Nutzer daran hindern, deinen Server zu erreichen.
UptimeRobot
UptimeRobot bietet im kostenlosen Plan 50 Monitore mit 5-Minuten-Intervallen.
- Erstelle ein Konto auf uptimerobot.com
- Klicke auf Add New Monitor
- Konfiguriere deinen ersten Monitor:
- Monitor Type: HTTP(s)
- Friendly Name: Mein Server — Hauptseite
- URL:
https://deinedomain.de - Monitoring Interval: 5 Minuten (kostenloser Plan)
Füge weitere Monitore für kritische Endpunkte hinzu:
https://deinedomain.de/api/health— API-Gesundheitscheck- Einen Ping-Monitor für die Server-IP — erkennt Ausfälle auf Netzwerkebene
- Einen Port-Monitor für SSH (22), SMTP (587) oder Datenbank-Ports, falls extern erreichbar
- Einen Keyword-Monitor, der nach bestimmtem Text auf einer Seite sucht — erkennt Fälle, in denen der Server 200 antwortet, aber Fehlerinhalte ausliefert
HetrixTools
HetrixTools bietet im kostenlosen Plan 15 Monitore mit 1-Minuten-Intervallen, plus eingebaute SSL- und Blacklist-Überwachung.
- Erstelle ein Konto auf hetrixtools.com
- Navigiere zu Uptime Monitors und klicke auf Add Monitor
- Wähle Website und gib deine URL ein
- Aktiviere SSL Certificate Monitoring — du wirst 30, 14 und 7 Tage vor Ablauf benachrichtigt
- Füge Monitoring-Standorte auf mehreren Kontinenten hinzu, um Ausfälle besser zu erkennen
Für die SSL-Ablaufüberwachung kannst du Zertifikate auch direkt über die Kommandozeile prüfen:
echo | openssl s_client -servername deinedomain.de -connect deinedomain.de:443 2>/dev/null | openssl x509 -noout -dates
Schritt 2: Prometheus + Grafana mit Docker Compose
Externe Monitore sagen dir, dass etwas ausgefallen ist. Prometheus und Grafana sagen dir warum und helfen dir, Probleme kommen zu sehen.
Verzeichnisstruktur
mkdir -p ~/monitoring/{prometheus,grafana,alertmanager}
cd ~/monitoring
Docker-Compose-Datei
Erstelle docker-compose.yml:
services:
prometheus:
image: prom/prometheus:v2.51.0
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus/alert-rules.yml:/etc/prometheus/alert-rules.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana:10.4.0
container_name: grafana
restart: unless-stopped
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=changeme_s3cure!
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3000:3000"
networks:
- monitoring
node-exporter:
image: prom/node-exporter:v1.7.0
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
networks:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
container_name: cadvisor
restart: unless-stopped
privileged: true
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
ports:
- "8080:8080"
networks:
- monitoring
alertmanager:
image: prom/alertmanager:v0.27.0
container_name: alertmanager
restart: unless-stopped
volumes:
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
networks:
- monitoring
blackbox-exporter:
image: prom/blackbox-exporter:v0.25.0
container_name: blackbox-exporter
restart: unless-stopped
ports:
- "9115:9115"
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge
Prometheus-Konfiguration
Erstelle prometheus/prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- "alert-rules.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'blackbox-http'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://deinedomain.de
- https://api.deinedomain.de/health
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
- job_name: 'blackbox-ssl'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://deinedomain.de
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
Alert-Regeln
Erstelle prometheus/alert-rules.yml:
groups:
- name: server-alerts
rules:
- alert: HoheCpuAuslastung
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "Hohe CPU-Auslastung auf {{ $labels.instance }}"
description: "CPU-Auslastung liegt seit über 5 Minuten über 80% (aktuell: {{ $value | printf \"%.1f\" }}%)"
- alert: HoherSpeicherverbrauch
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Hoher Speicherverbrauch auf {{ $labels.instance }}"
description: "Speicherverbrauch liegt über 85% (aktuell: {{ $value | printf \"%.1f\" }}%)"
- alert: FestplatteKnapp
expr: (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 > 85
for: 5m
labels:
severity: critical
annotations:
summary: "Wenig Festplattenspeicher auf {{ $labels.instance }}"
description: "Root-Dateisystem ist zu {{ $value | printf \"%.1f\" }}% belegt"
- alert: ContainerAusgefallen
expr: absent(container_last_seen{name=~".+"}) or (time() - container_last_seen{name=~".+"}) > 60
for: 1m
labels:
severity: critical
annotations:
summary: "Container {{ $labels.name }} ist ausgefallen"
- alert: EndpunktNichtErreichbar
expr: probe_success == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Endpunkt {{ $labels.instance }} ist nicht erreichbar"
description: "HTTP-Probe schlägt seit über 2 Minuten fehl"
- alert: SslZertifikatLaeuftBaldAb
expr: (probe_ssl_earliest_cert_expiry - time()) / 86400 < 14
for: 1h
labels:
severity: warning
annotations:
summary: "SSL-Zertifikat für {{ $labels.instance }} läuft in {{ $value | printf \"%.0f\" }} Tagen ab"
Stack starten
cd ~/monitoring
docker compose up -d
# Prüfen, ob alle Container laufen
docker compose ps
# Prometheus-Targets prüfen
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, health: .health}'
Öffne Grafana unter http://deine-server-ip:3000, melde dich mit den Zugangsdaten aus der Compose-Datei an und füge Prometheus als Datenquelle mit der URL http://prometheus:9090 hinzu. Importiere Dashboard-ID 1860 (Node Exporter Full) und 14282 (cAdvisor) von grafana.com für fertige Visualisierungen.
Schritt 3: E-Mail- und Slack-Benachrichtigungen
Alertmanager-Konfiguration
Erstelle alertmanager/alertmanager.yml:
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: 'alerts@deinedomain.de'
smtp_auth_username: 'alerts@deinedomain.de'
smtp_auth_password: 'dein-app-passwort'
smtp_require_tls: true
route:
group_by: ['alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'email-slack'
routes:
- match:
severity: critical
receiver: 'email-slack'
repeat_interval: 1h
receivers:
- name: 'email-slack'
email_configs:
- to: 'admin@deinedomain.de'
send_resolved: true
slack_configs:
- api_url: 'https://hooks.slack.com/services/DEIN/SLACK/WEBHOOK'
channel: '#server-alerts'
send_resolved: true
title: '{{ if eq .Status "firing" }}ALARM{{ else }}BEHOBEN{{ end }}: {{ .CommonLabels.alertname }}'
text: '{{ range .Alerts }}{{ .Annotations.description }}
{{ end }}'
Nach dem Erstellen der Datei starte den Alertmanager neu:
docker compose restart alertmanager
Benachrichtigungen testen
Prüfe, ob der Alertmanager Daten von Prometheus empfängt:
# Ausstehende und aktive Alerts prüfen
curl -s http://localhost:9093/api/v2/alerts | jq '.[].labels.alertname'
# Test-Alert senden
curl -X POST http://localhost:9093/api/v2/alerts \
-H "Content-Type: application/json" \
-d '[{"labels":{"alertname":"TestAlert","severity":"warning"},"annotations":{"summary":"Dies ist ein Test-Alert"},"startsAt":"'$(date -u +%Y-%m-%dT%H:%M:%S.000Z)'","generatorURL":"http://localhost:9090"}]'
Schritt 4: Docker Container Health Checks
Docker Health Checks teilen dem Daemon mit, ob ein Container tatsächlich funktioniert — nicht nur, ob er läuft. Füge sie zu deinen Anwendungs-Containern hinzu:
services:
webapp:
image: deine-app:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
database:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
nginx:
image: nginx:alpine
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
Health-Status über die Kommandozeile überwachen:
# Zustand aller Container prüfen
docker ps --format "table {{.Names}}\t{{.Status}}"
# Auf ungesunde Container warten
docker events --filter event=health_status
# Skript zur Benachrichtigung bei ungesunden Containern
#!/bin/bash
unhealthy=$(docker ps --filter health=unhealthy --format "{{.Names}}" 2>/dev/null)
if [ -n "$unhealthy" ]; then
echo "UNGESUNDE Container: $unhealthy" | mail -s "Docker Health Alarm" admin@deinedomain.de
fi
Füge dieses Skript als Fallback zum Cron hinzu, falls dein Haupt-Monitoring selbst ausfällt:
# Alle 5 Minuten ausführen
*/5 * * * * /usr/local/bin/docker-health-check.sh
Schritt 5: Einfache Status-Seite
Eine öffentliche Status-Seite ermöglicht es Nutzern, die Dienstverfügbarkeit zu prüfen, ohne dich kontaktieren zu müssen. Sowohl UptimeRobot als auch HetrixTools bieten kostenlose gehostete Status-Seiten an.
UptimeRobot Status-Seite
- Gehe zu My Settings > Status Pages > Add Status Page
- Wähle die anzuzeigenden Monitore aus
- Passe das Design an dein Branding an
- Nutze die bereitgestellte URL oder richte einen CNAME-Eintrag ein (z.B.
status.deinedomain.de)
Selbst gehostete Alternative: Gatus
Für eine selbst gehostete Status-Seite mit integriertem Monitoring füge Gatus zu deinem Stack hinzu:
gatus:
image: twinproduction/gatus:v5.11.0
container_name: gatus
restart: unless-stopped
volumes:
- ./gatus/config.yaml:/config/config.yaml
ports:
- "8081:8080"
networks:
- monitoring
Erstelle gatus/config.yaml:
storage:
type: sqlite
path: /data/data.db
endpoints:
- name: Website
url: https://deinedomain.de
interval: 2m
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 2000"
alerts:
- type: email
send-on-resolved: true
- name: API
url: https://api.deinedomain.de/health
interval: 1m
conditions:
- "[STATUS] == 200"
- "[BODY].status == UP"
- "[RESPONSE_TIME] < 1000"
- name: SSL-Zertifikat
url: https://deinedomain.de
interval: 1h
conditions:
- "[CERTIFICATE_EXPIRATION] > 14d"
Fehlerbehebung
Prometheus zeigt Targets als DOWN an
# Prüfen, ob Exporter aus dem Docker-Netzwerk erreichbar sind
docker exec prometheus wget -qO- http://node-exporter:9100/metrics | head -5
# Container-Logs prüfen
docker logs node-exporter --tail 20
# Netzwerk-Konnektivität prüfen
docker network inspect monitoring_monitoring
Grafana kann Prometheus nicht erreichen
Beim Hinzufügen der Datenquelle verwende den Docker-Servicenamen http://prometheus:9090, nicht localhost. Beide Container müssen sich im selben Docker-Netzwerk befinden.
Alertmanager sendet keine E-Mails
# Alertmanager-Logs prüfen
docker logs alertmanager --tail 30
# Konfigurationssyntax überprüfen
docker exec alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
# Für Gmail: Verwende ein App-Passwort, nicht dein normales Passwort
# Aktivieren unter https://myaccount.google.com/apppasswords
cAdvisor verbraucht viel CPU
Auf Systemen mit vielen Containern kann cAdvisor erhebliche Ressourcen verbrauchen. Schränke den Erfassungsbereich ein:
cadvisor:
command:
- '--housekeeping_interval=30s'
- '--docker_only=true'
- '--disable_metrics=percpu,sched,tcp,udp,disk,diskIO,hugetlb,referenced_memory'
Festplatte füllt sich durch Prometheus-Daten
# Aktuelle Speichergröße prüfen
du -sh /var/lib/docker/volumes/monitoring_prometheus_data/_data/
# Aufbewahrungsdauer in docker-compose.yml reduzieren
# Ändere: --storage.tsdb.retention.time=30d
# Zu: --storage.tsdb.retention.time=15d
# Prometheus neu starten
docker compose restart prometheus
Vorbeugung und Best Practices
Mehrschichtiger Monitoring-Ansatz
- Externes Uptime-Monitoring (UptimeRobot/HetrixTools) — erkennt Ausfälle, die für Endnutzer sichtbar sind
- Interne Metriken (Prometheus + Grafana) — liefert tiefe Einblicke in Ressourcenverbrauch und Trends
- Container Health Checks — ermöglicht Docker den automatischen Neustart ausgefallener Dienste
- Log-Monitoring — ergänze Loki oder leite Logs weiter, um Fehler auf Anwendungsebene zu erkennen
Alert-Hygiene
- Sende nur dann Benachrichtigungen, wenn menschliches Eingreifen nötig ist. Zu viele Alerts werden ignoriert.
- Nutze
for:-Klauseln in Prometheus-Regeln, um bei kurzen Spitzen nicht zu alarmieren - Setze
repeat_intervalhoch genug, um Alert-Müdigkeit zu vermeiden (4h für Warnungen, 1h für kritische Alerts) - Aktiviere immer
send_resolved: true, damit du weißt, wann ein Problem behoben ist
Sicherheitshinweise
- Stelle Prometheus oder Alertmanager niemals ohne Authentifizierung ins öffentliche Internet
- Betreibe Grafana hinter einem Reverse Proxy mit HTTPS
- Ändere die Standard-Zugangsdaten von Grafana sofort nach der Installation
- Schränke Ports in der Compose-Datei auf
127.0.0.1:9090:9090ein, wenn der Zugriff nur lokal oder über einen Reverse Proxy erfolgt
Wartungsroutine
# Monatlich: Monitoring-Stack aktualisieren
cd ~/monitoring
docker compose pull
docker compose up -d
# Wöchentlich: Festplattenbelegung im Blick behalten
df -h / | tail -1
# Prüfen, ob alle Prometheus-Targets gesund sind
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health != "up") | .labels.job'
Ein gut konfiguriertes Monitoring-Setup macht sich beim ersten Mal bezahlt, wenn es dich um 2 Uhr nachts weckt, anstatt dass deine Nutzer den Ausfall um 9 Uhr morgens entdecken. Starte noch heute mit den kostenlosen externen Tools und erweitere dann schrittweise um Prometheus und Grafana, wenn deine Infrastruktur wächst.
Experten-Hilfe gebraucht?
Monitoring + Alerts richtig einrichten? €49, in 30 Min erledigt.
Jetzt buchen — €49100% Geld-zurück-Garantie