Skip to main content

n8n: Das komplette technische Handbuch

n8n 2.x ist das aktuelle Major-Release – mit Fokus auf Sicherheit, Performance und Skalierung. Die stabile Version 2.8.0 (Stand Februar 2026) läuft auf dem offiziellen Docker-Image docker.n8n.io/n8nio/n8n und wird wöchentlich aktualisiert. Dieses Handbuch dokumentiert sämtliche Konfigurationsdetails, Befehle und Best Practices für den produktiven Self-hosted-Betrieb – von der Docker-Installation über Reverse-Proxy-Setup bis hin zu Skalierung und Troubleshooting.


1. Docker-Installation und grundlegende Einrichtung

Docker Run – Schnellstart

Der einfachste Weg, n8n lokal zu starten:

docker volume create n8n_data

docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -e GENERIC_TIMEZONE="Europe/Berlin" \
  -e TZ="Europe/Berlin" \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n

Das Volume /home/node/.n8n ist kritisch – es enthält die SQLite-Datenbank, den automatisch generierten Encryption Key und alle Konfigurationsdaten. Ohne persistentes Volume gehen bei Container-Neustart sämtliche Daten verloren. Für Produktionsumgebungen empfiehlt sich zwingend PostgreSQL (siehe Abschnitt 5).

Docker Run mit PostgreSQL (Produktion)

docker run -d --restart always \
  --name n8n \
  -p 5678:5678 \
  -e DB_TYPE=postgresdb \
  -e DB_POSTGRESDB_HOST=<POSTGRES_HOST> \
  -e DB_POSTGRESDB_PORT=5432 \
  -e DB_POSTGRESDB_DATABASE=n8n \
  -e DB_POSTGRESDB_USER=n8n \
  -e DB_POSTGRESDB_PASSWORD=<SICHERES_PASSWORT> \
  -e N8N_ENCRYPTION_KEY=<DEIN_ENCRYPTION_KEY> \
  -e N8N_HOST=n8n.example.com \
  -e N8N_PROTOCOL=https \
  -e WEBHOOK_URL=https://n8n.example.com/ \
  -e GENERIC_TIMEZONE="Europe/Berlin" \
  -e TZ="Europe/Berlin" \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n:2.8.0

Docker Compose – Produktionsreife Konfiguration mit PostgreSQL

docker-compose.yml:

version: "3.8"

volumes:
  db_storage:
  n8n_storage:

services:
  postgres:
    image: postgres:16-alpine
    container_name: n8n-postgres
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - db_storage:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n:2.8.0
    container_name: n8n
    restart: always
    environment:
      # Kern-Konfiguration
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${N8N_HOST}/
      - N8N_EDITOR_BASE_URL=https://${N8N_HOST}/
      - GENERIC_TIMEZONE=Europe/Berlin
      - TZ=Europe/Berlin
      # Sicherheit
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_SECURE_COOKIE=true
      - N8N_BLOCK_ENV_ACCESS_IN_NODE=true
      - NODE_ENV=production
      # Datenbank
      - 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}
      # Execution Management
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=336
      - EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000
      - EXECUTIONS_DATA_SAVE_ON_ERROR=all
      - EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
      # Logging
      - N8N_LOG_LEVEL=warn
      - N8N_METRICS=true
      - N8N_PROXY_HOPS=1
    ports:
      - "5678:5678"
    volumes:
      - n8n_storage:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

.env-Datei:

N8N_HOST=n8n.example.com
POSTGRES_USER=n8n
POSTGRES_PASSWORD=EinSehrSicheresPasswort123!
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=<mit openssl rand -hex 32 generieren>

Sichere Werte generieren:

openssl rand -hex 32      # Für N8N_ENCRYPTION_KEY
openssl rand -base64 32   # Für Passwörter

2. Vollständige Umgebungsvariablen-Referenz

Kern-Identität und Deployment

Variable Default Beschreibung
N8N_HOST localhost Hostname für URL-Generierung
N8N_PORT 5678 HTTP-Port
N8N_LISTEN_ADDRESS :: Bind-Adresse
N8N_PROTOCOL http http oder https – beeinflusst URL-Generierung
N8N_PATH / Basis-Pfad
N8N_EDITOR_BASE_URL Öffentliche URL für Editor (SAML, OAuth-Redirects)
N8N_ENCRYPTION_KEY Auto-generiert KRITISCH – Schlüssel für Credential-Verschlüsselung
GENERIC_TIMEZONE America/New_York Zeitzone für Schedule-Nodes
TZ System-Zeitzone

Webhooks

Variable Default Beschreibung
WEBHOOK_URL KRITISCH – Öffentliche URL für Webhooks, z.B. https://n8n.example.com/
N8N_ENDPOINT_WEBHOOK webhook Pfad für Produktions-Webhooks
N8N_ENDPOINT_WEBHOOK_TEST webhook-test Pfad für Test-Webhooks
N8N_PROXY_HOPS 0 Anzahl Reverse-Proxies (für korrekte IP-Auflösung)

Authentifizierung

Wichtig: N8N_BASIC_AUTH_ACTIVE, N8N_BASIC_AUTH_USER und N8N_BASIC_AUTH_PASSWORD sind in n8n 2.x deprecated. n8n nutzt jetzt ein eingebautes User-Management mit Owner-Setup beim ersten Start.

Variable Default Beschreibung
N8N_USER_MANAGEMENT_JWT_SECRET Auto-generiert JWT-Secret für Sessions
N8N_SECURE_COOKIE true HTTPS für Session-Cookies erzwingen
N8N_SAMESITE_COOKIE lax Cross-Site-Cookie-Policy

Datenbank

Variable Default Beschreibung
DB_TYPE sqlite sqlite oder postgresdb
DB_POSTGRESDB_HOST localhost PostgreSQL-Host
DB_POSTGRESDB_PORT 5432 PostgreSQL-Port
DB_POSTGRESDB_DATABASE n8n Datenbankname
DB_POSTGRESDB_USER postgres Datenbanknutzer
DB_POSTGRESDB_PASSWORD Datenbankpasswort
DB_POSTGRESDB_SCHEMA public PostgreSQL-Schema
DB_POSTGRESDB_POOL_SIZE 2 Parallele Verbindungen
DB_POSTGRESDB_SSL_ENABLED false SSL-Verbindung aktivieren
DB_TABLE_PREFIX Prefix für Tabellennamen

Alle sensiblen Variablen unterstützen das _FILE-Suffix für Docker-Secrets-Integration, z.B. DB_POSTGRESDB_PASSWORD_FILE=/run/secrets/db_password.

Execution-Konfiguration

Variable Default Beschreibung
EXECUTIONS_MODE regular regular oder queue (Redis-basiert)
EXECUTIONS_TIMEOUT -1 Timeout in Sekunden; -1 = kein Limit
EXECUTIONS_DATA_SAVE_ON_ERROR all Fehlgeschlagene Executions speichern
EXECUTIONS_DATA_SAVE_ON_SUCCESS all Erfolgreiche Executions speichern
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS true Manuelle Executions speichern
EXECUTIONS_DATA_PRUNE true Automatisches Löschen alter Daten
EXECUTIONS_DATA_MAX_AGE 336 Maximales Alter in Stunden (14 Tage)
EXECUTIONS_DATA_PRUNE_MAX_COUNT 10000 Maximale Anzahl gespeicherter Executions
N8N_CONCURRENCY_PRODUCTION_LIMIT -1 Parallele Produktions-Executions; -1 = unbegrenzt

Queue-Modus (Redis)

Variable Default Beschreibung
QUEUE_BULL_REDIS_HOST localhost Redis-Host
QUEUE_BULL_REDIS_PORT 6379 Redis-Port
QUEUE_BULL_REDIS_PASSWORD Redis-Passwort
QUEUE_HEALTH_CHECK_ACTIVE /healthz-Endpoint auf Workern aktivieren

Logging und Metriken

Variable Default Beschreibung
N8N_LOG_LEVEL info error, warn, info, debug
N8N_LOG_OUTPUT console console, file
N8N_LOG_FILE_LOCATION Log-Dateipfad
N8N_METRICS false Prometheus /metrics-Endpoint

Sicherheit

Variable Default Beschreibung
N8N_BLOCK_ENV_ACCESS_IN_NODE false process.env-Zugriff in Code-Nodes blockieren
N8N_BLOCK_FILE_ACCESS_TO_N8N_FILES true Zugriff auf .n8n-Verzeichnis blockieren
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS false 0600-Berechtigungen auf Config-Datei
N8N_COMMUNITY_PACKAGES_ENABLED true Community-Pakete erlauben
N8N_DIAGNOSTICS_ENABLED true Anonyme Telemetrie senden
NODES_EXCLUDE Nodes ausschließen, z.B. ["n8n-nodes-base.executeCommand"]

Binärdaten-Speicherung

Variable Default Beschreibung
N8N_DEFAULT_BINARY_DATA_MODE filesystem filesystem oder s3
N8N_EXTERNAL_STORAGE_S3_HOST S3-Endpoint
N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME S3-Bucket
N8N_EXTERNAL_STORAGE_S3_ACCESS_KEY S3-Access-Key
N8N_EXTERNAL_STORAGE_S3_ACCESS_SECRET S3-Secret

3. Reverse-Proxy mit Nginx und Traefik

Nginx-Konfiguration (vollständig mit SSL und WebSocket)

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name n8n.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name n8n.example.com;

    ssl_certificate     /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;
    include             /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;

    location / {
        proxy_pass http://localhost:5678;
        proxy_http_version 1.1;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket-Support (kritisch für den n8n-Editor)
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;

        # Timeouts für lang laufende Workflows
        proxy_read_timeout    3600s;
        proxy_send_timeout    3600s;

        # Buffering deaktivieren für Streaming/WebSocket
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache     off;

        client_max_body_size 50M;
    }
}

SSL-Zertifikat einrichten:

sudo apt install -y nginx certbot python3-certbot-nginx
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo certbot --nginx -d n8n.example.com

Der map-Block für WebSocket-Upgrade ist essenziell. Ohne ihn bricht die Editor-Verbindung ab, weil n8n über WebSockets (wss://) den Echtzeit-Status von Workflow-Ausführungen streamt. proxy_http_version 1.1 ist ebenfalls zwingend notwendig.

Traefik mit automatischem Let's Encrypt (Docker Compose)

version: "3.8"

services:
  traefik:
    image: traefik:v2.11
    restart: always
    command:
      - --api.dashboard=true
      - --api.insecure=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.mytlschallenge.acme.tlschallenge=true
      - --certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}
      - --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - traefik_letsencrypt:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro

  n8n:
    image: docker.n8n.io/n8nio/n8n:2.8.0
    restart: always
    environment:
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=Europe/Berlin
    labels:
      - traefik.enable=true
      - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
      - traefik.http.routers.n8n.entrypoints=websecure
      - traefik.http.routers.n8n.tls.certresolver=mytlschallenge
      - traefik.http.middlewares.n8n-headers.headers.SSLRedirect=true
      - traefik.http.middlewares.n8n-headers.headers.STSSeconds=315360000
      - traefik.http.middlewares.n8n-headers.headers.browserXSSFilter=true
      - traefik.http.middlewares.n8n-headers.headers.contentTypeNosniff=true
      - traefik.http.routers.n8n.middlewares=n8n-headers
      - traefik.http.services.n8n.loadbalancer.server.port=5678
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  traefik_letsencrypt:
  n8n_data:

.env für Traefik:

DOMAIN_NAME=example.com
SUBDOMAIN=n8n
SSL_EMAIL=admin@example.com

Traefik übernimmt die komplette SSL-Verwaltung automatisch – Zertifikatsausstellung, Renewal und HTTPS-Redirect. In Produktion sollte --api.insecure=true entfernt oder das Dashboard mit Auth-Middleware abgesichert werden.


4. SSL/HTTPS – vier Methoden im Überblick

Methode 1: Let's Encrypt mit Certbot + Nginx (empfohlen für Nginx-Setups):

sudo certbot --nginx -d n8n.example.com
sudo certbot renew --dry-run  # Renewal testen

Methode 2: Automatisch über Traefik (siehe oben) – keinerlei manuelle Zertifikatsverwaltung nötig.

Methode 3: Selbstsignierte Zertifikate (nur für Entwicklung):

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/n8n-selfsigned.key \
  -out /etc/ssl/certs/n8n-selfsigned.crt \
  -subj "/CN=n8n.example.com"

Methode 4: n8n-eigenes SSL (ohne Reverse Proxy):

N8N_PROTOCOL=https
N8N_SSL_CERT=/ssl/fullchain.pem
N8N_SSL_KEY=/ssl/privkey.pem

Zertifikate werden per Volume eingebunden. Die empfohlene Methode für Produktion ist aber immer ein Reverse Proxy (Nginx oder Traefik), der SSL terminiert.


5. PostgreSQL statt SQLite

Wann PostgreSQL verwenden?

Kriterium SQLite PostgreSQL
Einsatz Entwicklung, Testing Produktion, Multi-User
Konkurrenz Single-Writer, Locks unter Last Volle Parallelität
Queue-Modus Nicht unterstützt Erforderlich
Datenintegrität Dateisystem-basiert ACID, WAL-Recovery
n8n 2.x Noch unterstützt Empfohlen (PostgreSQL 13–17)

Vollständige Docker Compose mit PostgreSQL

Siehe die docker-compose.yml in Abschnitt 1. Die PostgreSQL-Connection-Parameter unterstützen SSL für verwaltete Datenbanken:

DB_POSTGRESDB_SSL_ENABLED=true
DB_POSTGRESDB_SSL_CA=/path/to/ca-certificate.crt
DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED=true

Migration von SQLite zu PostgreSQL

Es gibt kein eingebautes Migrationstool. Die zuverlässigste Methode:

# 1. Export aus SQLite-Instanz
docker exec -u node -it n8n n8n export:workflow --all --output=/tmp/workflows/
docker exec -u node -it n8n n8n export:credentials --all --output=/tmp/credentials/

# 2. Dateien aus Container kopieren
docker cp n8n:/tmp/workflows/ ./backup/
docker cp n8n:/tmp/credentials/ ./backup/

# 3. PostgreSQL-Instanz starten (GLEICHEN N8N_ENCRYPTION_KEY verwenden!)
# 4. Import in neue Instanz
docker exec -u node -it n8n-new n8n import:workflow --input=/tmp/workflows/
docker exec -u node -it n8n-new n8n import:credentials --input=/tmp/credentials/

Ab n8n 2.x steht auch n8n export:entities / n8n import:entities für vollständigere Migrationen zur Verfügung.


6. Backup-Strategien

CLI-Export-Befehle

# Alle Workflows exportieren
docker exec -u node n8n n8n export:workflow --all --output=/tmp/workflows.json

# Alle Workflows als separate Dateien (Git-freundlich)
docker exec -u node n8n n8n export:workflow --all --separate --output=/tmp/workflows/

# Alle Credentials exportieren (verschlüsselt)
docker exec -u node n8n n8n export:credentials --all --output=/tmp/credentials.json

# Credentials entschlüsselt exportieren (für Migration)
docker exec -u node n8n n8n export:credentials --all --decrypted --output=/tmp/creds_plain.json

# Vollständiger Entity-Export (n8n 2.x)
docker exec -u node n8n n8n export:entities --outputDir=/tmp/exports

Datenbank-Backup

PostgreSQL (pg_dump):

docker exec -t n8n-postgres pg_dump -U n8n n8n | gzip > n8n_$(date +%F).sql.gz

SQLite (Datei kopieren bei gestopptem n8n):

docker compose stop n8n
cp /var/lib/docker/volumes/n8n_data/_data/database.sqlite ./backup/
docker compose start n8n

Automatisiertes Backup-Skript

#!/bin/bash
# /opt/scripts/n8n-backup.sh
BACKUP_DIR="/opt/n8n-backups"
DATE=$(date +%F)
RETENTION_DAYS=30

mkdir -p "$BACKUP_DIR/$DATE"

# PostgreSQL-Dump
docker exec -t n8n-postgres pg_dump -U n8n n8n \
  | gzip > "$BACKUP_DIR/$DATE/postgres_$DATE.sql.gz"

# n8n-Volume sichern (enthält Encryption Key)
docker run --rm -v n8n_storage:/data alpine \
  tar czf - -C / data > "$BACKUP_DIR/$DATE/n8n_data_$DATE.tgz"

# Workflow-Export
docker exec -u node n8n n8n export:workflow --all \
  --output=/tmp/wf.json 2>/dev/null
docker cp n8n:/tmp/wf.json "$BACKUP_DIR/$DATE/"

# Alte Backups löschen
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +$RETENTION_DAYS \
  -exec rm -rf {} \;

echo "Backup abgeschlossen: $BACKUP_DIR/$DATE"

Crontab (täglich um 2 Uhr):

0 2 * * * /opt/scripts/n8n-backup.sh >> /var/log/n8n-backup.log 2>&1

REST-API für Backups

curl -H "X-N8N-API-KEY: DEIN_API_KEY" \
  https://n8n.example.com/api/v1/workflows > all_workflows.json

Der API-Key wird unter Settings → API im n8n-UI generiert. Die API gibt keine Credential-Secrets aus – dafür muss export:credentials --decrypted genutzt werden.


7. Update-Prozess für Docker

# 1. Aktuelle Version prüfen
docker exec n8n n8n --version

# 2. Release Notes lesen: https://docs.n8n.io/release-notes/

# 3. Backup erstellen (VOR dem Update!)
docker exec -t n8n-postgres pg_dump -U n8n n8n > n8n_pre_update.sql
docker run --rm -v n8n_storage:/data alpine tar czf - -C / data > n8n_data_pre_update.tgz

# 4. Image aktualisieren und Container neu starten
docker compose pull
docker compose down
docker compose up -d

# 5. Logs prüfen
docker compose logs -f n8n

Version Pinning ist Pflicht in Produktiondocker.n8n.io/n8nio/n8n:2.8.0 statt :latest oder :stable. Ohne gepinnte Version ist ein Rollback nahezu unmöglich, weil das alte Image nach docker compose pull überschrieben wird.

Rollback-Verfahren

docker compose down

# docker-compose.yml: Image auf alte Version zurücksetzen
# image: docker.n8n.io/n8nio/n8n:2.7.0

# Datenbank-Backup einspielen (falls nötig)
cat n8n_pre_update.sql | docker exec -i n8n-postgres psql -U n8n -d n8n

docker compose up -d

n8n 2.0 Breaking Changes: MySQL/MariaDB-Support wurde entfernt. Vor einem Upgrade von 1.x auf 2.x muss n8n migration-report ausgeführt werden. Die Docker-Tags stable und beta ersetzen die alten Tags latest und next.


8. Lizenzmodell – Fair-Code und Editionen

n8n nutzt die Sustainable Use License (SUL) – quelloffen, aber nicht Open Source nach OSI-Definition. Enterprise-Features (Dateien mit .ee. im Namen) stehen unter der n8n Enterprise License.

Erlaubt unter SUL: Interne Geschäftsautomatisierung (auch bei Großunternehmen), Self-Hosting, persönliche Nutzung, Code-Modifikation für eigenen Gebrauch, Beratungsdienstleistungen rund um n8n.

Verboten unter SUL: Weiterverkauf eines Produkts, dessen Wert wesentlich auf n8n basiert; Hosting von n8n als kostenpflichtigen Service für Dritte (konkurriert mit n8n Cloud); Einbettung in kostenpflichtige externe Dienste.

Community vs. Enterprise

Feature Community (kostenlos) Enterprise (kostenpflichtig)
Workflows/Executions Unbegrenzt Unbegrenzt
Integrationen 400+ 400+
User-Management Basic (Owner + Members) RBAC mit Custom Roles
SSO SAML, OIDC, LDAP
Workflow-Sharing Nur Owner/Creator Vollständig
Source Control Git-Integration, Environments
Audit Logging
Multi-Main HA
Support Community-Forum Dedizierter Support mit SLAs

Seit 2025 gibt es keine aktiven Workflow-Limits mehr – alle Pläne bieten unbegrenzte Workflows. Die Preisgestaltung skaliert stattdessen nach Execution-Anzahl.


9. Sicherheitseinstellungen für Produktion

Essenzielle Konfiguration

N8N_ENCRYPTION_KEY=<openssl rand -hex 32>
N8N_PROTOCOL=https
N8N_SECURE_COOKIE=true
N8N_BLOCK_ENV_ACCESS_IN_NODE=true
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
N8N_PROXY_HOPS=1
NODE_ENV=production
N8N_DIAGNOSTICS_ENABLED=false
N8N_LOG_LEVEL=warn

Der N8N_ENCRYPTION_KEY ist der kritischste Wert der gesamten Installation. Dieser Schlüssel verschlüsselt sämtliche gespeicherten Credentials (API-Keys, Passwörter, Tokens) in der Datenbank. Geht er verloren, sind alle Credentials unwiederbringlich verloren. Der Schlüssel muss separat gesichert werden und über alle Instanzen (Main + Worker im Queue-Modus) identisch sein.

Produktions-Checkliste

  • HTTPS mit gültigem SSL-Zertifikat erzwingen
  • Port 5678 nie direkt exponieren – immer hinter Reverse Proxy
  • 2FA für alle Admin-Accounts aktivieren
  • Ungenutzte Nodes ausschließen: NODES_EXCLUDE=["n8n-nodes-base.executeCommand"]
  • Webhook-Endpoints authentifizieren (Header Auth, JWT, HMAC)
  • Rate Limiting auf Reverse-Proxy-Ebene implementieren
  • Fail2ban auf dem Host konfigurieren
  • Firewall: nur Ports 80/443 öffnen

10. Performance-Tuning und Skalierung mit Queue-Modus

Architektur im Queue-Modus

Der Queue-Modus trennt Scheduling von Execution: Die Main-Instanz verwaltet UI, API, Trigger und Webhooks, übergibt Workflow-Ausführungen aber an eine Redis-Queue. Separate Worker-Prozesse ziehen Jobs aus der Queue und führen sie aus. Dies ermöglicht horizontale Skalierung.

Docker Compose mit Queue-Modus (PostgreSQL + Redis + Worker)

version: "3.8"

services:
  postgres:
    image: postgres:16-alpine
    restart: always
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes:
      - pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: always
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data

  n8n:
    image: docker.n8n.io/n8nio/n8n:2.8.0
    restart: always
    ports:
      - "5678:5678"
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
      - N8N_CONCURRENCY_PRODUCTION_LIMIT=20
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      - NODE_OPTIONS=--max-old-space-size=2048
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

  n8n-worker:
    image: docker.n8n.io/n8nio/n8n:2.8.0
    restart: always
    command: worker
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
      - QUEUE_HEALTH_CHECK_ACTIVE=true
      - NODE_OPTIONS=--max-old-space-size=2048
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  pg_data:
  redis_data:
  n8n_data:

Worker skalieren:

docker compose up -d --scale n8n-worker=3

Performance-Optimierungen

# Binärdaten auf Filesystem statt RAM speichern
N8N_DEFAULT_BINARY_DATA_MODE=filesystem

# Execution-Pruning aggressiv konfigurieren
EXECUTIONS_DATA_MAX_AGE=168
EXECUTIONS_DATA_PRUNE_MAX_COUNT=5000
EXECUTIONS_DATA_SAVE_ON_SUCCESS=none   # Nur Fehler speichern

# Node.js Heap vergrößern
NODE_OPTIONS=--max-old-space-size=4096

# Docker Resource-Limits setzen
deploy:
  resources:
    limits:
      memory: 2G
    reservations:
      memory: 1G

Minimum für Produktion: 2 GB RAM. Jeder Worker verbraucht 200–500 MB RAM. Empfohlene Concurrency pro Worker: 5–10. Im Queue-Modus ist PostgreSQL zwingend erforderlich, SQLite wird nicht unterstützt. Für Binärdaten in verteilten Setups muss S3/MinIO statt Filesystem verwendet werden.


11. Webhooks und externe Erreichbarkeit

URL-Struktur

Typ URL-Muster
Produktion https://n8n.example.com/webhook/<pfad>
Test https://n8n.example.com/webhook-test/<pfad>

Produktions-Webhooks funktionieren nur bei aktiviertem Workflow. Test-Webhooks laufen ~120 Sekunden nach Klick auf „Listen for Test Event".

Externe Erreichbarkeit einrichten

  1. DNS A-Record auf Server-IP zeigen lassen
  2. Firewall öffnen: sudo ufw allow 80 && sudo ufw allow 443
  3. Reverse Proxy konfigurieren (Nginx/Traefik)
  4. WEBHOOK_URL=https://n8n.example.com/ setzen
  5. N8N_PROXY_HOPS=1 setzen
  6. Workflow aktivieren

Webhook testen

curl -X POST https://n8n.example.com/webhook/mein-endpoint \
  -H "Content-Type: application/json" \
  -d '{"name": "test", "event": "order_created"}'

Webhook-Sicherheit

Der Webhook-Node bietet eingebaute Authentifizierungsoptionen: Header Auth (geheimer Header), Basic Auth, JWT Auth und IP-Whitelisting. Für Dienste wie Stripe oder GitHub sollte die HMAC-Signatur-Verifizierung über einen Code-Node implementiert werden. Unauthentifizierte Webhook-Endpoints sollten in Produktion nie verwendet werden.


12. Community Nodes installieren

Über die UI (empfohlen)

Settings → Community Nodes → Install → npm-Paketnamen eingeben (z.B. n8n-nodes-mcp) → Risikohinweis bestätigen → Install. Nur Owner- oder Admin-Rollen können installieren.

Per CLI (für Queue-Modus oder private Pakete)

docker exec -it n8n bash
cd /home/node/.n8n
npm install n8n-nodes-<paketname>
# Dann n8n neu starten

Im Queue-Modus muss das Paket auf allen Worker-Containern installiert werden.

Relevante Umgebungsvariablen

N8N_COMMUNITY_PACKAGES_ENABLED=true
N8N_REINSTALL_MISSING_PACKAGES=true    # Reinstall nach Container-Neustart
N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true  # Als AI-Agent-Tools erlauben

Community Nodes werden im Verzeichnis ~/.n8n/nodes/ gespeichert – das Volume muss persistiert sein, sonst gehen die Nodes bei Container-Neustart verloren.


13. Aktuelle n8n-Version (Februar 2026)

Kanal Version Datum
Stable 2.8.0 11. Feb 2026
Beta 2.9.0 16. Feb 2026
Legacy 1.x 1.123.21 20. Feb 2026

Die Docker-Tags stable und beta ersetzen seit n8n 2.0 die alten Tags latest und next. Die offizielle Image-Registry ist docker.n8n.io/n8nio/n8n, alternativ bleibt Docker Hub (n8nio/n8n) verfügbar. Für Produktion immer eine spezifische Version pinnen, z.B. docker.n8n.io/n8nio/n8n:2.8.0.


14. Typische Troubleshooting-Probleme und Lösungen

Container startet nicht – Berechtigungsfehler

EACCES: permission denied, open '/home/node/.n8n/config'

n8n läuft als User node (UID 1000). Fix: sudo chown -R 1000:1000 /pfad/zu/n8n/data oder user: "1000:1000" in der docker-compose.yml setzen.

Webhooks nicht erreichbar

Häufigste Ursachen: WEBHOOK_URL nicht gesetzt oder zeigt auf localhost, Workflow nicht aktiviert (Produktions-Webhooks erfordern aktivierten Workflow), fehlende Proxy-Header in Nginx/Traefik, oder N8N_PROXY_HOPS nicht korrekt. Diagnose:

docker exec n8n env | grep WEBHOOK_URL
curl -X POST https://n8n.example.com/webhook/test -d '{"test": true}'

Memory-Probleme / OOM

docker stats n8n    # Ressourcen überwachen

# Sofortmaßnahmen:
N8N_DEFAULT_BINARY_DATA_MODE=filesystem
EXECUTIONS_DATA_MAX_AGE=168
EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
NODE_OPTIONS=--max-old-space-size=4096

Große Datenmengen in kleineren Batches verarbeiten (200 statt 10.000 Zeilen). Sub-Workflows nutzen, um Speicher zu isolieren.

Encryption Key verloren

Katastrophal. Wenn der N8N_ENCRYPTION_KEY verloren geht und kein Backup existiert, sind alle gespeicherten Credentials unwiederbringlich verloren. Prävention: Key aus ~/.n8n/config sichern, explizit als Umgebungsvariable setzen, und separat vom Datenbank-Backup aufbewahren.

Schnellreferenz häufiger Fehler

Fehler Lösung
EACCES: permission denied chown -R 1000:1000 /data/pfad
Received request for unknown webhook Workflow aktivieren
Request failed with status code 401 OAuth-Tokens erneuern
Out of memory Memory-Limits erhöhen, Binary-Mode auf Filesystem
Missing encryption key N8N_ENCRYPTION_KEY identisch auf allen Instanzen setzen
Zeitzone falsch GENERIC_TIMEZONE=Europe/Berlin und TZ=Europe/Berlin setzen

Debug-Logging aktivieren

N8N_LOG_LEVEL=debug    # Nur für aktives Debugging, danach auf warn zurücksetzen

docker logs -f n8n --tail 200
docker logs n8n | grep -i "error"

Fazit und Kernempfehlungen

Self-hosted n8n 2.x ist eine ausgereifte Plattform für Workflow-Automatisierung. Die fünf entscheidenden Konfigurationsentscheidungen für jede produktive Installation lauten: PostgreSQL statt SQLite, explizit gesetzter und gesicherter Encryption Key, Reverse Proxy mit SSL (Nginx oder Traefik), Execution-Pruning aktivieren, und Version Pinning im Docker-Image. Wer mehr als gelegentliche Workflow-Ausführungen benötigt, sollte den Queue-Modus mit Redis und separaten Workern evaluieren – er verwandelt n8n von einer Single-Process-Anwendung in eine horizontal skalierbare Architektur. Die Community Edition deckt den Großteil aller Anwendungsfälle ab; Enterprise-Features wie SSO, RBAC und Multi-Main-HA werden erst in größeren Team-Setups oder bei Compliance-Anforderungen relevant.