PLANKA 2.2.1 mit Docker Compose installieren und sicher betreiben
PLANKA 2.2.1 mit Docker Compose betreiben: offizielle Vorlage mit eigenem SECRET_KEY, Zustimmung zu den Nutzungsbedingungen, Reverse Proxy mit WebSocket, getestetes Backup mit Wiederherstellung und Update.
Geprüft am 14.10.2026 · für planka 2.2.1
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

PLANKA ist ein selbst gehostetes Kanban-Board für Teams: Projekte enthalten Boards, Boards enthalten Listen, Listen enthalten Karten mit Beschreibung, Kommentaren, Anhängen, Fälligkeiten und Zeiterfassung. Änderungen erscheinen per WebSocket sofort bei allen angemeldeten Nutzern. Diese Anleitung zeigt den Betrieb von PLANKA 2.2.1 mit Docker Compose auf einem Linux-Server: Konfiguration nach der offiziellen Vorlage, erster Login mit der Zustimmung zu den Nutzungsbedingungen, Reverse Proxy mit HTTPS, Backup mit Wiederherstellung und Update.
Voraussetzungen
Die Projektdokumentation nennt keine verbindliche Mindestausstattung. Für ein Team mit einigen Dutzend Personen reicht:
- Server: Linux-VPS oder Mini-PC mit 2 CPU-Kernen und 4 GB RAM, x86_64 (amd64) oder ARM64. Das Image
ghcr.io/plankanban/planka:2.2.1wird fürlinux/amd64undlinux/arm64ausgeliefert. - Speicher: 10 GB frei, der Bedarf wächst vor allem mit Anhängen.
- Software: Debian 12/13 oder Ubuntu 24.04 mit Docker Engine und dem Compose-Plugin (
docker compose, nicht das altedocker-compose). - Netz: ein DNS-Name wie
planka.example.comund ein Reverse Proxy mit TLS-Zertifikat für den Zugriff von außen. - Lizenz: PLANKA steht unter der „PLANKA Community License“ (Fair-Use-Lizenz, keine OSI-Lizenz). Der interne Einsatz im eigenen Unternehmen ist erlaubt, der Betrieb als gehosteter Dienst für Dritte mit kommerziellem Nutzen nicht.
| Eckdaten | Wert |
|---|---|
| Image Anwendung | ghcr.io/plankanban/planka:2.2.1 |
| Image Datenbank | postgres:16-alpine |
| Port im Container | 1337 (HTTP und WebSocket) |
| Volumes | data für /app/data (Anhänge, Avatare), db-data für /var/lib/postgresql/data |
| Pflicht-Variablen | BASE_URL, DATABASE_URL, SECRET_KEY |
| Benutzer im Container | node, UID/GID 1000 |
Schritt 1: Projektordner und Geheimnisse anlegen
Legen Sie einen Projektordner an und erzeugen Sie zwei Zufallswerte: den Signaturschlüssel für Zugriffstoken und das Passwort des ersten Administrators. Die offizielle Vorlage enthält SECRET_KEY=notsecretkey und warnt im Kommentar ausdrücklich: Wer diesen veröffentlichten Wert stehen lässt, erlaubt jedem, gültige Token für beliebige Konten der Instanz zu erzeugen.
sudo mkdir -p /opt/planka && cd /opt/planka
printf 'SECRET_KEY=%s\nADMIN_PASSWORD=%s\n' "$(openssl rand -hex 64)" "$(openssl rand -hex 16)" | sudo tee .env > /dev/null
sudo chmod 600 .env
Compose liest die .env automatisch ein. Das Administratorpasswort gehört in Ihren Passwortmanager.
Verifizieren: sudo cat /opt/planka/.env zeigt zwei Zeilen, der SECRET_KEY ist 128 Hexadezimalzeichen lang. ls -l /opt/planka/.env zeigt die Rechte -rw-------.
Schritt 2: compose.yaml nach der offiziellen Vorlage
Die folgende Datei entspricht der offiziellen docker-compose.yml des Projekts mit drei bewussten Abweichungen: fester Image-Tag statt latest, Port nur an 127.0.0.1 und Geheimnisse aus der .env. Speichern Sie sie als /opt/planka/compose.yaml.
services:
planka:
image: ghcr.io/plankanban/planka:2.2.1
restart: on-failure
volumes:
- data:/app/data
ports:
- "127.0.0.1:3000:1337"
environment:
- BASE_URL=https://planka.example.com
- DATABASE_URL=postgresql://postgres@postgres/planka
- SECRET_KEY=${SECRET_KEY:?}
- TRUST_PROXY=true
- DEFAULT_LANGUAGE=de-DE
- DEFAULT_ADMIN_EMAIL=admin@example.com
- DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD:?}
- DEFAULT_ADMIN_NAME=Administrator
- DEFAULT_ADMIN_USERNAME=admin
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: on-failure
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=planka
- POSTGRES_HOST_AUTH_METHOD=trust
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d planka"]
interval: 10s
timeout: 5s
retries: 5
volumes:
data:
db-data:
Die wichtigsten Punkte im Einzelnen:
- BASE_URL ist die Adresse, die Nutzer im Browser eingeben. Weicht sie ab, werden WebSocket-Verbindungen abgewiesen.
- TRUST_PROXY=true lässt PLANKA die Header des Reverse Proxys auswerten. Ohne Proxy lassen Sie die Zeile weg.
- POSTGRES_HOST_AUTH_METHOD=trust stammt aus der offiziellen Vorlage und erlaubt Anmeldungen ohne Passwort. Das ist nur vertretbar, weil der Datenbankdienst keinen Port veröffentlicht und ausschließlich im internen Compose-Netz erreichbar ist. Ergänzen Sie beim Dienst
postgresdaher niemals einenports:-Eintrag. - DEFAULT_ADMIN_* legt beim ersten Start ein Administratorkonto an. Laut Kommentar der Vorlage bleibt ein über
DEFAULT_ADMIN_EMAILdefiniertes Konto gegen Bearbeiten und Löschen geschützt, solange die Variable gesetzt ist.
Weitere Variablen der Vorlage: SMTP_*, S3_* und Varianten mit Suffix __FILE für Docker Secrets. Ausgehende Anfragen (SMTP, Webhooks, Favicons) laufen über einen internen Squid-Proxy. Standardmäßig sperrt er nur localhost und postgres, weitere interne Ziele ergänzen Sie in OUTGOING_BLOCKED_HOSTS. GRAVATAR_BASE_URL bleibt leer, weil Gravatar laut Vorlage IP-Adressen und gehashte Mailadressen an einen Dritten übermittelt.
Verifizieren: docker compose config --quiet gibt nichts aus und endet mit Exit-Code 0. docker compose config --images listet ghcr.io/plankanban/planka:2.2.1 und postgres:16-alpine.
Schritt 3: Stack starten und prüfen
cd /opt/planka
docker compose pull
docker compose up -d
docker compose ps
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/
Compose startet PLANKA erst, wenn PostgreSQL den Healthcheck besteht. Beim ersten Start legt die Anwendung das Schema an.
Im Test auf einem Host mit 2 Kernen und 8 GB RAM waren beide Container rund 30 Sekunden nach dem Start healthy. Die Anwendung belegte im Leerlauf etwa 180 MiB Arbeitsspeicher, PostgreSQL etwa 32 MiB. Das Protokoll zeigte erwartungsgemäß:
[W] Custom terms not found, falling back to template
debug: It looks like your `sails.config.sockets.onlyAllowOrigins` array only includes
debug: references to the `localhost` origin.
Beides ist kein Fehler. Die zweite Meldung erscheint nur mit localhost in der BASE_URL.
Verifizieren: docker compose ps zeigt beide Dienste als Up (healthy), das PLANKA-Image bringt einen eigenen Healthcheck mit. Der curl-Aufruf liefert 200. docker compose exec planka id zeigt uid=1000(node) gid=1000(node).
Schritt 4: Erster Login und Nutzungsbedingungen
Melden Sie sich mit admin und dem Passwort aus der .env an. PLANKA 2.2.1 verlangt vor dem ersten Zugriff die Zustimmung zu den Nutzungsbedingungen, vorher gibt es kein Zugriffstoken, auch nicht per API.
Die mitgelieferten Bedingungen sind laut Dokumentation nur ein Ausgangspunkt und müssen an Ihre rechtlichen Anforderungen angepasst werden. Eigene Texte legen Sie als terms/de-DE.md im Projektordner ab und binden das Verzeichnis ein:
volumes:
- data:/app/data
- ./terms:/app/terms/custom
Danach ist docker compose up -d nötig. Nutzen Sie das Administratorkonto nicht für die tägliche Arbeit.
Für Skripte wichtig: POST /api/access-tokens antwortet bei fehlender Zustimmung trotz korrekter Zugangsdaten mit HTTP 403:
HTTP 403
{"code": "E_FORBIDDEN", "pendingToken": "eyJhbGciOiJI...",
"message": "Terms acceptance required", "step": "accept-terms"}
Den pendingToken aus dieser Antwort senden Sie zusammen mit dem SHA-256-Hash der Bedingungen (GET /api/terms) als signature an POST /api/access-tokens/accept-terms. Erst diese Antwort enthält das Zugriffstoken, danach funktioniert der normale Login direkt.
Verifizieren: Nach der Zustimmung sehen Sie die leere Projektübersicht und können ein Projekt mit einem Board anlegen. Ein zweiter Login desselben Kontos per API liefert HTTP 200 mit Token.
Schritt 5: Reverse Proxy mit HTTPS und WebSocket
PLANKA überträgt Änderungen über Socket.IO. Ohne WebSocket-Weiterleitung kommen Änderungen anderer Nutzer nicht an. Die offizielle Nginx-Vorlage, gekürzt und um TLS ergänzt:
upstream planka {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 443 ssl;
http2 on;
server_name planka.example.com;
ssl_certificate /etc/letsencrypt/live/planka.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/planka.example.com/privkey.pem;
client_max_body_size 50M;
location ~* \.io {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1d;
proxy_pass http://planka;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s;
proxy_pass http://planka;
}
}
Vorlagen für Apache, Traefik und Caddy stehen ebenfalls in der Dokumentation. Details zu Zertifikaten finden Sie in Nginx als Reverse Proxy mit TLS, eine Alternative mit automatischem Zertifikat in Caddy als Reverse Proxy einrichten.
Verifizieren: sudo nginx -t meldet syntax is ok. curl -sI https://planka.example.com/ liefert HTTP/2 200. In den Entwicklerwerkzeugen des Browsers erscheint eine Verbindung zu /socket.io/ mit Status 101, und eine Kartenänderung in einem zweiten Browserfenster erscheint ohne Neuladen.
Schritt 6: Backup und Wiederherstellung
Die Datenbank enthält Projekte, Karten und Konten, die Anhänge liegen im Volume data. Sichern Sie beides. In /opt/planka heißen die Volumes planka_data und planka_db-data.
cd /opt/planka
docker compose stop planka
docker compose exec -T postgres pg_dump -U postgres -Fc planka > planka-db.dump
docker run --rm -v planka_data:/data:ro -v "$PWD":/backup alpine tar czf /backup/planka-data.tgz -C /data .
docker compose start planka
Das kurze Stoppen verhindert, dass zwischen Dump und Dateikopie neue Anhänge entstehen. Die mitgelieferten Skripte docker-backup.sh und docker-restore.sh sichern dagegen im laufenden Betrieb und unverschlüsselt, sofern Sie nicht BACKUP_PASSPHRASE setzen. Laut Skriptkommentar enthält das Archiv Passwort-Hashes, Sitzungen und TOTP-Geheimnisse. Behandeln Sie jede Sicherung wie die Datenbank selbst.
Wiederherstellung in eine bestehende Instanz:
cd /opt/planka
docker compose stop planka
docker compose exec -T postgres dropdb -U postgres planka
docker compose exec -T postgres createdb -U postgres planka
docker compose exec -T postgres pg_restore -U postgres -d planka < planka-db.dump
docker run --rm -v planka_data:/data -v "$PWD":/backup alpine sh -c "rm -rf /data/* && tar xzf /backup/planka-data.tgz -C /data && chown -R 1000:1000 /data"
docker compose start planka
Ohne das chown gehören die Dateien root, und der Prozess node kann nicht mehr schreiben.
Im Test ergab die Sicherung einer Instanz mit einem Projekt einen Dump von 69 KB. Ein nach dem Backup angelegtes Projekt „NachBackup“ war nach der Wiederherstellung verschwunden, das Projekt aus der Zeit davor und eine Markierungsdatei im Datenvolume (Eigentümer 1000:1000) waren wieder da, die Oberfläche lieferte HTTP 200.
Verifizieren: ls -lh planka-db.dump planka-data.tgz zeigt zwei Dateien mit plausibler Größe. Nach der Wiederherstellung listet docker compose exec -T postgres psql -U postgres -d planka -tAc "select name from project;" Ihre Projekte, und die Oberfläche liefert wieder HTTP 200.
Schritt 7: Updates einspielen
Die offizielle Update-Anleitung lautet: Backup, docker compose down, pull, up -d. Wegen des festen Tags ändern Sie vorher die Version in der compose.yaml, nach einem Blick in die Release Notes.
cd /opt/planka
# vorher Backup nach Schritt 6
sed -i 's|planka:2.2.1|planka:NEUE_VERSION|' compose.yaml
docker compose pull
docker compose up -d
docker compose logs planka --tail 50
Neue Releases migrieren das Schema beim Start. Ein Rollback gelingt nur mit altem Tag plus Backup vor dem Update.
Verifizieren: docker compose images planka zeigt den neuen Tag, das Protokoll enthält keine Fehlermeldungen, die Oberfläche liefert HTTP 200 und bestehende Boards sind vollständig.
Typische Fehler
| Symptom | Ursache | Lösung |
|---|---|---|
required variable SECRET_KEY is missing a value | .env fehlt oder liegt nicht neben der compose.yaml | .env nach Schritt 1 anlegen, docker compose config --quiet prüfen |
API-Login liefert 403 Terms acceptance required | Konto hat den Nutzungsbedingungen noch nicht zugestimmt | Einmal im Browser zustimmen oder accept-terms wie in Schritt 4 |
accept-terms liefert 400: Value ('kurz') was shorter than the configured minimum length (64) | Kein vollständiger SHA-256-Hash gesendet | Hash hexadezimal (64 Zeichen) über den Text aus /api/terms bilden |
| Änderungen anderer Nutzer erscheinen erst nach Neuladen | Proxy leitet WebSocket nicht weiter | location ~* \.io mit Upgrade- und Connection-Header ergänzen |
Weiterleitungen auf localhost, Socket-Fehler | BASE_URL stimmt nicht mit der Browseradresse überein | Öffentliche HTTPS-Adresse eintragen, TRUST_PROXY=true, docker compose up -d |
| Upload bricht ab | Rechte im Volume falsch oder client_max_body_size zu klein | chown -R 1000:1000 auf das Datenverzeichnis, Proxy-Limit erhöhen |
port is already allocated | Port 3000 auf dem Host belegt | Anderen Hostport wählen, BASE_URL bei direktem Zugriff anpassen |
Häufige Fragen
Ist PLANKA Open Source?
Nicht im Sinne der Open Source Definition. Die Lizenzdatei enthält die PLANKA Community License 1.1 auf Basis einer Fair-Use-Lizenz. Interne Nutzung im Unternehmen ist erlaubt, ein gehosteter Dienst für Kunden braucht eine kommerzielle Lizenz.
Welche Funktionen fehlen in der Community-Edition?
Laut offizieller Gegenüberstellung unter anderem Kalender- und Zeitstrahlansichten, Vorlagen, Gastrollen, Single Sign-on per OIDC und PDF-Export. Diese gehören zur Pro-Edition.
Warum mindestens Version 2.2.1?
Laut Release Notes behebt 2.2.1 eine Path-Traversal-Lücke (CWE-22) in den Routen /user-avatars, /background-images und /favicons. Angemeldete Nutzer konnten auf Instanzen mit lokalem Dateispeicher Dateien lesen, die für den PLANKA-Prozess lesbar waren.
Fazit
PLANKA läuft mit zwei Containern und wenigen Variablen. Entscheidend für den Betrieb sind ein eigener SECRET_KEY, ein Proxy mit WebSocket-Weiterleitung, ein zurückgespieltes Backup aus Datenbank und Anhängen und regelmäßige Updates. Wer Kalender, Zeitstrahl oder Single Sign-on braucht, prüft vorher die Pro-Edition oder ein anderes Werkzeug.
Weiterführende Anleitungen und Quellen
- Docker Compose: Multi-Container-Stacks aufbauen
- Docker Compose absichern: Secrets, Healthchecks und Non-Root
- Plane mit Docker als Projektmanagement
- PLANKA-Dokumentation: Docker Production Version
- Offizielle docker-compose.yml mit allen Variablen
- PLANKA-Dokumentation: Backup und Restore
- PLANKA-Dokumentation: Update
- PLANKA-Dokumentation: Nutzungsbedingungen anpassen
- Release Notes PLANKA 2.2.1
- PLANKA Community License


