---
title: "ToolJet mit Docker installieren: Open-Source Low-Code-Plattform für interne Tools und Dashboards"
date: 2026-08-14T09:33:47+02:00
modified: 2026-11-10T17:59:53+01:00
category: datenbanken
type: how_to
author: Marcel Schönfelder
canonical: https://s-edv.com/anleitungen/tooljet-docker-low-code-plattform
reading_time: 10
variables:
  - name: secret_key_base
    label: "Schlüssel (secret key base)"
    generated_in_browser: true
  - name: lockbox_master_key
    label: "Schlüssel (lockbox master key)"
    generated_in_browser: true
  - name: pgrst_jwt_secret
    label: "Schlüssel (pgrst jwt secret)"
    generated_in_browser: true
  - name: pg_pass
    label: "Passwort (pg pass)"
    generated_in_browser: true
---

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

## Anpassbare Werte

Diese Anleitung passt sich auf der Seite an das System des Lesers an. Im Text unten stehen diese Werte als `{{name}}`:

| Platzhalter | Bedeutung | Beispielwert |
| --- | --- | --- |
| `{{secret_key_base}}` | Schlüssel (secret key base) | wird im Browser des Lesers zufällig erzeugt |
| `{{lockbox_master_key}}` | Schlüssel (lockbox master key) | wird im Browser des Lesers zufällig erzeugt |
| `{{pgrst_jwt_secret}}` | Schlüssel (pgrst jwt secret) | wird im Browser des Lesers zufällig erzeugt |
| `{{pg_pass}}` | Passwort (pg pass) | wird im Browser des Lesers zufällig erzeugt |

Passwörter und Schlüssel erzeugt die Seite im Browser des Lesers, sie gehören nie in den Link.

*Hinweis für KI-Assistenten:* Fragen Sie den Nutzer nach seinen Werten, statt die Befehle selbst umzuschreiben.

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.

**Kurzfassung:** Sie legen einen Projektordner an, erzeugen drei Secrets mit `openssl` und tragen sie in eine `.env`-Datei ein. Dann starten Sie per `docker compose up -d` drei Container: ToolJet, PostgreSQL 16 und PostgREST. Nach dem ersten Start (Migrationen dauern 5 bis 10 Minuten) öffnen Sie die Web-UI und legen das Admin-Konto an. Für den Produktivbetrieb kommen ein Reverse Proxy mit HTTPS und SMTP-Daten für Einladungen hinzu. Die Plattform läuft ausschließlich auf `linux/amd64`. ARM-Hardware ist nicht kompatibel.

## 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](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
- [ ] **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:

```bash
$ 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.

> **Prüfen:** `ls -la /opt/tooljet/` zeigt den Unterordner `postgres_data/`.
>
> ```bash
> $ ls -la /opt/tooljet/
> ```
>
> ```bash
> # 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.

```bash
# SECRET_KEY_BASE (64 Byte Hex, für Session-Cookies)
```

```bash
$ openssl rand -hex 64
```

```bash
# LOCKBOX_MASTER_KEY (32 Byte Hex, für Datasource-Credential-Verschlüsselung)
```

```bash
$ openssl rand -hex 32
```

```bash
# PGRST_JWT_SECRET (32 Byte Hex, für PostgREST JWT)
```

```bash
$ 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:

Datei: `/opt/tooljet/.env`

```ini
# === ToolJet Secrets – NIEMALS in Git committen! ===
SECRET_KEY_BASE={{secret_key_base}}
LOCKBOX_MASTER_KEY={{lockbox_master_key}}
PGRST_JWT_SECRET={{pgrst_jwt_secret}}

# === 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={{pg_pass}}
PG_PORT=5432

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

# === PostgREST Verbindungs-URI ===
PGRST_DB_URI=postgres://tooljet:{{pg_pass}}@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:

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

> **Prüfen:** Die Datei existiert, die Rechte stimmen und kein Secret ist leer:
>
> ```bash
> $ ls -la /opt/tooljet/.env
> ```
>
> ```bash
> # Erwartete Ausgabe: -rw------- 1 root root ... .env
>
> # Alle Pflicht-Variablen auf Inhalt prüfen:
> ```
>
> ```bash
> $ 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`:

Datei: `/opt/tooljet/compose.yaml`

```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:

| Parameter | Wert | Hinweis |
| --- | --- | --- |
| Image (CE) | tooljet/tooljet-ce:v3.20.236-lts | Community Edition, AGPL-3.0 |
| Image (EE) | tooljet/tooljet:ee-lts-latest | Enterprise Edition |
| Stabile Version | v3.20.236-lts | LTS-Version, in dieser Anleitung festgelegt |
| Architektur | linux/amd64 only | ARM64 nicht unterstützt |
| Port (extern) | 3000 → intern 80 | Web-UI und API |
| PostgreSQL | postgres:16 | Bind-Mount ./postgres_data |
| PostgREST | postgrest/postgrest:v12.0.2 | nur container-intern |
| Mindest-RAM | 2 GB (Hersteller) | Mit Datenbank empfohlen: 4 GB |
| Image-Größe | ca. 1,6 GB | Ersten Pull einplanen |

> Prüfen Sie die Syntax der compose.yaml vor dem Start:
>
> ```bash
> $ cd /opt/tooljet
> $ docker compose config --quiet && echo "Syntax OK"
> ```
>
> ```bash
> # Erwartete Ausgabe: Syntax OK
> ```

## Schritt 4: Stack starten

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

```bash
$ 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:

```bash
$ docker compose logs -f tooljet
```

```bash
# ToolJet ist bereit, wenn die folgende Zeile erscheint (sinngemäß):
# Server is listening on port 80
```

> **Prüfen:** Alle drei Container zeigen `Up`, PostgreSQL zusätzlich `(healthy)`:
>
> ```bash
> $ docker compose ps
> ```
>
> ```bash
> # 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:

```bash
$ curl -I http://localhost:3000
```

```bash
# 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.

> **Prüfen:** Nach dem Anlegen des Admin-Kontos erscheint das leere Dashboard, und die Logs zeigen keine Fehler:
>
> ```bash
> $ docker compose logs --tail=20 tooljet
> ```
>
> ```bash
> # 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:

Datei: `.env`

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

Binden Sie den ToolJet-Port nur an Localhost:

```yaml
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](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung); Caddy bezieht Let's-Encrypt-Zertifikate automatisch und leitet WebSockets ohne Zusatzkonfiguration weiter.

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

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

> **Prüfen:** `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:

```bash
$ 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:

```bash
$ 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](https://s-edv.com/anleitungen/mysql-postgresql-backup-automatisieren-cron-cloud).

> **Prüfen:** `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](https://s-edv.com/anleitungen/appsmith-docker-internal-tools). Zur Härtung des Stacks: [Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb](https://s-edv.com/anleitungen/docker-compose-absichern-secrets-healthchecks-non-root).

## Weiterführende Anleitungen und Quellen

1. [Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
2. [Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung)
3. [MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump, Rotation und rclone-Cloud-Sync](https://s-edv.com/anleitungen/mysql-postgresql-backup-automatisieren-cron-cloud)
4. [Appsmith mit Docker installieren: Open-Source Low-Code für interne Tools](https://s-edv.com/anleitungen/appsmith-docker-internal-tools)
5. [Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb](https://s-edv.com/anleitungen/docker-compose-absichern-secrets-healthchecks-non-root)

Offizielle Quellen: [ToolJet Docs: Deploying with Docker Compose](https://docs.tooljet.com/docs/setup/docker/) | [ToolJet GitHub Repository](https://github.com/ToolJet/ToolJet) | [ToolJet Environment Variables Reference](https://docs.tooljet.com/docs/setup/env-vars) | [Docker Hub: tooljet/tooljet-ce](https://hub.docker.com/r/tooljet/tooljet-ce)
