Zuletzt aktualisiert: 29.10.2026 · Lesezeit: 15-20 Minuten
n8n installieren, mit Icinga verbinden und die ersten Alarme in Microsoft Teams sehen: Das schaffst du auf Ubuntu 26.04 an einem Nachmittag. Danach meldet dein Monitoring jeden Statuswechsel sofort im Teams-Kanal, schickt werktags einen Statusbericht und warnt dich rechtzeitig vor ablaufenden Zertifikaten.
Die wichtigsten Punkte in 30 Sekunden
- n8n läuft per Docker Compose in drei Containern: n8n, PostgreSQL 17 und ein Task Runner für Code-Nodes. MySQL und MariaDB unterstützt n8n seit Version 2.0 nicht mehr.
- n8n liest Hosts und Services über die Icinga-REST-API mit einem eigenen API-Benutzer, der Probleme bestätigen und Downtimes setzen, aber keine Konfiguration ändern darf.
- Bei jedem Statuswechsel ruft Icinga ein Skript auf, das einen abgesicherten n8n-Webhook anstößt. n8n postet die Meldung über die Teams-App „Workflows“ in deinen Kanal.
- Dazu kommen ein werktäglicher Statusbericht und ein Zertifikats-Wochenbericht.
- Vor dem Produktivbetrieb fehlen noch HTTPS über einen Reverse Proxy und eine Kopie der Backups auf einem zweiten System.
Was ist n8n?
n8n ist eine Plattform zur Workflow-Automatisierung. Abläufe setzt du im Browser aus Bausteinen, sogenannten Nodes, zusammen, etwa „Webhook empfangen“, „HTTP-Anfrage senden“ oder „Code ausführen“. n8n lässt sich selbst hosten, sodass Daten wie Hostnamen und Alarmtexte dein Netzwerk nicht verlassen.
Vorraussetzungen für die Installation
- Ein Server mit Ubuntu 26.04 und root- oder sudo-Rechten
- Eine laufende Icinga-2-Instanz, in dieser Anleitung auf demselben Server
- Ein Microsoft-Teams-Kanal, in dem du über die App „Workflows“ einen Webhook anlegen darfst
- In den Befehlen steht für die IP-Adresse deines Servers im LAN und Training für seinen Hostnamen, ersetze beides durch deine eigenen Werte
n8n installieren: Schritt für Schritt
In den ersten vier Schritten richtest du Docker ein, legst die Konfiguration an und startest n8n. Wechsle dafür mit sudo -i in eine Root-Shell.
Schritt 1: Docker installieren
Installiere Docker und das Compose-Plugin aus dem offiziellen Docker-Repository:
Installiere Docker und das Compose-Plugin aus dem offiziellen Docker-Repository:
Bash
apt update && apt install -y ca-certificates curl jq
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-pluginDas Werkzeug jq brauchst du später für das Benachrichtigungsskript in Icinga.
Schritt 2: Projektverzeichnis und Secrets anlegen
Alle Dateien liegen unter /opt/n8n. Lege das Verzeichnis an und kopiere direkt das CA-Zertifikat von Icinga hinein, damit n8n die Verbindung zur Icinga-API später sauber prüfen kann:
mkdir -p /opt/n8n/certs && cd /opt/n8n
cp /var/lib/icinga2/certs/ca.crt certs/icinga-ca.crt
chmod 644 certs/icinga-ca.crtErstelle anschließend die Datei .env mit Platzhaltern:
cat > .env << 'EOF'
N8N_VERSION=CHANGE_ME_VERSION
N8N_HOST=CHANGE_ME_IP
POSTGRES_USER=n8n
POSTGRES_DB=n8n
POSTGRES_PASSWORD=CHANGE_ME_DB
N8N_ENCRYPTION_KEY=CHANGE_ME_KEY
N8N_RUNNERS_AUTH_TOKEN=CHANGE_ME_TOKEN
EOF
chmod 600 .envDie Platzhalter musst du nicht von Hand ausfüllen. Führe die folgenden Befehle unverändert aus: Sie erzeugen Passwort, Encryption Key und Token als Zufallswerte, tragen die IP deines Servers ein und ermitteln die aktuelle stabile n8n-Version:
sed -i "s/CHANGE_ME_DB/$(openssl rand -hex 24)/" .env
sed -i "s/CHANGE_ME_KEY/$(openssl rand -hex 32)/" .env
sed -i "s/CHANGE_ME_TOKEN/$(openssl rand -hex 32)/" .env
sed -i "s/CHANGE_ME_IP/$(hostname -I | awk '{print $1}')/" .env
docker pull n8nio/n8n:stable
sed -i "s/CHANGE_ME_VERSION/$(docker run --rm n8nio/n8n:stable --version)/" .env
Mit cat .env prüfst du das Ergebnis. Statt der Platzhalter stehen dort jetzt echte Werte. Hat dein Server mehrere Netzwerkkarten, kontrolliere bei N8N_HOST, ob die richtige IP eingetragen wurde, und korrigiere sie gegebenenfalls mit einem Editor.
Wichtig: Kopiere den Wert von N8N_ENCRYPTION_KEY in deinen Passwortmanager. Mit diesem Schlüssel verschlüsselt n8n alle gespeicherten Zugangsdaten. Geht er verloren, sind sie nach einer Neuinstallation unbrauchbar.
Warum eine feste Version? n8n und der Task Runner müssen exakt dieselbe Version haben. Über die Variable N8N_VERSION aktualisierst du später beide Container mit einer einzigen Zeile.
Schritt 3: docker-compose.yml erstellen
Die Umgebung besteht aus drei Containern: n8n selbst, PostgreSQL als Datenbank und dem Task Runner, der Code aus Code-Nodes isoliert ausführt. Lege die Datei /opt/n8n/docker-compose.yml an:
services:
postgres:
image: postgres:17
container_name: n8n-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
n8n:
image: n8nio/n8n:${N8N_VERSION}
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
extra_hosts:
- "training:<server-ip>"
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_HOST: ${N8N_HOST}
N8N_PORT: 5678
N8N_PROTOCOL: http
WEBHOOK_URL: http://${N8N_HOST}:5678/
N8N_SECURE_COOKIE: "false"
GENERIC_TIMEZONE: Europe/Berlin
TZ: Europe/Berlin
N8N_RUNNERS_MODE: external
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 336
N8N_DIAGNOSTICS_ENABLED: "false"
NODE_EXTRA_CA_CERTS: /certs/icinga-ca.crt
volumes:
- n8n_data:/home/node/.n8n
- ./certs:/certs:ro
depends_on:
postgres:
condition: service_healthy
task-runners:
image: n8nio/runners:${N8N_VERSION}
container_name: n8n-runners
restart: unless-stopped
environment:
N8N_RUNNERS_TASK_BROKER_URI: http://n8n:5679
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
depends_on:
- n8n
volumes:
postgres_data:
n8n_data:Kurz zu den wichtigsten Einstellungen:
- postgres:17 ist die Datenbank. Seit n8n 2.0 unterstützt n8n nur noch PostgreSQL und SQLite, MySQL und MariaDB nicht mehr.
- N8N_RUNNERS_MODE: external lässt Code-Nodes im eigenen Container task-runners laufen. Das ist in n8n 2.x der empfohlene Betrieb.
- N8N_SECURE_COOKIE: „false“ erlaubt den Login über HTTP. Das ist nur für den Betrieb im internen Netz gedacht, bis HTTPS eingerichtet ist.
- extra_hosts und NODE_EXTRA_CA_CERTS sorgen dafür, dass n8n Icinga unter seinem Hostnamen erreicht und dessen Zertifikat vertraut. Der Hostname muss dem Namen im Icinga-Zertifikat entsprechen, den dir openssl x509 -in /var/lib/icinga2/certs/$(hostname).crt -noout -subject anzeigt.
- EXECUTIONS_DATA_PRUNE löscht Ausführungsdaten nach 336 Stunden, also 14 Tagen.
Schritt 4: n8n starten
Prüfe die Datei und starte die Container:
docker compose config --quiet && docker compose up -d
docker compose psAlle drei Container sollten den Status running haben. Rufe dann im Browser http://deine-IP-Addresse:5678 auf und lege dein Owner-Konto an. Den anschließenden Dialog zum KI-Assistenten kannst du schließen, n8n funktioniert ohne ihn.
Ob der Task Runner arbeitet, testest du mit einem neuen Workflow: Füge einen Code-Node mit
return [{ json: { test: „ok“ } }];
hinzu und führe ihn aus. Erscheint ok in der Ausgabe, ist die Installation vollständig.

Icinga anbinden
n8n liest Hosts und Services über die REST-API von Icinga auf Port 5665. Dafür bekommt n8n einen eigenen API-Benutzer.
Schritt 5: API-Benutzer für n8n anlegen
Prüfe zuerst, ob die API aktiv ist. In der Ausgabe muss api unter Enabled stehen:
icinga2 feature listFalls nicht, aktivierst du sie mit icinga2 api setup und startest Icinga anschließend mit systemctl restart icinga2 neu.
Erzeuge dann ein Passwort und lege den Benutzer an. Notiere dir das Passwort, du brauchst es in Schritt 6:
PW=$(openssl rand -hex 20) && echo "$PW"cat >> /etc/icinga2/conf.d/api-users.conf << EOF
object ApiUser "n8n" {
password = "$PW"
permissions = [
"status/query",
"objects/query/Host",
"objects/query/Service",
"actions/acknowledge-problem",
"actions/remove-acknowledgement",
"actions/schedule-downtime",
"actions/remove-downtime"
]
}
EOFDer Benutzer darf Hosts und Services lesen, Probleme bestätigen und Downtimes setzen, aber keine Konfiguration ändern. Prüfe die Konfiguration und lade Icinga neu:
icinga2 daemon -C && systemctl reload icinga2Mit dem nächsten Aufruf testest du den Zugang inklusive Zertifikatsprüfung. Kommt JSON zurück, ist alles bereit:
curl -s --cacert /var/lib/icinga2/certs/ca.crt -u "n8n:$PW" https://training:5665/v1/status | head -c 300Schritt 6: Zugangsdaten in n8n hinterlegen
Öffne in n8n den Bereich Credentials und lege neue Zugangsdaten vom Typ Basic Auth an. Als User trägst du n8n ein, als Passwort den Wert aus Schritt 5. Nenne die Credential Icinga API und speichere sie.
n8n verschlüsselt das Passwort mit dem Encryption Key. In den Workflows taucht es nirgends im Klartext auf.

Echtzeit Alarme an Microsoft Teams senden
Bei jedem Statuswechsel ruft Icinga ein Skript auf. Das Skript schickt die Daten an einen Webhook in n8n, und n8n postet daraus eine Nachricht in deinen Teams-Kanal. So kommen Alarme sofort an, ohne doppelte Meldungen, und auch Entwarnungen werden gemeldet.
Schritt 7: Webhook in Microsoft Teams anlegen
Öffne in Teams den Kanal für die Alarme, klicke auf die drei Punkte neben dem Kanalnamen und wähle Workflows. Suche nach der Vorlage „Webhook-Benachrichtigungen an einen Kanal senden“, vergib einen Namen wie n8n Icinga-Alarme und bestätige Team und Kanal. Am Ende zeigt Teams eine lange URL an, die du kopierst.
Warum Workflows? Die klassischen Incoming-Webhook-Connectors in Teams werden von Microsoft abgekündigt. Die Workflows-App ist der aktuelle Weg. Behandle die URL wie ein Passwort, denn wer sie kennt, kann in deinen Kanal posten.
Schritt 8: Alarm Workflow in n8n bauen
Erzeuge zuerst einen Token, mit dem du den Webhook absicherst, und notiere ihn:
openssl rand -hex 24Lege in n8n einen neuen Workflow Icinga Alarme an und füge als ersten Node einen Webhook hinzu:
- HTTP Method: POST
- Path: icinga-alarm
- Authentication: Header Auth, mit neuen Zugangsdaten: Name X-Icinga-Token, Value dein Token
- Respond: Immediately
Hänge einen HTTP Request-Node an. Stelle Method auf POST, trage als URL die Teams-URL aus Schritt 7 ein, aktiviere Send Body und wähle als Body Content Type JSON mit Using JSON:
{
"type": "message",
"attachments": [{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"wrap": true,
"color": "{{ ({CRITICAL: 'Attention', DOWN: 'Attention', WARNING: 'Warning', UNREACHABLE: 'Warning', OK: 'Good', UP: 'Good'})[$json.body.state] || 'Accent' }}",
"text": "{{ $json.body.state }}: {{ $json.body.service ? $json.body.service + ' auf ' + $json.body.host : 'Host ' + $json.body.host }} ({{ $json.body.type }})"
},
{
"type": "FactSet",
"facts": [
{ "title": "Host", "value": "{{ $json.body.host }}" },
{ "title": "Service", "value": "{{ $json.body.service || 'Host-Alarm' }}" },
{ "title": "Ausgabe", "value": {{ JSON.stringify($json.body.output) }} },
{ "title": "Zeit", "value": "{{ $json.body.time }}" }
]
}
]
}
}]
}Die Überschrift wird bei CRITICAL und DOWN rot, bei WARNING gelb und bei OK und UP grün. Die Prüfausgabe läuft über JSON.stringify, weil Anführungszeichen in der Ausgabe sonst das JSON zerstören würden.
Speichere den Workflow und aktiviere ihn oben rechts. Ab jetzt ist der Webhook dauerhaft unter der
Production URL http://deine-IP-Addresse:5678/webhook/icinga-alarm erreichbar.
Schritt 9: Benachrichtigungsskript in Icinga anlegen
Das Skript verpackt die Daten von Icinga mit jq als JSON und schickt sie an n8n:
cat > /etc/icinga2/scripts/n8n-notify.sh << 'EOF'
#!/bin/bash
# Sendet Icinga-Benachrichtigungen an den n8n-Webhook
N8N_URL="http://deine-IP-Addresse:5678/webhook/icinga-alarm"
N8N_TOKEN="Dein_TOKEN"
payload=$(jq -n \
--arg type "$N8N_TYPE" \
--arg host "$N8N_HOST" \
--arg service "$N8N_SERVICE" \
--arg state "$N8N_STATE" \
--arg output "$N8N_OUTPUT" \
--arg time "$N8N_TIME" \
'{type: $type, host: $host, service: $service, state: $state, output: $output, time: $time}')
curl -sS --fail -m 10 -X POST "$N8N_URL" \
-H "Content-Type: application/json" \
-H "X-Icinga-Token: $N8N_TOKEN" \
-d "$payload"
EOFTrage die IP deines Servers und deinen Token ein und schränke die Rechte ein, denn das Skript enthält den Token:
Bash
sed -i "s/deine-IP-Addresse/$(hostname -I | awk '{print $1}')/" /etc/icinga2/scripts/n8n-notify.sh
sed -i 's/Dein_TOKEN/hier-dein-token/' /etc/icinga2/scripts/n8n-notify.sh
chown root:nagios /etc/icinga2/scripts/n8n-notify.sh
chmod 750 /etc/icinga2/scripts/n8n-notify.shTeste das Skript genau so, wie Icinga es aufrufen wird. Kommt {„message“:“Workflow was started“} zurück, erscheint die Testmeldung in Teams:
sudo -u nagios env N8N_TYPE=PROBLEM N8N_HOST=testhost N8N_SERVICE=test \
N8N_STATE=CRITICAL N8N_OUTPUT="Testmeldung" N8N_TIME="$(date)" \
/etc/icinga2/scripts/n8n-notify.shSchritt 10: Benachrichtigungsregeln anlegen
Icinga braucht jetzt zwei Befehle (für Services und für Hosts), einen Benutzer als Empfänger und zwei Regeln:
cat > /etc/icinga2/conf.d/n8n-notification.conf << 'EOF'
object NotificationCommand "n8n-webhook" {
command = [ ConfigDir + "/scripts/n8n-notify.sh" ]
env = {
N8N_TYPE = "$notification.type$"
N8N_HOST = "$host.name$"
N8N_SERVICE = "$service.display_name$"
N8N_STATE = "$service.state$"
N8N_OUTPUT = "$service.output$"
N8N_TIME = "$icinga.long_date_time$"
}
}
object NotificationCommand "n8n-webhook-host" {
command = [ ConfigDir + "/scripts/n8n-notify.sh" ]
env = {
N8N_TYPE = "$notification.type$"
N8N_HOST = "$host.name$"
N8N_SERVICE = ""
N8N_STATE = "$host.state$"
N8N_OUTPUT = "$host.output$"
N8N_TIME = "$icinga.long_date_time$"
}
}
object User "n8n-webhook" {
display_name = "n8n Webhook"
}
apply Notification "n8n-service" to Service {
command = "n8n-webhook"
users = [ "n8n-webhook" ]
interval = 0
assign where true
ignore where host.vars.n8n_alarm == false || service.vars.n8n_alarm == false
}
apply Notification "n8n-host" to Host {
command = "n8n-webhook-host"
users = [ "n8n-webhook" ]
interval = 0
assign where true
ignore where host.vars.n8n_alarm == false
}
EOFGut zu wissen:
- interval = 0 schickt pro Problem genau eine Meldung statt regelmäßiger Erinnerungen.
- assign where true gilt für alle Hosts und Services, auch für künftige.
- ignore where nimmt Hosts oder Services aus, bei denen du vars.n8n_alarm = false setzt
Prüfe als Nächstes, wie Icinga seine Konfiguration einbindet:
grep -n "conf.d" /etc/icinga2/icinga2.confIst include_recursive „conf.d“ aktiv, wird die neue Datei automatisch geladen. Ist die Zeile auskommentiert, was bei Installationen mit Director und Icinga DB üblich ist, bindest du die Datei gezielt ein:
grep -q 'conf.d/n8n-notification.conf' /etc/icinga2/icinga2.conf || \
echo 'include "conf.d/n8n-notification.conf"' >> /etc/icinga2/icinga2.confPrüfe die Konfiguration und starte Icinga neu:
icinga2 daemon -C && systemctl restart icinga2Schritt 11: Alamierung testen
Zum Testen eignet sich ein Host mit dem Check dummy, der einen festgelegten Status zurückgibt:
cat > /etc/icinga2/conf.d/n8n-test.conf << 'EOF'
object Host "n8n-testhost" {
check_command = "dummy"
vars.dummy_state = 0
vars.dummy_text = "Testhost erreichbar"
}
object Service "test-critical" {
host_name = "n8n-testhost"
check_command = "dummy"
check_interval = 1m
vars.dummy_state = 2
vars.dummy_text = "Webserver antwortet nicht (simuliert)"
}
EOFgrep -q 'conf.d/n8n-test.conf' /etc/icinga2/icinga2.conf || \
echo 'include "conf.d/n8n-test.conf"' >> /etc/icinga2/icinga2.conficinga2 daemon -C && systemctl restart icinga2Icinga meldet ein Problem erst, wenn es nach mehreren Prüfversuchen bestätigt ist.
Nach etwa drei Minuten erscheint in Teams eine rote Meldung zu test-critical. Setzt du vars.dummy_state auf 0 und startest Icinga neu, folgt kurz darauf die grüne Entwarnung.
Ist ein Host ausgefallen, unterdrückt Icinga übrigens die Meldungen seiner Services. Ein Serverausfall erzeugt so eine einzige Nachricht statt vieler. Wenn alles funktioniert, entfernst du den Testhost wieder:
sed -i '/conf.d\/n8n-test.conf/d' /etc/icinga2/icinga2.conf
rm /etc/icinga2/conf.d/n8n-test.conf
icinga2 daemon -C && systemctl restart icinga2n8n mit Unterstützung einführen?
Ob Anbindung an dein Ticketsystem, kundenspezifische Alarmierung oder Betrieb im Cluster: Unsere Consultants helfen dir, n8n sauber in deine Infrastruktur zu integrieren.
kostenlose Erstberatung →
Berichte nach Zeitplan
Neben den Echtzeit-Alarmen liefert n8n zwei regelmäßige Berichte in denselben Teams-Kanal: werktags eine Übersicht aller offenen Probleme und montags einen Überblick über ablaufende Zertifikate.
Schritt 12: Täglichen Statusbericht einrichten
Lege einen neuen Workflow Icinga Statusbericht an. Als Trigger dient ein Schedule Trigger mit Trigger Interval „Custom (Cron)“ und dieser Expression für Montag bis Freitag um 7 Uhr:

Hänge einen HTTP Request-Node an, der Icinga abfragt:
- Method: POST
- URL: https://training:5665/v1/objects/services
- Authentication: Generic Credential Type, Basic Auth, Credential Icinga API
- Send Headers: Accept mit application/json und X-HTTP-Method-Override mit GET
- Send Body: JSON, Using JSON, mit diesem Inhalt:
{
"filter": "service.state != 0 && service.acknowledgement == 0",
"attrs": ["display_name", "host_name", "state", "last_check_result"]
}

Warum POST mit GET-Header? Icinga erwartet Filter bei lesenden Anfragen, ein GET-Request kann aber keinen Body mitschicken. Der Header X-HTTP-Method-Override: GET ist der von Icinga empfohlene Weg, Filter sauber zu übergeben. Der Filter liefert alle Probleme, die noch niemand in Icinga bestätigt hat.
Als dritten Node fügst du einen HTTP Request-Node für Teams hinzu, eingerichtet wie in Schritt 8, mit diesem Body:
{
"type": "message",
"attachments": [{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "Icinga-Statusbericht vom {{ $now.toFormat('dd.MM.yyyy') }}"
},
{
"type": "TextBlock",
"wrap": true,
"color": "{{ $json.results.length ? 'Warning' : 'Good' }}",
"text": "{{ $json.results.length === 0 ? 'Alles in Ordnung, keine offenen Probleme.' : ($json.results.length === 1 ? 'Aktuell 1 offenes Problem:' : 'Aktuell ' + $json.results.length + ' offene Probleme:') }}"
},
{
"type": "FactSet",
"facts": {{ JSON.stringify($json.results.length === 0 ? [{ title: 'Status', value: 'Alle Services OK' }] : $json.results.sort((a, b) => b.attrs.state - a.attrs.state).map(r => ({ title: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'][r.attrs.state], value: r.attrs.host_name + ' / ' + r.attrs.display_name + ': ' + (r.attrs.last_check_result?.output || '') }))) }}
}
]
}
}]
}Die Nachricht trägt das aktuelle Datum, passt den Satz an die Anzahl der Probleme an und sortiert die Liste nach Schwere, CRITICAL vor WARNING. Ist alles grün, meldet sie das ebenfalls. Speichere den Workflow und aktiviere ihn.
Tipp: Lass zusätzlich einen Manual Trigger mit dem Icinga-Node verbunden. Dann kannst du den Bericht jederzeit per Klick auf „Execute workflow“ testen.
Schritt 13: Zertifikats Wochenbericht einrichten
Die Prüfung der Zertifikate übernimmt Icinga. Lege dafür einen Sammel-Host mit deinen Domains an. Für jede Domain erzeugt eine Apply-Regel automatisch einen eigenen Service:
cat > /etc/icinga2/conf.d/zertifikate.conf << 'EOF'
object Host "zertifikate" {
check_command = "dummy"
vars.dummy_state = 0
vars.dummy_text = "Sammel-Host für Zertifikatsprüfungen"
vars.domains = [
"www.netways.de",
"www.n8n.io"
]
}
apply Service "cert-" for (domain in host.vars.domains) {
check_command = "http"
check_interval = 12h
retry_interval = 30m
vars.http_address = domain
vars.http_vhost = domain
vars.http_ssl = true
vars.http_sni = true
vars.http_certificate = "30,14"
}
EOF
grep -q 'conf.d/zertifikate.conf' /etc/icinga2/icinga2.conf || \
echo 'include "conf.d/zertifikate.conf"' >> /etc/icinga2/icinga2.conf
icinga2 daemon -C && systemctl restart icinga2Icinga prüft jedes Zertifikat zweimal täglich. Ab 30 Tagen Restlaufzeit wird der Service gelb, ab 14 Tagen rot, und die Regeln aus Schritt 10 melden das automatisch in Teams. Die erste Prüfung stößt du in Icinga Web über „Jetzt prüfen“ beim jeweiligen cert–Service an.
Für den Bericht duplizierst du in n8n den Workflow aus Schritt 12 und nennst die Kopie Zertifikate Wochenbericht. Passe dann drei Dinge an.
Im Schedule Trigger änderst du die Expression auf Montag um 7 Uhr:

Warum versteht der Code mehrere Datumsformate? Wie das Prüf-Plugin das Ablaufdatum ausgibt, hängt von seiner Version und der Systemsprache ab. Auf einem deutsch eingestellten Server kommt etwa Fr 11 Dez 2026 20:02:07 GMT, auf einem englischen Fri Dec 11. Domains ohne lesbares Datum landen im Abschnitt „Nicht prüfbar“, damit keine Störung untergeht.
Zum Schluss passt du den Teams-Node an. Öffne ihn und ersetze den kompletten Inhalt im Feld JSON durch die folgende kurze Version. Der Code-Node hat die Nachricht bereits vollständig gebaut und gibt sie im Feld card weiter. Der Teams-Node muss sie nur noch in den Rahmen packen, den Teams erwartet, und abschicken:
{
"type": "message",
"attachments": [{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {{ JSON.stringify($json.card) }}
}]
}
Betrieb absichern
Schritt 13: Backup einrichten
Zum Abschluss sicherst du jede Nacht alles, was für eine Wiederherstellung nötig ist: die n8n-Datenbank, die .env mit dem Encryption Key, die Compose-Konfiguration samt Zertifikat und die Icinga-Konfiguration.
cat > /opt/n8n/backup.sh << 'EOF'
#!/bin/bash
# Tägliches Backup für n8n und Icinga-Konfiguration
set -e
BACKUP_DIR=/opt/n8n/backups
DATE=$(date +%F)
mkdir -p "$BACKUP_DIR"
docker exec n8n-postgres pg_dump -U n8n -d n8n | gzip > "$BACKUP_DIR/n8n-db-$DATE.sql.gz"
cp /opt/n8n/.env "$BACKUP_DIR/env-$DATE.bak"
tar czf "$BACKUP_DIR/n8n-config-$DATE.tar.gz" -C /opt/n8n docker-compose.yml certs
tar czf "$BACKUP_DIR/icinga2-config-$DATE.tar.gz" -C /etc icinga2
chmod 600 "$BACKUP_DIR"/*
find "$BACKUP_DIR" -type f -mtime +14 -delete
EOF
chmod 700 /opt/n8n/backup.shFühre das Skript einmal von Hand aus und richte dann einen Cronjob für eine beliebige Zeit ein:
/opt/n8n/backup.sh && ls -lh /opt/n8n/backups
echo '0 2 * * * root /opt/n8n/backup.sh' > /etc/cron.d/n8n-backupWo steht die Uhrzeit? In den ersten beiden Feldern des Cron-Eintrags: 0 ist die Minute, 5 die Stunde. Die drei Sternchen danach stehen für jeden Tag, jeden Monat und jeden Wochentag. Für 2:30 Uhr hieße der Eintrag zum Beispiel 30 2 * * *. Cron richtet sich nach der Zeitzone des Servers, die dir timedatectl anzeigt.
Sicherungen, die älter als 14 Tage sind, löscht das Skript automatisch. Für den Produktivbetrieb kopierst du den Ordner /opt/n8n/backups zusätzlich regelmäßig auf ein anderes System.
n8n mit Unterstützung einführen? Ob Anbindung an euer Ticketsystem, kundenspezifische Alarmierung oder Betrieb im Cluster: Unsere Consultants helfen dir, n8n sauber in deine Infrastruktur zu integrieren.
Fazit zur n8n Installation

In wenigen Schritten hast du n8n auf Ubuntu 26.04 installiert und mit Icinga verbunden. Alarme zu Hosts und Services landen in Echtzeit in Microsoft Teams, ein Statusbericht und ein Zertifikatsbericht laufen automatisch, und neue Hosts und Services werden ohne weiteren Aufwand einbezogen.
Bevor du die Umgebung produktiv nutzt, solltest du noch zwei Dinge ergänzen: HTTPS über einen Reverse Proxy, damit Logins und Webhooks verschlüsselt übertragen werden und du N8N_SECURE_COOKIE wieder entfernen kannst, sowie eine Kopie der Backups auf einem zweiten System inklusive eines einmaligen Wiederherstellungstests.
Auf dieser Grundlage lassen sich weitere Abläufe ergänzen, etwa automatisch erstellte Tickets bei kritischen Alarmen, Meldungen in die Kanäle einzelner Kunden oder Wartungsfenster, die Kunden per Formular eintragen.
Wenn du dabei Unterstützung brauchst, melde dich gerne bei uns!
