Zabbix: SSL-Zertifikate automatisch überwachen — Komplettanleitung
SSL-Zertifikate mit Zabbix automatisch überwachen. External Scripts, Auto-Discovery über Nginx Proxy Manager und Trigger für ablaufende Zertifikate einrichten.
- Warum SSL-Zertifikate monitoren?
- Voraussetzungen
- Architektur: Wie funktioniert’s?
- External Scripts erstellen
- Zabbix Template konfigurieren
- Nginx Proxy Manager Integration
- Telegram-Alerts einrichten
- Troubleshooting
- Erweiterte Konfiguration
- Best Practices
- 🛒 Empfohlene Tools
- Zusammenfassung
- Weiterführende Links
Abgelaufene SSL-Zertifikate sind der Klassiker unter den Homelab-Pannen: Plötzlich funktioniert nichts mehr, Browser warnen vor Sicherheitsrisiken und im schlimmsten Fall bemerkt man’s erst, wenn der Chef anruft. In diesem Tutorial zeige ich dir, wie du mit Zabbix eine vollautomatische Überwachung aller SSL-Zertifikate einrichtest — inklusive Auto-Discovery über Nginx Proxy Manager, Trigger für 30/14/7-Tage-Warnungen und Telegram-Alerts.
Warum SSL-Zertifikate monitoren?#
Let’s Encrypt hat uns kostenlose SSL-Zertifikate gebracht — aber sie laufen nach 90 Tagen ab. Wenn dein Certbot-Renewal aus irgendeinem Grund fehlschlägt (falsche DNS-Einträge, Rate-Limits, fehlende Permissions), merkst du’s oft erst, wenn’s zu spät ist.
Die typischen Probleme:
- Let’s Encrypt Zertifikate: Laufen nach 90 Tagen ab, Renewal kann fehlschlagen
- Wildcard-Zertifikate: Besonders kritisch, weil sie oft mehrere Services betreffen
- Vergessene Subdomains: Du hast eine Domain mal für ein Projekt angelegt und vergessen
- Externe Services: APIs, Webhooks oder Integrationen die auf gültige Zerts angewiesen sind
Genau hier setzt unser Zabbix SSL-Monitoring an: Alle Domains werden automatisch erkannt, geprüft und du bekommst rechtzeitig Bescheid bevor’s kritisch wird.
Voraussetzungen#
Bevor wir loslegen, stelle sicher dass du folgendes hast:
- Zabbix Server (mindestens Version 6.0, besser 7.x)
- Nginx Proxy Manager (optional, für Auto-Discovery)
- Root-Zugriff auf deinen Zabbix-Server
- Grundwissen Zabbix: Wenn du Zabbix noch nicht kennst, lies zuerst meinen Zabbix Monitoring Homelab Einsteiger-Guide
Architektur: Wie funktioniert’s?#
Unser Setup besteht aus drei Komponenten:
- Discovery-Script (
discover_ssl_domains.sh): Liest alle Domains aus Nginx Proxy Manager SQLite DB - Check-Script (
check_ssl.sh): Prüft ein einzelnes Zertifikat und gibt die verbleibenden Tage zurück - Zabbix Template: Nutzt die Scripts für Auto-Discovery und Item-Generierung
Der Workflow:
Nginx Proxy Manager DB → Discovery Script → Zabbix LLD → Items pro Domain → Trigger bei <30/14/7 Tagen
External Scripts erstellen#
Zabbix External Scripts liegen unter /usr/lib/zabbix/externalscripts/ (Debian/Ubuntu) oder /usr/lib64/zabbix/externalscripts/ (RHEL/CentOS). Die Scripts müssen:
- Ausführbar sein (
chmod +x) - Dem Zabbix-User gehören oder von ihm lesbar sein
- Ergebnisse auf STDOUT ausgeben
Script 1: Discovery Script#
Erstelle /usr/lib/zabbix/externalscripts/discover_ssl_domains.sh:
#!/bin/bash
# discover_ssl_domains.sh - Liest alle Domains aus Nginx Proxy Manager SQLite DB
NPM_DB="/opt/nginxproxymanager/data/database.sqlite"
# Prüfe ob DB existiert
if [ ! -f "$NPM_DB" ]; then
echo ''
exit 0
fi
# Lese alle Domains aus der DB
DOMAINS=$(sqlite3 "$NPM_DB" "SELECT DISTINCT domain_names FROM proxy_host;" 2>/dev/null | tr ',' '\n' | sort -u)
# Baue JSON für Zabbix LLD
echo -n '{"data":['
FIRST=1
for DOMAIN in $DOMAINS; do
# Überspringe leere Zeilen und Wildcards
if [ -z "$DOMAIN" ] || [[ "$DOMAIN" == *"*"* ]]; then
continue
fi
if [ $FIRST -eq 1 ]; then
FIRST=0
else
echo -n ","
fi
echo -n "{
\"\":\"$DOMAIN\",
\"\":\"443\"
}"
done
echo ']}'
Hinweis: Wenn du Nginx Proxy Manager nicht verwendest, kannst du die Domains auch aus einer statischen Liste laden:
#!/bin/bash
# Alternative: Statische Domainliste
DOMAINS=(
"example.com"
"mail.example.com"
"cloud.example.com"
)
echo -n '{"data":['
FIRST=1
for DOMAIN in "$"; do
if [ $FIRST -eq 1 ]; then
FIRST=0
else
echo -n ","
fi
echo -n "{
\"\":\"$DOMAIN\",
\"\":\"443\"
}"
done
echo ']}'
Script 2: SSL Check Script#
Erstelle /usr/lib/zabbix/externalscripts/check_ssl.sh:
#!/bin/bash
# check_ssl.sh - Prüft SSL-Zertifikat und gibt verbleibende Tage zurück
DOMAIN="$1"
PORT="$"
if [ -z "$DOMAIN" ]; then
echo "ERROR: No domain specified"
exit 1
fi
# Hole Zertifikat und extrahiere Ablaufdatum
EXPIRY=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:$PORT" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | \
cut -d= -f2)
if [ -z "$EXPIRY" ]; then
echo "ERROR: Could not retrieve certificate for $DOMAIN:$PORT"
exit 1
fi
# Konvertiere zu Unix Timestamp
EXPIRY_TIMESTAMP=$(date -d "$EXPIRY" +%s 2>/dev/null)
NOW_TIMESTAMP=$(date +%s)
# Berechne verbleibende Tage
DAYS_LEFT=$(( ($EXPIRY_TIMESTAMP - $NOW_TIMESTAMP) / 86400 ))
echo "$DAYS_LEFT"
Scripts installieren#
# Scripts erstellen
cd /usr/lib/zabbix/externalscripts/
sudo vim discover_ssl_domains.sh # Inhalt einfügen
sudo vim check_ssl.sh # Inhalt einfügen
# Ausführbar machen
sudo chmod +x discover_ssl_domains.sh check_ssl.sh
# Owner setzen
sudo chown zabbix:zabbix discover_ssl_domains.sh check_ssl.sh
# Testen
sudo -u zabbix ./discover_ssl_domains.sh
sudo -u zabbix ./check_ssl.sh example.com 443
Expected Output Discovery:
{"data":[
":"example.com","":"443"},
":"mail.example.com","":"443"}
]}
Expected Output Check:
67
(Zahl = Tage bis Ablauf)
Zabbix Template konfigurieren#
Jetzt erstellen wir das Zabbix Template mit Low-Level Discovery.
Discovery Rule erstellen#
Configuration → Templates → Create template
- Template name:
Template SSL Certificate Monitoring - Groups:
Templates/Applications
- Template name:
Discovery rules → Create discovery rule
- Name:
SSL Domain Discovery - Type:
External check - Key:
discover_ssl_domains.sh - Update interval:
1h
- Name:
Item Prototype erstellen#
In der Discovery Rule → Item prototypes → Create item prototype:
- Name:
SSL Certificate Expiry: - Type:
External check - Key:
check_ssl.sh[,] - Type of information:
Numeric (unsigned) - Units:
days - Update interval:
12h - History storage period:
90d - Trend storage period:
365d
Beschreibung: Days until SSL certificate expires for
Trigger Prototypes erstellen#
Jetzt kommen die Trigger die uns warnen wenn’s brenzlig wird:
Trigger 1: Critical (7 Tage)#
Name:
SSL Certificate expires in less than 7 days:Expression:
last(/Template SSL Certificate Monitoring/check_ssl.sh[,])<7Severity:
HighDescription:
The SSL certificate for will expire in days! Action required: Renew certificate immediately.
Trigger 2: Warning (14 Tage)#
Name:
SSL Certificate expires in less than 14 days:Expression:
last(/Template SSL Certificate Monitoring/check_ssl.sh[,])<14Severity:
WarningManual close: Yes
Description:
The SSL certificate for will expire in days. Please check renewal process.
Trigger 3: Information (30 Tage)#
Name:
SSL Certificate expires in less than 30 days:Expression:
last(/Template SSL Certificate Monitoring/check_ssl.sh[,])<30Severity:
InformationManual close: Yes
Description:
The SSL certificate for will expire in days.
Tipp: Die Schwellwerte kannst du über Macros flexibel machen:
= 7
= 14
= 30
Dann in der Expression: last(...)<
Host zuweisen#
- Configuration → Hosts
- Host auswählen (z.B. deinen Zabbix Server)
- Templates → Link new templates
Template SSL Certificate Monitoringauswählen- Update
Nach spätestens 1 Stunde (Discovery-Intervall) sollten die ersten Items auftauchen:
Monitoring → Latest data → Filter: Host = [Your Host]
Du solltest nun für jede entdeckte Domain ein Item sehen mit dem aktuellen Wert (Tage bis Ablauf).
Nginx Proxy Manager Integration#
Wenn du Nginx Proxy Manager verwendest, ist die Auto-Discovery besonders elegant: Jede neue Proxy Host wird automatisch ins Monitoring aufgenommen.
NPM SQLite DB Zugriff#
Nginx Proxy Manager speichert alle Domains in /opt/nginxproxymanager/data/database.sqlite. Unser Discovery-Script liest direkt daraus:
SELECT DISTINCT domain_names FROM proxy_host;
Beispiel-Output:
cloud.example.com
mail.example.com,webmail.example.com
git.example.com
Das Script splittet Mehrfach-Domains am Komma und erstellt für jede einen eigenen Discovery-Eintrag.
Permissions prüfen#
# Zabbix-User muss die DB lesen können
sudo chmod 644 /opt/nginxproxymanager/data/database.sqlite
sudo chown npmuser:zabbix /opt/nginxproxymanager/data/database.sqlite
Alternativ kannst du einen Cronjob einrichten der die Domains periodisch exportiert:
# /etc/cron.hourly/export-npm-domains
#!/bin/bash
sqlite3 /opt/nginxproxymanager/data/database.sqlite \
"SELECT DISTINCT domain_names FROM proxy_host;" > /tmp/npm_domains.txt
chmod 644 /tmp/npm_domains.txt
Telegram-Alerts einrichten#
Damit du auch unterwegs Bescheid bekommst wenn ein Zertifikat abläuft, richten wir Telegram-Benachrichtigungen ein:
1. Telegram Bot erstellen#
- Schreibe @BotFather auf Telegram
/newbot→ Namen vergeben- API Token kopieren (z.B.
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
2. Chat ID herausfinden#
# Sende dir selbst eine Nachricht über den Bot, dann:
curl https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
Kopiere die chat_id aus der Response.
3. Media Type in Zabbix konfigurieren#
- Administration → Media types → Telegram
- Token: Dein Bot-Token
- Test mit deiner Chat-ID
4. User-Media einrichten#
- Administration → Users → [Dein User]
- Media → Add
- Type:
Telegram - Send to: Deine Chat-ID
- Severity: Alle aktivieren
5. Action erstellen#
Configuration → Actions → Trigger actions → Create action:
- Name:
SSL Certificate Expiry Notification - Conditions:
- Trigger severity >=
Warning - Trigger name contains
SSL Certificate
- Trigger severity >=
- Operations:
Send message to user:
[Dein User]Message template:
🔒 SSL Alert: Host: Domain: Days left: Severity: Time:
Jetzt bekommst du Telegram-Nachrichten sobald ein Zertifikat die Schwellwerte unterschreitet!
Troubleshooting#
“ERROR: Could not retrieve certificate”#
Mögliche Ursachen:
- Domain ist nicht erreichbar (DNS, Firewall)
- Port ist falsch (nicht 443)
- SNI (Server Name Indication) fehlt
Lösung: Prüfe manuell:
openssl s_client -servername example.com -connect example.com:443 < /dev/null
Discovery findet keine Domains#
Prüfen:
sudo -u zabbix /usr/lib/zabbix/externalscripts/discover_ssl_domains.sh
Häufige Fehler:
- NPM DB-Pfad falsch (prüfe
/opt/nginxproxymanager/data/database.sqlite) - Permissions fehlen (
chmod 644) - SQLite3 nicht installiert (
apt install sqlite3)
Items werden nicht erstellt#
- Discovery Rule ausführen: Configuration → Hosts → Discovery → “Execute now”
- Logs prüfen:
tail -f /var/log/zabbix/zabbix_server.log - Script-Output testen: External scripts müssen valides JSON zurückgeben
Zabbix Agent vs External Scripts#
Häufige Verwechslung: External Scripts laufen auf dem Zabbix Server, nicht auf dem Agent! Der Zabbix Server führt das Script aus und kontaktiert die Zieldomains direkt.
Das bedeutet:
- Keine Agent-Installation auf dem Ziel nötig
- Zabbix Server braucht Outbound-Zugriff auf Port 443
- Scripts müssen auf dem Zabbix Server liegen
False Positives bei Wildcard-Zertifikaten#
Wenn du Wildcard-Zertifikate (*.example.com) verwendest, können Subdomains mehrfach gemessen werden.
Lösung: Filter im Discovery-Script:
# Überspringe Domains die von Wildcard abgedeckt sind
if [[ "$DOMAIN" == *.example.com ]]; then
continue
fi
Oder: Prüfe nur das Wildcard-Zertifikat direkt.
Erweiterte Konfiguration#
Multi-Port Monitoring#
Wenn du Services auf anderen Ports überwachst (z.B. SMTPS 465, IMAPS 993):
Im Discovery-Script:
echo -n "{
\"\":\"mail.example.com\",
\"\":\"465\",
\"\":\"SMTPS\"
}"
Item-Key: check_ssl.sh[,]
Subject Alternative Names (SAN) prüfen#
Manche Zertifikate decken mehrere Domains ab (SAN). Um alle zu erfassen:
#!/bin/bash
# check_ssl_san.sh - Extrahiert alle SANs
DOMAIN="$1"
openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | \
openssl x509 -noout -text | \
grep -A1 "Subject Alternative Name" | \
tail -n1 | \
sed 's/DNS://g' | \
tr ',' '\n'
Zertifikat-Aussteller überwachen#
Prüfe ob das Zertifikat von Let’s Encrypt kommt:
ISSUER=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:$PORT" 2>/dev/null | \
openssl x509 -noout -issuer | \
grep -o "Let's Encrypt")
if [ -z "$ISSUER" ]; then
echo "0" # Nicht Let's Encrypt
else
echo "1" # Let's Encrypt
fi
Best Practices#
Update-Intervalle:
- Discovery:
1h(findet neue Domains schnell) - Items:
12h(Zertifikate ändern sich selten)
- Discovery:
History & Trends:
- History:
90d(3 Let’s Encrypt Zyklen) - Trends:
365d(Jahresübersicht)
- History:
Trigger-Schwellwerte:
- 30 Tage: Information (frühe Vorwarnung)
- 14 Tage: Warning (Zeit zum Handeln)
- 7 Tage: High (kritisch, sofort reagieren)
Dependencies:
- Setze Dependencies auf Host-Erreichbarkeit
- Verhindert Alert-Spam bei Netzwerkausfall
Maintenance Windows:
- Plane Maintenance während Zertifikat-Renewals
- Verhindert False-Positives während Renewal-Prozess
🛒 Empfohlene Tools#
📊
Zabbix Monitoring Kit
Fertige Templates und Dashboards für SSL-Monitoring, Proxmox, Docker und mehr. Sofort einsatzbereit in deinem Zabbix. Monitoring Kit holen → 🖥️
Hetzner Cloud
Dedizierten Monitoring-Server betreiben? Hetzner Cloud ab 4€/Monat. Hetzner ausprobieren →
Zusammenfassung#
Mit diesem Setup hast du ein vollautomatisches SSL-Zertifikat-Monitoring das:
✅ Alle Domains automatisch erkennt (via NPM oder statische Liste)
✅ Ablaufdaten täglich prüft
✅ Dich rechtzeitig warnt (30/14/7 Tage)
✅ Via Telegram Bescheid gibt
✅ Komplett wartungsfrei läuft
Nie wieder abgelaufene Zertifikate — dein Homelab dankt’s dir, deine User auch.
Weiterführende Links#
- Zabbix Monitoring Homelab Einsteiger-Guide
- Nginx Reverse Proxy Homelab
- Zabbix Dokumentation: External checks
- Let’s Encrypt: Certificate Lifecycle
Fragen oder Probleme? Schreib mir oder hinterlasse einen Kommentar!
Update 2026-02-08: Nginx Proxy Manager Integration und Telegram-Alerts hinzugefügt.
Einige Links auf dieser Seite sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision — für dich ändert sich am Preis nichts. So unterstützt du diesen Blog und ermöglichst weitere kostenlose Tutorials. Danke! 🙏
[« Vorherige]
UniFi WLAN optimieren: Kanäle, Sendeleistung und Band Steering richtig einstellen