Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 18.09.2026 · 10 min Lesezeit

Baserow mit Docker Compose selbst hosten: Airtable-Alternative für KMU

Baserow 2.4.0 mit der offiziellen Mehr-Container-Compose-Datei betreiben: Dateien vom Release-Tag, Pflichtwerte in der .env, Caddy nur an 127.0.0.1, Reverse Proxy, getestetes Backup mit Restore und Update.

Geprüft am 14.10.2026 · für baserow 2.4.0

WerbelinksMit * 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

Aufgeräumter Schreibtisch mit farbigen Karteikästen voller leerer Karteikarten, Holzschubladen und einem kompakten Mini-PC am Fenster

Baserow ist eine No-Code-Datenbank mit Weboberfläche: Fachabteilungen legen Tabellen mit Feldtypen und Verknüpfungen an, teilen Formulare zur Dateneingabe und automatisieren einfache Abläufe, ohne dass die IT für jede neue Spalte ein Ticket bearbeitet. Die Daten liegen in einer eigenen PostgreSQL-Datenbank. Diese Anleitung zeigt den Betrieb von Baserow 2.4.0 mit der offiziellen Mehr-Container-Compose-Datei auf einem Linux-Server, mit Port nur an 127.0.0.1, Reverse Proxy mit HTTPS, getestetem Backup und Update.

Voraussetzungen

  • Server: Linux-VPS oder Mini-PC mit 2 CPU-Kernen und 4 GB RAM, x86_64 oder ARM64. Im Test belegte der Stack im Leerlauf rund 2,8 GB RAM, davon allein Backend und Celery-Worker über 2 GB. 4 GB sind daher die Untergrenze.
  • Speicher: mindestens 10 GB frei. Die Images belegen zusammen rund 3 GB, dazu kommen Datenbank und hochgeladene Dateien.
  • Software: Debian 12/13 oder Ubuntu 24.04 mit Docker Engine und Compose-Plugin. Die Doku nennt Docker 19.03 als Minimum, aktuelle Versionen sind empfehlenswert.
  • Netz: ein DNS-Name wie baserow.example.de und ein Reverse Proxy mit TLS-Zertifikat.
  • Lizenz: Der Kern steht unter MIT-Lizenz. Als Premium und Enterprise gekennzeichnete Funktionen, etwa erweiterte Rollen, SSO per SAML und Audit-Log, benötigen einen kostenpflichtigen Lizenzschlüssel.

Das Projekt empfiehlt für die meisten Nutzer das einfachere All-in-one-Image baserow/baserow mit einem Container. Diese Anleitung verwendet die Mehr-Container-Variante, weil sie Datenbank, Redis und Worker getrennt zeigt und sich besser überwachen und sichern lässt.

DienstImageAufgabe
caddycaddy:2.11.4Interner Proxy, verteilt auf Backend und Frontend, liefert Medien aus
backendbaserow/backend:2.4.0REST-API, Migrationen beim Start
web-frontendbaserow/web-frontend:2.4.0Weboberfläche
celery, celery-export-worker, celery-beat-workerbaserow/backend:2.4.0Hintergrundaufgaben, Exporte, zeitgesteuerte Jobs
dbpgvector/pgvector:pg15PostgreSQL 15 mit pgvector, Volume pgdata
redisredis:6Warteschlange und Cache, mit Passwort
volume-permissions-fixerbash:4.4Setzt einmalig UID 9999 auf das Volume media

Schritt 1: Dateien aus dem Release-Tag laden

Laden Sie die drei Dateien aus dem Tag 2.4.0 statt aus dem Zweig master. So passen Compose-Datei, Caddy-Konfiguration und Image-Version zusammen, und ein späterer Download zieht nicht unbemerkt eine neuere Version. Das Caddyfile ist Pflicht: Die Compose-Datei bindet es aus dem Projektordner ein.

sudo mkdir -p /opt/baserow && cd /opt/baserow
V=2.4.0
sudo curl -fsSLo docker-compose.yml https://raw.githubusercontent.com/baserow/baserow/$V/docker-compose.yml
sudo curl -fsSLo Caddyfile https://raw.githubusercontent.com/baserow/baserow/$V/Caddyfile
sudo curl -fsSLo .env https://raw.githubusercontent.com/baserow/baserow/$V/.env.example
sudo chmod 600 .env

Die Compose-Datei ist rund 600 Zeilen lang. Schreiben Sie sie nicht ab und kürzen Sie sie nicht: Sie enthält im Block x-backend-variables alle Variablen, die Backend und Worker gemeinsam nutzen.

Verifizieren: ls -la /opt/baserow zeigt docker-compose.yml, Caddyfile und .env. grep -c image: docker-compose.yml liefert eine zweistellige Zahl, grep 'BASEROW_VERSION:-' docker-compose.yml | head -1 zeigt 2.4.0.

Schritt 2: .env mit Pflichtwerten und lokaler Bindung

Drei Werte sind in der Compose-Datei mit :? als Pflicht markiert, ohne sie bricht jeder Befehl ab. Die Beispieldatei empfiehlt zusätzlich einen eigenen BASEROW_JWT_SIGNING_KEY. Erzeugen Sie alle vier Werte zufällig mit dem Befehl aus der Beispieldatei:

cd /opt/baserow
for k in SECRET_KEY BASEROW_JWT_SIGNING_KEY DATABASE_PASSWORD REDIS_PASSWORD; do
  v=$(tr -dc 'a-z0-9' < /dev/urandom | head -c 50)
  sudo sed -i "s|^#\? \?$k=.*|$k=$v|" .env
done

Ergänzen oder ändern Sie danach in der .env diese Zeilen:

BASEROW_VERSION=2.4.0
BASEROW_PUBLIC_URL=https://baserow.example.de
HOST_PUBLISH_IP=127.0.0.1
WEB_FRONTEND_PORT=8080
WEB_FRONTEND_SSL_PORT=8443
BASEROW_ENABLE_SECURE_PROXY_SSL_HEADER=true

Ohne HOST_PUBLISH_IP veröffentlicht Caddy die Ports 80 und 443 auf allen Schnittstellen. Die Baserow-Dokumentation warnt ausdrücklich, dass Docker dabei Regeln der ufw-Firewall umgeht. BASEROW_PUBLIC_URL muss exakt der Adresse entsprechen, die Nutzer im Browser eingeben. Der interne Caddy leitet nur Anfragen weiter, deren Hostname in dieser Adresse oder in BASEROW_EXTRA_PUBLIC_URLS steht.

Verifizieren: docker compose config --quiet endet ohne Ausgabe. docker compose config --images zeigt baserow/backend:2.4.0, baserow/web-frontend:2.4.0, caddy:2.11.4, pgvector/pgvector:pg15 und redis:6. docker compose config | grep published zeigt nur host_ip: 127.0.0.1.

Schritt 3: Stack starten und Migrationen abwarten

cd /opt/baserow
docker compose pull
docker compose up -d
docker compose ps --format 'table {{.Service}}\t{{.Status}}'
docker compose logs -f backend

Beim ersten Start führt das Backend alle Datenbankmigrationen aus, auch die der Premium- und Enterprise-Module. In dieser Zeit steht das Backend auf health: starting oder unhealthy. Starten Sie in dieser Phase nichts neu, ein Neustart verlängert den Vorgang nur.

Im Test auf 2 Kernen und 8 GB RAM dauerte der Download der Images rund 35 Sekunden, bis das Backend healthy meldete vergingen gut 3 Minuten. Das Protokoll zeigte dabei über 600 Migrationsschritte.

Den Health-Endpunkt prüfen Sie mit dem Hostnamen aus BASEROW_PUBLIC_URL, sonst leitet der interne Caddy die Anfrage nicht weiter:

curl -s -H 'Host: baserow.example.de' http://127.0.0.1:8080/api/_health/

Verifizieren: Alle Dienste außer volume-permissions-fixer (einmaliger Lauf, danach Exited (0)) stehen auf healthy oder Up, und der Health-Endpunkt antwortet mit OK.

Schritt 4: Ersten Administrator anlegen

Eine frische Instanz hat keinen Benutzer. Der erste Aufruf zeigt eine Registrierungsseite, und das erste registrierte Konto erhält Administratorrechte. Registrieren Sie sich deshalb direkt nach dem Start, bevor die Instanz über den Proxy erreichbar ist. Prüfen Sie danach unter Admin-Werkzeuge, Einstellungen, ob neue Registrierungen erlaubt bleiben sollen.

Die Registrierung ist auch per API möglich, was sich für automatisierte Tests eignet. Die Antwort enthält ein Zugriffstoken, weitere API-Aufrufe senden es im Header Authorization: JWT <token>:

curl -s -X POST -H 'Host: baserow.example.de' -H 'Content-Type: application/json' \
  -d '{"name":"Admin","email":"admin@example.de","password":"LANGES_PASSWORT","authenticate":true}' \
  http://127.0.0.1:8080/api/user/

Im Test lieferte die Registrierung "is_staff": true. Eine zweite Registrierung ohne Anmeldung gelang danach ebenfalls mit HTTP 200: Die Registrierung bleibt offen, bis Sie sie in den Admin-Einstellungen abschalten.

Formulare, die Sie später öffentlich teilen, sind über eine Adresse mit zufälliger Kennung erreichbar. Jeder, der die Adresse kennt, kann Datensätze anlegen. Für Formulare mit personenbezogenen Daten aktivieren Sie den Passwortschutz der Ansicht.

Verifizieren: In der Antwort steht beim Benutzer "is_staff": true. Nach der Anmeldung im Browser erscheint im linken Menü der Bereich Admin-Werkzeuge.

Schritt 5: Reverse Proxy mit HTTPS

Die Compose-Datei empfiehlt, einen eigenen Proxy einfach auf den internen Caddy weiterzuleiten, weil dieser das Routing von /api/, /ws/ und /media/ bereits richtig erledigt. Ein Nginx-Beispiel mit WebSocket-Unterstützung für die Echtzeitaktualisierung:

server {
    listen 443 ssl;
    http2 on;
    server_name baserow.example.de;
    ssl_certificate     /etc/letsencrypt/live/baserow.example.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/baserow.example.de/privkey.pem;
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s;
    }
}

Wichtig ist proxy_set_header Host $host: Ohne den öffentlichen Hostnamen erkennt der interne Caddy die Anfrage nicht als Baserow-Anfrage. Grundlagen zu Nginx und Zertifikaten finden Sie in Nginx als Reverse Proxy mit TLS.

Verifizieren: sudo nginx -t meldet syntax is ok. curl -s https://baserow.example.de/api/_health/ liefert OK. Eine Änderung in einer Tabelle erscheint in einem zweiten Browserfenster ohne Neuladen.

Schritt 6: Backup und Wiederherstellung

Zu sichern sind die Datenbank und das Volume media mit hochgeladenen Dateien. Die Doku beschreibt einen eingebauten Befehl, der eine Datenbank sichert, die gerade nicht benutzt wird. Stoppen Sie daher vorher die Anwendungsdienste. Der Sicherungsordner muss der UID 9999 gehören:

cd /opt/baserow
sudo mkdir -p /opt/baserow-backup && sudo chown 9999:9999 /opt/baserow-backup
docker compose stop caddy backend web-frontend celery celery-export-worker celery-beat-worker
docker compose run --rm -v /opt/baserow-backup:/baserow/backups backend backup -f /baserow/backups/baserow_backup.tar.gz
docker run --rm -v baserow_media:/data:ro -v /opt/baserow-backup:/backup alpine tar czf /backup/media.tgz -C /data .
docker compose up -d

Der Volume-Name baserow_media ergibt sich aus dem Ordnernamen /opt/baserow. Prüfen Sie ihn mit docker volume ls.

Die Wiederherstellung erfolgt laut Doku in eine neue, leere Datenbank, nicht über eine bestehende. Bei gleichem Datenbanknamen löschen Sie die alte Datenbank vorher:

cd /opt/baserow
docker compose stop caddy backend web-frontend celery celery-export-worker celery-beat-worker
docker compose exec -T db psql -U baserow -d postgres -c 'DROP DATABASE baserow;' -c 'CREATE DATABASE baserow OWNER baserow;'
docker compose run --rm -v /opt/baserow-backup:/baserow/backups backend restore -f /baserow/backups/baserow_backup.tar.gz
docker run --rm -v baserow_media:/data -v /opt/baserow-backup:/backup alpine sh -c 'tar xzf /backup/media.tgz -C /data && chown -R 9999:9999 /data'
docker compose up -d

Im Test ergab die Sicherung einer frischen Instanz ein Archiv von 1,1 MB, der Befehl endet mit Successfully backed up Baserow. Eine nach dem Backup angelegte Tabelle „NachBackup“ war nach der Wiederherstellung verschwunden, die Tabelle aus der Zeit davor und die Anmeldung funktionierten, der Health-Endpunkt meldete nach rund 20 Sekunden wieder OK.

Verifizieren: ls -lh /opt/baserow-backup zeigt beide Archive. Nach der Wiederherstellung listet docker compose exec -T db psql -U baserow -d baserow -tAc 'select name from database_table order by id;' genau die Tabellen vom Zeitpunkt des Backups, und die Anmeldung mit den alten Zugangsdaten funktioniert.

Schritt 7: Updates einspielen

Ein Update besteht aus neuen Dateien vom neuen Release-Tag und einem Neustart. Das Backend migriert das Schema beim Start automatisch. Prüfen Sie vorher die Release Notes und legen Sie ein Backup nach Schritt 6 an.

cd /opt/baserow
V=NEUE_VERSION
sudo curl -fsSLo docker-compose.yml https://raw.githubusercontent.com/baserow/baserow/$V/docker-compose.yml
sudo curl -fsSLo Caddyfile https://raw.githubusercontent.com/baserow/baserow/$V/Caddyfile
sudo sed -i "s|^BASEROW_VERSION=.*|BASEROW_VERSION=$V|" .env
docker compose pull
docker compose up -d
docker compose logs -f backend

Ein Zurückstellen der Version nach der Migration ist kein Rollback, die ältere Anwendung kennt das neuere Schema nicht. Der Weg zurück ist das alte Image zusammen mit dem Backup vor dem Update. Für einen Wechsel der PostgreSQL-Hauptversion beschreibt die Doku einen eigenen Weg über das Image pgautoupgrade, das in der Compose-Datei auskommentiert bereitsteht.

Verifizieren: docker compose config --images zeigt die neue Version, alle Dienste werden wieder healthy, und /api/settings/ liefert JSON.

Typische Fehler

SymptomUrsacheLösung
required variable REDIS_PASSWORD is missing a valuePflichtwert in .env leer oder .env liegt nicht neben der Compose-DateiSchritt 2 wiederholen, docker compose config --quiet
Aufruf über IP liefert HTTP 404 mit "statusMessage": "Server Error"Hostname der Anfrage passt nicht zu BASEROW_PUBLIC_URLMit dem öffentlichen Namen aufrufen, im Proxy Host $host setzen oder BASEROW_EXTRA_PUBLIC_URLS ergänzen
Backend minutenlang unhealthy nach Start oder UpdateMigrationen laufen nochdocker compose logs -f backend beobachten, nicht neu starten
Uploads schlagen fehl, Rest funktioniertVolume oder Hostordner gehört nicht UID 9999chown -R 9999:9999 auf das Medienverzeichnis
Oberfläche aktualisiert sich nicht liveProxy leitet WebSocket nicht weiterUpgrade- und Connection-Header ergänzen
PermissionError: [Errno 13] Permission denied: '/baserow/backups/...' beim BackupSicherungsordner gehört nicht UID 9999chown 9999:9999 auf den Ordner

Häufige Fragen

All-in-one oder mehrere Container?

Das Projekt empfiehlt für die meisten Nutzer baserow/baserow mit einem Container und einem Volume. Die Mehr-Container-Variante lohnt sich, wenn Sie Datenbank und Worker getrennt überwachen, skalieren oder eine externe PostgreSQL-Instanz nutzen wollen.

Kann ich direkt per SQL auf die Tabellen zugreifen?

Lesen ist technisch möglich, das interne Schema ist aber ein Implementierungsdetail und kann sich mit Versionen ändern. Der vorgesehene Weg für Integrationen ist die REST-API.

Brauche ich den Mailversand?

Für Passwort-Zurücksetzen, Einladungen und Benachrichtigungen ja. Die Variablen EMAIL_SMTP_* stehen in der .env.example.

Welche Funktionen kosten Geld?

Premium- und Enterprise-Funktionen wie SSO per SAML, Audit-Log und erweiterte Rollen. Tabellen, Ansichten, Formulare, Automatisierungen und die API gehören zum freien Kern.

Fazit

Baserow liefert eine solide Grundlage für strukturierte Daten im eigenen Haus, ist aber kein Einzelcontainer: acht Dienste, rund 3 GB Images und ein erster Start von mehreren Minuten gehören dazu. Mit Dateien vom Release-Tag, lokaler Bindung, einem Proxy mit korrektem Host-Header und einem getesteten Backup läuft der Stack berechenbar. Wer nur eine schlanke Tabellenoberfläche über einer bestehenden Datenbank braucht, prüft vorher leichtere Werkzeuge wie NocoDB.

Weiterführende Anleitungen und Quellen

BaserowDocker ComposeSelfhostingAirtable-AlternativeDatenbankBackupPostgreSQL