Zum Inhalt springen
← Alle Beiträge
· 6 Min. Lesezeit·Emre Yurtbay

Workflow-Automatisierung mit n8n: Self-Hosting, Architektur und erste Workflows

n8n als selbst gehostete Workflow-Engine: Einordnung gegenüber Make, Zapier, Temporal und Airflow, Docker-Setup und ein praxisnaher Beispiel-Workflow.

n8nWorkflow-EngineAutomatisierungDockerSelf-HostingNode.jsDSGVOTemporalAirflowIntegration

Automatisierungswerkzeuge sind aus modernen IT-Architekturen nicht wegzudenken. Ob Daten zwischen SaaS-Systemen synchronisiert, Webhooks verarbeitet oder wiederkehrende Batch-Jobs orchestriert werden müssen – ohne eine dedizierte Automatisierungsschicht landet die Logik schnell als Spaghetti-Code in Microservices oder als fragile Shell-Skripte in Cron-Jobs. Dieser Artikel beleuchtet die Klasse der Workflow-Engines am Beispiel von n8n, ordnet sie gegenüber verwandten Werkzeugen ein und zeigt, wie Sie n8n in wenigen Minuten selbst betreiben.

Was ist eine Workflow-Engine?

Eine Workflow-Engine modelliert Automatisierungslogik als gerichteten Graphen aus Nodes. Jeder Node kapselt eine Aktion oder Transformation; Verbindungen (Edges) definieren den Datenfluss. Das Kernprinzip lautet:

Trigger --> Verarbeitung --> Aktion(en)

n8n folgt diesem Modell visuell: Sie ziehen Nodes auf eine Canvas, verbinden sie und konfigurieren sie per Formular. Unter der Haube ist n8n eine Node.js-Anwendung (TypeScript), die Workflows in einer SQLite- oder PostgreSQL-Datenbank persistiert und per Webhooks, Cron oder manuell auslöst.

Typische Anwendungsfälle:

  • Eingehende Webhooks verarbeiten und an interne APIs weiterleiten
  • Daten zwischen CRM, ERP und Kommunikationsplattformen synchronisieren
  • Alerts aus Monitoring-Systemen anreichern und eskalieren
  • Datei-Uploads transformieren und in Objektspeicher schreiben

Einordnung: n8n, Make/Zapier, Temporal, Airflow

Bevor Sie ein Werkzeug wählen, lohnt sich eine ehrliche Abgrenzung. Die folgende Tabelle zeigt die wesentlichen Unterschiede:

+------------------+------------+------------+------------+------------+
| Kriterium        | n8n        | Make/Zapier| Temporal   | Airflow    |
+------------------+------------+------------+------------+------------+
| Hosting          | Self/SaaS  | SaaS only  | Self/Cloud | Self/Cloud |
| Code-Freiheit    | hoch       | niedrig    | vollstaend.| hoch       |
| Visuelle Canvas  | ja         | ja         | nein       | DAG-View   |
| Durability/Retry | einfach    | einfach    | nativ/tief | mittel     |
| Zielgruppe       | Dev/Ops    | No-Code    | Backend-Dev| Data-Eng.  |
| Lizenz           | fair-code  | proprietaer| MIT        | Apache 2.0 |
| DSGVO Self-Host  | ja         | nein       | ja         | ja         |
+------------------+------------+------------+------------+------------+

Make und Zapier eignen sich für schnelle, no-code Integrationen zwischen Cloud-Diensten. Sobald Sie eigene Transformationslogik, Self-Hosting aus Datenschutzgründen oder komplexere Verzweigungen brauchen, stoßen Sie an Grenzen.

Temporal und Apache Airflow sind echte Code-Orchestratoren. Temporal bietet nativ dauerhafte Workflows mit automatischen Retries, Saga-Pattern und deterministischen Replays – geeignet für verteilte Transaktionen, die Minuten bis Stunden (oder länger) dauern. Airflow ist speziell auf datengetriebene DAG-Pipelines (ETL, ML-Pipelines) ausgerichtet. Beide erfordern deutlich mehr Entwicklungsaufwand und Infrastruktur.

n8n positioniert sich dazwischen: ausreichend mächtig für produktive Integrationsstrecken, entwicklerfreundlich dank Code-Nodes, aber ohne die Garantien eines durable-execution Frameworks. Für operative Webhooks, Benachrichtigungspipelines und mittlere Komplexität ist n8n die pragmatische Wahl.

n8n selbst hosten mit Docker

n8n stellt ein offizielles Docker-Image unter docker.n8n.io/n8nio/n8n bereit. Das folgende docker-compose.yml ist produktionsnah und deckt Persistenz, Zeitzone und Webhook-URL ab:

# docker-compose.yml
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=n8n.beispiel.de
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.beispiel.de/
      - GENERIC_TIMEZONE=Europe/Berlin
      - TZ=Europe/Berlin
      # Verschluesselungs-Key fuer Credentials fest setzen (sonst pro Volume generiert)
      - N8N_ENCRYPTION_KEY=bitte-ersetzen-langer-zufallswert
      # Externe PostgreSQL-Datenbank statt SQLite
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=db-passwort
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=db-passwort
    volumes:
      - pg_data:/var/lib/postgresql/data

volumes:
  n8n_data:
  pg_data:

Starten Sie den Stack mit:

docker compose up -d
# Logs beobachten
docker compose logs -f n8n

n8n ist danach unter http://localhost:5678 erreichbar.

Hinweis zur Authentifizierung: Die früher übliche Basic-Auth über N8N_BASIC_AUTH_ACTIVE/N8N_BASIC_AUTH_USER/N8N_BASIC_AUTH_PASSWORD wurde mit n8n 1.0 entfernt und ist in aktuellen Versionen wirkungslos. Stattdessen greift das integrierte User-Management: Beim ersten Aufruf legen Sie ein Owner-Konto (E-Mail + Passwort) an; weitere Benutzer laden Sie anschließend ein. Eine echte Schutzschicht für die exponierte Instanz gehört in den vorgelagerten Reverse-Proxy.

In Produktion schalten Sie einen Reverse-Proxy (nginx, Caddy, Traefik) davor, der TLS terminiert und optional IP-Allowlisting umsetzt. Die Variable WEBHOOK_URL muss auf die extern erreichbare HTTPS-URL zeigen, damit Webhook-Nodes korrekte Callback-URLs generieren.

Beispiel-Workflow: Webhook bis HTTP-Request

Der folgende Ablauf illustriert einen typischen Integrationsfall: Ein eingehender Webhook liefert Rohdaten, ein Code-Node transformiert sie, ein HTTP-Request-Node schickt das Ergebnis an eine externe API, und ein Respond-Node antwortet dem Aufrufer.

+-----------------+    +-----------------+    +-----------------+    +-----------------+
| Webhook Trigger |--->| Code / Transform|--->| HTTP Request    |--->| Respond to      |
| POST /hook/xyz  |    | (JS, $input)    |    | POST /api/ingest|    | Webhook         |
+-----------------+    +-----------------+    +-----------------+    +-----------------+

Code-Node: Items transformieren

n8n reicht Daten als Array von Items weiter. Im Code-Node greifen Sie über $input.all() darauf zu und geben ein neues Array zurück:

// Code-Node (JavaScript) - Modus "Run Once for All Items"
const items = $input.all();

return items
  .filter(item => item.json.status === "active")
  .map(item => {
    const { id, name, email, createdAt } = item.json;

    return {
      json: {
        externalId: `EXT-${id}`,
        displayName: name.trim(),
        contactEmail: email.toLowerCase(),
        // ISO-8601-Timestamp sicherstellen
        registeredAt: new Date(createdAt).toISOString(),
        source: "n8n-webhook",
      },
    };
  });

Wichtige Konventionen:

  • Jedes zurückgegebene Objekt muss eine json-Property haben.
  • Binärdaten landen in einer optionalen binary-Property.
  • $input, $workflow und $execution sind globale Hilfsobjekte der n8n-Laufzeit; auf Daten anderer Nodes greifen Sie idiomatisch über $('Node-Name') zu.

Workflow-Skelett als JSON

n8n-Workflows lassen sich als JSON exportieren und versionieren. Ein minimales Skelett sieht so aus:

{
  "name": "Webhook-Transform-Request",
  "nodes": [
    {
      "id": "1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [240, 300],
      "parameters": {
        "httpMethod": "POST",
        "path": "ingest",
        "responseMode": "responseNode"
      }
    },
    {
      "id": "2",
      "name": "Transform",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [460, 300],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "return $input.all().map(i => ({ json: { ...i.json, processed: true } }));"
      }
    },
    {
      "id": "3",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [680, 300],
      "parameters": {
        "method": "POST",
        "url": "https://api.beispiel.de/ingest",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json) }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "Authorization", "value": "Bearer {{ $env.API_TOKEN }}" }
          ]
        }
      }
    },
    {
      "id": "4",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [900, 300],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"ok\": true } }}"
      }
    }
  ],
  "connections": {
    "Webhook": { "main": [[{ "node": "Transform", "type": "main", "index": 0 }]] },
    "Transform": { "main": [[{ "node": "HTTP Request", "type": "main", "index": 0 }]] },
    "HTTP Request": { "main": [[{ "node": "Respond to Webhook", "type": "main", "index": 0 }]] }
  }
}

Da der Webhook mit responseMode: "responseNode" konfiguriert ist, beendet der Node Respond to Webhook (n8n-nodes-base.respondToWebhook) die HTTP-Antwort an den Aufrufer. Secrets wie API_TOKEN hinterlegen Sie in n8n als Credentials oder als Umgebungsvariable, niemals hardcodiert im Workflow-JSON.

Lizenz und DSGVO

n8n steht unter der Sustainable Use License (fair-code). Das bedeutet: Sie dürfen die Software kostenlos nutzen, modifizieren und weitergeben – allerdings nur für Ihre eigenen internen Geschäftszwecke oder für nicht-kommerzielle bzw. persönliche Nutzung. Eingeschränkt ist insbesondere, n8n als gehosteten Dienst für Dritte anzubieten oder ein Produkt zu verkaufen, dessen Wert wesentlich auf n8n beruht; dafür ist eine separate kommerzielle Lizenz nötig. Das bloße Anbieten von Beratungs- oder Implementierungsleistungen rund um n8n ist hingegen erlaubt. Die Details finden Sie in der Sustainable Use License sowie im n8n-Repository.

Für europäische Unternehmen ist der DSGVO-Aspekt des Self-Hostings relevant: Alle verarbeiteten Nutzdaten verbleiben in Ihrer eigenen Infrastruktur. Bei SaaS-Anbietern wie Make oder Zapier werden Payload-Daten auf deren Servern – häufig außerhalb der EU – verarbeitet, was Auftragsverarbeitungsverträge und ggf. Drittland-Transfer-Prüfungen erfordert.

Praxis-Empfehlung

Beginnen Sie mit SQLite für lokale Entwicklung und Prototypen; für Produktion empfiehlt sich PostgreSQL mit einem dedizierten Volume und regelmäßigen Backups (pg_dump). Setzen Sie zudem einen festen N8N_ENCRYPTION_KEY, damit hinterlegte Credentials bei einem Neuaufbau weiter entschlüsselt werden können. Versionieren Sie Ihre Workflow-JSONs in Git, begrenzen Sie ausführliche Execution-Logs auf Debug-Phasen (Datensparsamkeit), und schützen Sie die Instanz durch einen Reverse-Proxy mit TLS. Für Workflows mit harten Zuverlässigkeitsanforderungen – etwa verteilte Transaktionen über mehrere externe Systeme hinweg – prüfen Sie, ob Temporal die bessere Grundlage wäre.

Haben Sie Fragen zur Integration in Ihre konkrete Systemlandschaft, zur Skalierung über mehrere Worker oder zur Absicherung der n8n-Instanz? Schreiben Sie an info@yurtbay.dev.

Projekt besprechen