Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Datenbanken 14.08.2026 · 10 min Lesezeit Geprüft 01.10.2026

ToolJet mit Docker installieren: Open-Source Low-Code-Plattform für interne Tools und Dashboards

ToolJet ist eine Open-Source-Low-Code-Plattform für interne Tools, Dashboards und Business-Apps mit über 80 Datenquellen. Die Anleitung zeigt die Installation von ToolJet v3.20 LTS mit Docker Compose, PostgreSQL und PostgREST auf einem Linux-Host.

Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Titelbild: ToolJet mit Docker installieren, Interne Tools, Dashboards, Daten

ToolJet ist eine Low-Code-Plattform (AGPL-3.0) für Admin-Panels, CRUD-Oberflächen (Anlegen, Lesen, Ändern, Löschen von Datensätzen) und Freigabe-Workflows. Sie verbindet per Drag-and-Drop über 80 Datenquellen, von PostgreSQL und MySQL über REST- und GraphQL-APIs bis zu S3, und erzeugt daraus Web-Anwendungen. Diese Anleitung zeigt, wie Sie ToolJet v3.20 LTS auf einem Linux-Host per Docker Compose aufsetzen.

Voraussetzungen

  • Linux-Host oder VM mit x86_64-Architektur (kein ARM64, kein Apple Silicon ohne Rosetta-Emulation); Ubuntu 22.04 LTS oder Debian 12 empfohlen
  • Docker Engine ≥ 20.10 und Docker Compose Plugin v2 (docker compose, nicht das veraltete docker-compose); falls noch nicht installiert: Docker und Docker Compose auf Linux installieren
  • Mindestens 1 vCPU und 2 GB RAM laut Hersteller; mit PostgreSQL und PostgREST auf demselben Host planen Sie 2 vCPUs und 4 GB RAM ein
  • Mindestens 8 GB freier Festplattenspeicher (das ToolJet-Image allein ist rund 1,6 GB groß)
  • Für Ihre Nutzer erreichbare IP-Adresse oder Domain für die TOOLJET_HOST-Variable (inklusive Protokoll, z. B. http://192.168.1.10:3000)
  • openssl auf dem Host installiert (auf Ubuntu/Debian standardmäßig vorhanden)
  • Optional: SMTP-Zugangsdaten für E-Mail-Einladungen, Domain und SSL-Zertifikat für HTTPS hinter einem Reverse Proxy

Schritt 1: Projektordner anlegen

Legen Sie einen eigenen Ordner für den ToolJet-Stack an; Konfiguration und Datenbank-Bind-Mount liegen hier:

$ mkdir -p /opt/tooljet
$ cd /opt/tooljet
$ mkdir postgres_data

Die Herstellervorlage legt postgres_data ebenfalls vor dem ersten Start an; so ist klar, wo die Datenbankdateien liegen.

ls -la /opt/tooljet/ zeigt den Unterordner postgres_data/.

$ ls -la /opt/tooljet/
# Erwartete Ausgabe:
# drwxr-xr-x  3 root root 4096 Jun 11 10:00 .
# drwxr-xr-x 12 root root 4096 Jun 11 10:00 ..
# drwxr-xr-x  2 root root 4096 Jun 11 10:00 postgres_data

Schritt 2: Secrets erzeugen und .env anlegen

ToolJet benötigt drei Secrets, die Sie einmalig vor dem ersten Start erzeugen. Ändern Sie sie danach nicht mehr, sonst werden gespeicherte Datenquellen-Zugangsdaten und Sitzungen ungültig.

# SECRET_KEY_BASE (64 Byte Hex, für Session-Cookies)
$ openssl rand -hex 64
# LOCKBOX_MASTER_KEY (32 Byte Hex, für Datasource-Credential-Verschlüsselung)
$ openssl rand -hex 32
# PGRST_JWT_SECRET (32 Byte Hex, für PostgREST JWT)
$ openssl rand -hex 32

Tragen Sie die drei Ausgaben in eine neue Datei /opt/tooljet/.env ein und ersetzen Sie alle Platzhalter. Die ToolJet-Anwendungsdaten (PG_DB) und die ToolJet-Datenbank für eigene Tabellen (TOOLJET_DB) liegen wie in der Herstellervorlage in zwei getrennten Datenbanken derselben Instanz; ToolJet legt tooljet_db beim Start selbst an:

# === ToolJet Secrets – NIEMALS in Git committen! ===
SECRET_KEY_BASE=IHR_64BYTE_HEX_WERT
LOCKBOX_MASTER_KEY=IHR_32BYTE_HEX_WERT
PGRST_JWT_SECRET=IHR_ZWEITER_32BYTE_HEX_WERT

# === ToolJet Host: Adresse, unter der Nutzer ToolJet aufrufen ===
TOOLJET_HOST=http://192.168.1.10:3000

# === PostgreSQL-Zugangsdaten ===
PG_HOST=postgres
PG_DB=tooljet_production
PG_USER=tooljet
PG_PASS=sicheres_passwort_hier
PG_PORT=5432

# === ToolJet-Datenbank (gleiche Instanz, eigene Datenbank) ===
TOOLJET_DB=tooljet_db
TOOLJET_DB_HOST=postgres
TOOLJET_DB_USER=tooljet
TOOLJET_DB_PASS=sicheres_passwort_hier
TOOLJET_DB_PORT=5432

# === PostgREST Verbindungs-URI ===
PGRST_DB_URI=postgres://tooljet:sicheres_passwort_hier@postgres:5432/tooljet_db

# === Optionale Härtung ===
DISABLE_TOOLJET_TELEMETRY=true
DISABLE_SIGNUPS=true

Schützen Sie die Datei vor unbefugtem Zugriff und halten Sie sie aus Git-Repositories heraus:

$ chmod 600 /opt/tooljet/.env
$ echo ".env" >> /opt/tooljet/.gitignore

Die Datei existiert, die Rechte stimmen und kein Secret ist leer:

$ ls -la /opt/tooljet/.env
# Erwartete Ausgabe: -rw------- 1 root root ... .env

# Alle Pflicht-Variablen auf Inhalt prüfen:
$ grep -E "^(SECRET_KEY_BASE|LOCKBOX_MASTER_KEY|PGRST_JWT_SECRET)=" /opt/tooljet/.env

Schritt 3: compose.yaml erstellen

Der Stack besteht aus tooljet (App und Frontend), postgres (Datenbank) und postgrest (interner REST-Layer für die ToolJet-Datenbank).

Zum Image: tooljet/tooljet-ce ist die Community Edition unter AGPL-3.0, tooljet/tooljet die Enterprise Edition mit SAML SSO und Audit-Logs. Die Anleitung legt das Image auf die LTS-Version v3.20.236-lts fest; gleitende Tags wie ce-lts-latest oder latest ziehen bei jedem Pull unkontrolliert neue Versionen.

Erstellen Sie die Datei /opt/tooljet/compose.yaml:

services:
  tooljet:
    image: tooljet/tooljet-ce:v3.20.236-lts
    platform: linux/amd64
    restart: always
    tty: true
    stdin_open: true
    ports:
      - "3000:80"
    env_file:
      - .env
    environment:
      SERVE_CLIENT: "true"
      PORT: "80"
    command: npm run start:prod
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - logs:/app/logs
      - certs:/app/certs
      - fallbackcerts:/app/fallbackcerts

  postgres:
    image: postgres:16
    restart: always
    environment:
      POSTGRES_USER: ${PG_USER}
      POSTGRES_PASSWORD: ${PG_PASS}
      POSTGRES_DB: ${PG_DB}
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${PG_USER} -d ${PG_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  postgrest:
    image: postgrest/postgrest:v12.0.2
    platform: linux/amd64
    restart: always
    environment:
      PGRST_DB_URI: ${PGRST_DB_URI}
      PGRST_JWT_SECRET: ${PGRST_JWT_SECRET}
      PGRST_SERVER_PORT: "80"
      PGRST_DB_PRE_CONFIG: postgrest.pre_config
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  logs:
  certs:
  fallbackcerts:

Beachte: Der postgres_data-Ordner wird als Bind-Mount (./postgres_data:/var/lib/postgresql/data) und nicht als Named Volume eingebunden. So liegen die Daten sichtbar im Projektordner und bleiben auch bei einem versehentlichen docker compose down -v erhalten.

Die Eckdaten im Überblick:

ParameterWertHinweis
Image (CE)tooljet/tooljet-ce:v3.20.236-ltsCommunity Edition, AGPL-3.0
Image (EE)tooljet/tooljet:ee-lts-latestEnterprise Edition
Stabile Versionv3.20.236-ltsLTS-Version, in dieser Anleitung festgelegt
Architekturlinux/amd64 onlyARM64 nicht unterstützt
Port (extern)3000 → intern 80Web-UI und API
PostgreSQLpostgres:16Bind-Mount ./postgres_data
PostgRESTpostgrest/postgrest:v12.0.2nur container-intern
Mindest-RAM2 GB (Hersteller)Mit Datenbank empfohlen: 4 GB
Image-Größeca. 1,6 GBErsten Pull einplanen

Prüfen Sie die Syntax der compose.yaml vor dem Start:

$ cd /opt/tooljet
$ docker compose config --quiet && echo "Syntax OK"
# Erwartete Ausgabe: Syntax OK

Schritt 4: Stack starten

Starten Sie den Stack im Hintergrund; der erste Pull des ToolJet-Images dauert einige Minuten:

$ cd /opt/tooljet
$ docker compose up -d

Beim allerersten Start führt ToolJet automatisch alle Datenbankmigrationen durch. Dieser Prozess dauert 5 bis 10 Minuten. Starten Sie den Container in dieser Zeit nicht neu, sonst brechen die Migrationen ab. Den Fortschritt zeigen die Logs:

$ docker compose logs -f tooljet
# ToolJet ist bereit, wenn die folgende Zeile erscheint (sinngemäß):
# Server is listening on port 80

Alle drei Container zeigen Up, PostgreSQL zusätzlich (healthy):

$ docker compose ps
# Erwartete Ausgabe:
# NAME                IMAGE                              STATUS
# tooljet-tooljet-1   tooljet/tooljet-ce:v3.20.236-lts   Up X minutes
# tooljet-postgres-1  postgres:16                        Up X minutes (healthy)
# tooljet-postgrest-1 postgrest/postgrest:v12.0.2        Up X minutes

Prüfen Sie zusätzlich, ob ToolJet antwortet:

$ curl -I http://localhost:3000
# Erwartete Ausgabe: HTTP/1.1 200 OK (oder 302 Found zur Login-Seite)

Schritt 5: Erst-Einrichtung im Browser

Öffnen Sie http://<IHRE-IP>:3000 im Browser. Beim ersten Aufruf legen Sie im Einrichtungsassistenten das erste Admin-Konto an. Anschließend stehen im Dashboard folgende Funktionen bereit:

  1. Apps erstellen: per Drag-and-Drop im visuellen App-Builder
  2. Datenquellen verbinden: über „Data Sources“ im linken Menü (PostgreSQL, REST-API, MySQL, MongoDB, S3, Stripe und 75+ weitere)
  3. Nutzer einladen: über „Settings → Users“ (setzt SMTP-Konfiguration voraus)
  4. Workspaces verwalten: mehrere getrennte Arbeitsbereiche

Mit DISABLE_SIGNUPS=true registrieren sich neue Benutzer nur noch per Einladung; das ist für produktive Installationen der richtige Ansatz.

Nach dem Anlegen des Admin-Kontos erscheint das leere Dashboard, und die Logs zeigen keine Fehler:

$ docker compose logs --tail=20 tooljet
# Keine Zeilen mit ERROR oder FATAL sollten erscheinen

Schritt 6: Reverse Proxy und HTTPS (optional, empfohlen)

Für den Produktivbetrieb gehört ToolJet hinter einen Reverse Proxy mit HTTPS. Passen Sie dazu die .env an:

TOOLJET_HOST=https://tooljet.ihre-domain.de

Binden Sie den ToolJet-Port nur an Localhost:

ports:
  - "127.0.0.1:3000:80"

Der Reverse Proxy muss WebSocket-Verbindungen weiterleiten (Upgrade- und Connection-Header), sonst funktionieren Echtzeit-Features in der UI nicht. Eine Einstiegsanleitung bietet Caddy als Reverse Proxy mit automatischem HTTPS; Caddy bezieht Let's-Encrypt-Zertifikate automatisch und leitet WebSockets ohne Zusatzkonfiguration weiter.

Erstellen Sie nach jeder Änderung an der .env den Container neu:

$ docker compose up -d --force-recreate tooljet

curl -I https://tooljet.ihre-domain.de liefert 200 ohne Zertifikatsfehler, ToolJet leitet nicht auf http:// um, und der App-Builder öffnet sich ohne Verbindungsfehler (WebSockets).

Schritt 7: Updates und Backup

Legen Sie vor jedem Update ein Backup beider Datenbanken an:

$ cd /opt/tooljet
$ docker compose exec -T postgres pg_dump -U tooljet tooljet_production > backup_app_$(date +%Y%m%d).sql
$ docker compose exec -T postgres pg_dump -U tooljet tooljet_db > backup_tjdb_$(date +%Y%m%d).sql

Für das Update tragen Sie das neue LTS-Tag aus Docker Hub in die compose.yaml ein; die Migrationen laufen beim Start automatisch:

$ docker compose pull
$ docker compose up -d

Alternativ sichern Sie das Verzeichnis postgres_data bei gestopptem Stack. Automatisierte Offsite-Backups mit pg_dump und rclone beschreibt die Anleitung MySQL & PostgreSQL Backup automatisieren mit cron.

ls -lh backup_*.sql zeigt zwei nicht leere Dumps, docker compose images das neue Tag, und docker compose ps alle drei Container als Up.

Troubleshooting / Typische Fehler

Container startet nicht, postgres_data-Fehler

Tritt mit der Herstellervorlage auf, die den Ordner als Bind-Volume (driver_opts) einbindet und ihn nicht selbst anlegt. Ordner anlegen (mkdir /opt/tooljet/postgres_data) und docker compose up -d erneut ausführen.

OAuth/SAML-Redirect schlägt fehl, falsche Weiterleitungs-URL

TOOLJET_HOST ist ohne Protokoll gesetzt oder zeigt auf die falsche IP. Immer http:// oder https:// voranstellen und die korrekte öffentlich erreichbare Adresse verwenden. Nach Änderung docker compose up -d --force-recreate tooljet.

Kryptofehler beim Start / App zeigt leere Seite

SECRET_KEY_BASE oder LOCKBOX_MASTER_KEY sind leer oder wurden nachträglich geändert. Bei bestehenden Daten nicht mehr ändern. Prüfen mit docker compose exec tooljet env | grep SECRET_KEY_BASE.

PostgREST crasht in Schleife

PGRST_DB_URI zeigt auf falsche Datenbank oder Zugangsdaten stimmen nicht. URI-Format prüfen: postgres://tooljet:passwort@postgres:5432/tooljet_db. PostgreSQL-Healthcheck abwarten.

Container startet nicht auf ARM64 / Apple Silicon (Exec format error)

ToolJet unterstützt offiziell nur linux/amd64. Auf Apple Silicon hilft platform: linux/amd64 (Emulation) nur für Tests.

Sehr langsamer erster Start (5 bis 10 Minuten)

Normal, die Migrationen laufen. Logs beobachten, nicht neu starten.

E-Mail-Einladungen kommen nicht an

SMTP-Variablen fehlen in der .env. DEFAULT_FROM_EMAIL, SMTP_DOMAIN, SMTP_PORT, SMTP_USERNAME und SMTP_PASSWORD eintragen und Stack neu starten.

Workflows funktionieren nicht bei mehreren Instanzen

Workflows benötigen bei mehreren Worker-Instanzen einen externen Redis. Einen Redis-Container hinzufügen und REDIS_HOST/REDIS_PORT in der .env setzen.

.env versehentlich committed

Aus dem Repository-Verlauf entfernen, PGRST_JWT_SECRET und Datenbankpasswort ersetzen; bei LOCKBOX_MASTER_KEY und SECRET_KEY_BASE vorher gespeicherte Zugangsdaten sichern, da ein Wechsel sie ungültig macht.

Häufige Fragen

Welchen Image-Tag soll ich verwenden: ce-lts-latest, ee-lts-latest oder latest?

Für den Open-Source-Betrieb tooljet/tooljet-ce, für Enterprise-Features wie SAML SSO oder Audit-Log tooljet/tooljet (proprietäre Lizenzteile). In beiden Fällen ein festes LTS-Tag wie v3.20.236-lts verwenden; ce-lts-latest und latest lösen bei jedem Pull ungeplante Updates und Migrationen aus.

Wie groß sind die Systemanforderungen wirklich?

Der Hersteller nennt 1 vCPU, 2 GB RAM und 8 GiB Speicher für eine VM, x86-64, Ubuntu 22.04 oder neuer. Mit PostgreSQL und PostgREST auf demselben Host sind 2 vCPUs und 4 GB RAM eine sinnvolle Größe für ein kleines Team.

Kann ich ToolJet hinter einem Reverse Proxy mit HTTPS betreiben?

Ja, das ist der empfohlene Weg; die Einstellungen stehen in Schritt 6. Wichtig ist die WebSocket-Weiterleitung, sonst funktioniert der App-Builder nicht korrekt.

Was ist der Unterschied zwischen ToolJet DB und der PostgreSQL-Datenbank?

ToolJet nutzt PostgreSQL als App-Datenbank (Konfiguration, Apps, Benutzer) und als ToolJet DB: eine integrierte Datenbank, in der Sie direkt aus ToolJet-Apps Tabellen anlegen und abfragen, ohne eine externe Datenquelle zu konfigurieren. PostgREST stellt diese zweite Datenbank per REST bereit.

Wie deaktiviere ich die öffentliche Registrierung?

DISABLE_SIGNUPS=true in der .env setzen und den Container mit docker compose up -d --force-recreate tooljet neu erstellen. Danach registrieren sich neue Nutzer nur per Einladung.

Wie sichere ich die Daten bei einem Update ab?

Mit den beiden pg_dump-Befehlen aus Schritt 7 oder bei gestopptem Stack per rsync auf ./postgres_data. Verwenden Sie nie docker compose down -v; das Flag löscht die Named Volumes.

Fazit

ToolJet liefert interne Admin-Panels, CRUD-Oberflächen und Dashboards mit wenig eigenem Code, weil über 80 Konnektoren die Anbindung übernehmen. Die Installation dauert etwa 30 Minuten; entscheidend sind die drei Secrets und ein korrektes TOOLJET_HOST. Gegenüber Retool bleiben die Daten auf Ihrem Server. Einschränkungen: keine ARM-Unterstützung und ein langer erster Start. Für den Produktivbetrieb gehören Reverse Proxy mit HTTPS und automatische pg_dump-Backups dazu.

Eine Alternative mit ähnlichem Ansatz ist Appsmith mit Docker. Zur Härtung des Stacks: Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
  2. Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
  3. MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump, Rotation und rclone-Cloud-Sync
  4. Appsmith mit Docker installieren: Open-Source Low-Code für interne Tools
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb

Offizielle Quellen: ToolJet Docs: Deploying with Docker Compose | ToolJet GitHub Repository | ToolJet Environment Variables Reference | Docker Hub: tooljet/tooljet-ce