n8n selbst hosten mit Docker Compose: Komplettanleitung für deutsche Server

So installieren Sie n8n mit Docker Compose: Postgres statt SQLite, .env, Volumes und Updates Schritt für Schritt.

n8n lässt sich mit Docker Compose in wenigen Schritten auf einem eigenen Server installieren. Sie legen eine compose.yaml und eine .env-Datei an, definieren Volumes für die dauerhaften Daten und starten den Stack mit einem einzigen Befehl.

Für den produktiven Betrieb wechseln viele Betreiber von der mitgelieferten SQLite-Datenbank zu PostgreSQL. Dieser Artikel zeigt die Compose-Datei, die nötigen Umgebungsvariablen, die Volumes und den Ablauf für Updates.

Wie installiert man n8n mit Docker Compose?

Die Installation besteht aus vier Schritten: Docker prüfen, Projektverzeichnis anlegen, compose.yaml und .env schreiben, Stack starten. Danach ist n8n unter Ihrer Domain erreichbar.

  1. Docker und Docker Compose prüfen mit docker --version und docker compose version
  2. Projektverzeichnis anlegen, darin einen Unterordner local-files für den Dateiaustausch
  3. compose.yaml und .env in dieses Verzeichnis legen
  4. Stack starten mit docker compose up -d

Die folgende compose.yaml folgt dem offiziellen Setup aus der n8n-Dokumentation zu Docker Compose. Traefik übernimmt darin den Reverse Proxy und die TLS-Zertifikate.

1services:
2 traefik:
3 image: traefik:v3.1
4 restart: always
5 command:
6 - "--providers.docker=true"
7 - "--providers.docker.exposedbydefault=false"
8 - "--entrypoints.web.address=:80"
9 - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
10 - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
11 - "--entrypoints.websecure.address=:443"
12 - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
13 - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
14 - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
15 ports:
16 - "80:80"
17 - "443:443"
18 volumes:
19 - traefik_data:/letsencrypt
20 - /var/run/docker.sock:/var/run/docker.sock:ro
21
22 n8n:
23 image: n8nio/n8n:1.81.0
24 restart: always
25 ports:
26 - "127.0.0.1:5678:5678"
27 labels:
28 - traefik.enable=true
29 - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
30 - traefik.http.routers.n8n.tls=true
31 - traefik.http.routers.n8n.entrypoints=web,websecure
32 - traefik.http.routers.n8n.tls.certresolver=mytlschallenge
33 - traefik.http.middlewares.n8n.headers.SSLRedirect=true
34 - traefik.http.middlewares.n8n.headers.STSSeconds=315360000
35 - traefik.http.middlewares.n8n.headers.browserXSSFilter=true
36 - traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
37 - traefik.http.middlewares.n8n.headers.forceSTSHeader=true
38 - traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
39 - traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
40 - traefik.http.middlewares.n8n.headers.STSPreload=true
41 - traefik.http.routers.n8n.middlewares=n8n@docker
42 environment:
43 - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
44 - N8N_PORT=5678
45 - N8N_PROTOCOL=https
46 - NODE_ENV=production
47 - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
48 - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
49 - TZ=${GENERIC_TIMEZONE}
50 - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
51 - N8N_RUNNERS_ENABLED=true
52 - N8N_RESTRICT_FILE_ACCESS_TO=/files
53 volumes:
54 - n8n_data:/home/node/.n8n
55 - ./local-files:/files
56
57volumes:
58 n8n_data:
59 traefik_data:

Der Versions-Tag 1.81.0 ist bewusst gesetzt. Ohne Tag zieht docker compose pull jede neue Hauptversion mit, auch wenn sich Umgebungsvariablen geändert haben.

Was gehört in die .env-Datei?

Die .env-Datei enthält alle Werte, die sich von Server zu Server unterscheiden. Dadurch bleibt die compose.yaml auf jedem Server identisch.

1DOMAIN_NAME=beispiel.de
2SUBDOMAIN=n8n
3GENERIC_TIMEZONE=Europe/Berlin
4SSL_EMAIL=technik@beispiel.de

Variable | Zweck | Beispielwert

Variable: DOMAIN_NAME · Zweck: Basisdomain für Traefik-Regel und TLS · Beispielwert: beispiel.de

Variable: SUBDOMAIN · Zweck: Subdomain, unter der n8n läuft · Beispielwert: n8n

Variable: GENERIC_TIMEZONE · Zweck: Zeitzone für Zeitplan-Nodes und TZ · Beispielwert: Europe/Berlin

Variable: SSL_EMAIL · Zweck: Kontaktadresse für die Zertifikatsausstellung · Beispielwert: technik@beispiel.de

Die Datei enthält serverspezifische Werte und später oft auch Passwörter. Sie gehört deshalb in die .gitignore und nie in ein öffentliches Repository.

SQLite oder PostgreSQL: Welche Datenbank ist sinnvoll?

SQLite reicht für Einzelinstanzen mit wenigen parallelen Ausführungen, PostgreSQL ist die richtige Wahl für produktive Server mit vielen Workflows. n8n nutzt ohne weitere Konfiguration SQLite und legt die Datei database.sqlite im Verzeichnis .n8n ab.

Kriterium | SQLite | PostgreSQL

Kriterium: Konfiguration · SQLite: keine, Standard · PostgreSQL: DB_TYPE und fünf weitere Variablen

Kriterium: Parallele Ausführungen · SQLite: begrenzt, Schreibsperren auf Dateiebene · PostgreSQL: für parallele Zugriffe ausgelegt

Kriterium: Backup im laufenden Betrieb · SQLite: Datei kopieren ist heikel · PostgreSQL: pg_dump ohne Stopp möglich

Kriterium: Queue-Modus mit mehreren Workern · SQLite: nicht geeignet · PostgreSQL: Voraussetzung

Kriterium: Zusätzlicher Container · SQLite: nein · PostgreSQL: ja

Die Variablennamen stehen in der Dokumentation zur Datenbankauswahl. Der folgende Ausschnitt ergänzt dieselbe compose.yaml. Die Zeilen unter n8n gehören in den bereits vorhandenen Block, nicht in einen zweiten.

1services:
2 postgres:
3 image: postgres:16.4
4 restart: always
5 environment:
6 - POSTGRES_DB=${POSTGRES_DB}
7 - POSTGRES_USER=${POSTGRES_USER}
8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
9 volumes:
10 - postgres_data:/var/lib/postgresql/data
11 healthcheck:
12 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
13 interval: 10s
14 timeout: 5s
15 retries: 5
16
17 n8n:
18 depends_on:
19 postgres:
20 condition: service_healthy
21 environment:
22 - DB_TYPE=postgresdb
23 - DB_POSTGRESDB_HOST=postgres
24 - DB_POSTGRESDB_PORT=5432
25 - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
26 - DB_POSTGRESDB_USER=${POSTGRES_USER}
27 - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
28 - DB_POSTGRESDB_SCHEMA=public
29
30volumes:
31 postgres_data:

Die drei neuen Werte kommen ebenfalls in die .env-Datei:

1POSTGRES_DB=n8n
2POSTGRES_USER=n8n
3POSTGRES_PASSWORD=hier-ein-langes-zufaelliges-passwort

Auch mit PostgreSQL bleibt das Volume auf /home/node/.n8n notwendig. Dort liegt der Schlüssel, mit dem n8n die gespeicherten Zugangsdaten verschlüsselt.

Welche Volumes und Verzeichnisse benötigt n8n?

Vier Speicherorte müssen einen Neuaufbau des Containers überleben. Fehlt einer davon, gehen Workflows, Zugangsdaten, Zertifikate oder ausgetauschte Dateien verloren.

Volume oder Pfad | Ziel im Container | Inhalt

Volume oder Pfad: n8n_data · Ziel im Container: /home/node/.n8n · Inhalt: Verschlüsselungsschlüssel, SQLite-Datei, Instanzdaten

Volume oder Pfad: traefik_data · Ziel im Container: /letsencrypt · Inhalt: TLS-Zertifikate von Let's Encrypt

Volume oder Pfad: postgres_data · Ziel im Container: /var/lib/postgresql/data · Inhalt: Datenbank, sofern PostgreSQL genutzt wird

Volume oder Pfad: ./local-files · Ziel im Container: /files · Inhalt: Dateiaustausch zwischen Host und Workflows

Im Workflow sprechen Sie den Austauschordner über den Pfad /files an, nicht über den Host-Pfad. Die Variable N8N_RESTRICT_FILE_ACCESS_TO begrenzt den Zugriff auf genau dieses Verzeichnis.

Wie aktualisiert man n8n mit Docker Compose?

Ein Update läuft über die drei Befehle docker compose pull, docker compose down und docker compose up -d. Die Volumes bleiben dabei unberührt, Workflows und Zugangsdaten also erhalten.

1cd /opt/n8n
2docker compose pull
3docker compose down
4docker compose up -d
5docker compose logs -f n8n

Vor dem Update ändern Sie den Versions-Tag in der compose.yaml auf die gewünschte Version. Prüfen Sie vorher die Release-Hinweise, weil sich Umgebungsvariablen zwischen Hauptversionen ändern können.

Der Tag next liefert die instabile Beta-Version und gehört nicht auf einen produktiven Server. Die Tag-Übersicht steht in der Anleitung zur Docker-Installation.

Wer eine saubere Konfiguration von Anfang an will, plant lieber einmal gründlich. Genau das übernimmt NordFlux im Rahmen der n8n-Einrichtung zum Festpreis, inklusive Entscheidung zwischen SQLite und PostgreSQL.

Typische Fehler und Ursachen

Fünf Fehlerbilder treten bei Docker-Compose-Installationen besonders häufig auf. Alle lassen sich über Umgebungsvariablen oder Volumes lösen.

Zugangsdaten lassen sich nach einem Neuaufbau nicht mehr entschlüsseln.

Ursache: Das Volume auf /home/node/.n8n fehlte oder wurde neu angelegt, also erzeugte n8n einen neuen Verschlüsselungsschlüssel. Lösung: Volume dauerhaft mounten oder N8N_ENCRYPTION_KEY fest vorgeben. Quelle: Umgebungsvariablen für das Deployment.

Webhook-URLs im Editor zeigen auf localhost statt auf die Domain.

Ursache: WEBHOOK_URL und N8N_HOST sind nicht gesetzt, n8n kennt seine öffentliche Adresse nicht. Lösung: beide Variablen wie im Beispiel oben setzen und den Container neu starten. Quelle: Setup mit Docker Compose.

Zeitplan-Nodes feuern zur falschen Uhrzeit.

Ursache: Nur TZ oder nur GENERIC_TIMEZONE ist gesetzt, der Container läuft sonst auf UTC. Lösung: beide Variablen auf denselben Wert setzen, etwa Europe/Berlin. Quelle: Installation mit Docker.

n8n meldet beim Start eine Deprecation-Warnung zu Task Runnern.

Ursache: N8N_RUNNERS_ENABLED fehlt in der Konfiguration. Lösung: Variable in Version 1.x auf true setzen. Ab n8n 2.0 ist sie überflüssig. Quelle: Installation mit Docker.

Ein Workflow findet eine Datei auf dem Server nicht.

Ursache: N8N_RESTRICT_FILE_ACCESS_TO steht auf /files, der Workflow nutzt aber den Host-Pfad. Lösung: im Workflow den Containerpfad /files/... verwenden und den Mount ./local-files:/files prüfen. Quelle: Setup mit Docker Compose.

Häufige Fragen zu n8n Docker Compose

Brauche ich eine eigene Domain, um n8n mit Docker Compose zu betreiben?

Nein. Für eine einfache Einzelcontainer-Installation genügen ein Volume und der Port 5678, n8n ist dann unter http://localhost:5678 erreichbar. Eine Domain brauchen Sie erst für den Aufbau mit Traefik und automatischem TLS-Zertifikat.

Wo speichert n8n meine Zugangsdaten und Workflows?

Im Volume, das auf /home/node/.n8n zeigt. Dort liegt bei SQLite-Nutzung die Datenbankdatei und unabhängig von der Datenbankwahl der Verschlüsselungsschlüssel. Ohne dieses Volume sind die Daten nach dem nächsten Neuaufbau verloren.

Wie aktualisiere ich n8n ohne Datenverlust?

Die Reihenfolge docker compose pull, docker compose down und docker compose up -d tauscht nur das Image aus. Workflows, Zugangsdaten und Datenbank liegen in den Volumes und bleiben erhalten. Vor größeren Versionssprüngen lohnt ein Blick in die Release-Hinweise.

Kann ich zwischen einer festen n8n-Version und der Beta-Version wählen?

Ja, über den Image-Tag. Ein Tag wie 1.81.0 fixiert eine stabile Version, der Tag next liefert die instabile Beta-Version. Für produktive Server ist ein fixierter Versions-Tag die verlässlichere Wahl.

Simon Glowik, Gründer von NordFlux
Über den Autor

Gründer von NordFlux. Sieben Jahre Erfahrung von Web und SEO bis zur Automatisierung im Konzern-Maßstab, heute pragmatisch für den Mittelstand und mit deutscher Datenhoheit.

Zertifizierungen

  • Microsoft zertifiziert — PL-900 und AZ-900
  • UiPath zertifiziert — Automation Developer Associate
Alle Beiträge
Weiterlesen

Verwandte Anleitungen

Kostenlose Erstanalyse

n8n per Docker Compose installiert, aber ohne Betriebssicherheit?

Postgres statt SQLite, eine saubere .env-Datei und richtig gesetzte Volumes sind die Grundlage, doch erst der laufende Betrieb mit Updates und Backups entscheidet über die Ausfallsicherheit. NordFlux übernimmt den betreuten n8n-Betrieb auf Ihrer Docker-Infrastruktur, mit Monitoring, Updates und getesteten Backups statt Ad-hoc-Wartung. Im ersten Gespräch prüfen wir Ihr aktuelles Setup und zeigen die größten Betriebsrisiken.

n8n Kosten und Lizenzenn8n Hosting in Deutschland

  • PostgreSQL-Migration und Volume-Struktur, die auch bei Wachstum trägt
  • Automatisierte, getestete Backups statt manueller Sicherungskopien
  • Update-Prozess mit Rollback-Option statt Ausfall am Montagmorgen