Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung IT-Branche 20.08.2026 · 9 min Lesezeit

Plane mit Docker installieren: Self-hosted Projektmanagement als Jira-Alternative

Plane Community Edition v1.4.2 mit den offiziellen Release-Dateien per Docker Compose betreiben: Passwörter samt Verbindungs-URLs ändern, Proxy nur lokal, Instanz-Administrator, Reverse Proxy, getestetes Datenbank-Backup und Update.

Geprüft am 30.09.2026 · für plane 1.4.2

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

Planungstisch mit leeren Karten entlang einer Zeitleiste, dahinter eine Pinnwand mit farbigen Fäden, auf einem Sideboard ein kleiner Server

Plane ist ein Projektmanagement-Werkzeug mit Arbeitspaketen (Work Items), Zyklen, Modulen, Seiten und Kanban-, Listen- und Gantt-Ansichten. Die Community Edition steht unter AGPL-3.0 und lässt sich auf eigener Hardware betreiben. Diese Anleitung zeigt den offiziellen Weg für Docker Compose mit Plane v1.4.2: Dateien direkt aus dem Release laden, Standardpasswörter ersetzen, Ports nur lokal veröffentlichen, Instanz-Administrator anlegen, Reverse Proxy, Backup und Update.

Voraussetzungen

  • Server: 2 CPU-Kerne (x86_64 oder ARM64) und laut Herstellerdoku mindestens 4 GB RAM, für den Produktivbetrieb empfiehlt Plane 8 GB. Im Test belegten alle Container im Leerlauf zusammen rund 1,3 GB RAM.
  • Speicher: mindestens 20 GB frei. Die Images belegen zusammen mehrere Gigabyte, dazu kommen Datenbank und Uploads in MinIO.
  • Software: Linux (Debian, Ubuntu) mit Docker Engine und aktuellem Compose-Plugin.
  • Netz: ein DNS-Name wie plane.example.com und ein Reverse Proxy mit TLS, alternativ das integrierte HTTPS des Plane-Proxys.
  • Edition: Diese Anleitung beschreibt die Community Edition. Die Herstellerdoku stellt inzwischen die Commercial Edition mit dem Installer prime-cli in den Vordergrund, die Community Edition wird weiter über die Release-Dateien auf GitHub verteilt.
EckdatenWert
VersionPlane v1.4.2 (Tag v1.4.2 auf Docker Hub, makeplane/*)
Anwendungsdiensteweb, space, admin, live, api, worker, beat-worker, migrator, proxy
Infrastrukturpostgres:15.7-alpine, valkey/valkey:7.2.11-alpine, rabbitmq:3.13.6-management-alpine, MinIO (pgsty/minio)
PortsProxy 80 und 443, per Override an 127.0.0.1
Volumespgdata, redisdata, uploads, rabbitmq_data, proxy_config, proxy_data, vier Log-Volumes
PflichtänderungenSECRET_KEY, LIVE_SERVER_SECRET_KEY, POSTGRES_PASSWORD, RABBITMQ_PASSWORD, AWS_SECRET_ACCESS_KEY

Schritt 1: Release-Dateien laden

Das offizielle Skript setup.sh lädt genau zwei Dateien aus dem Release und ruft danach docker compose mit --env-file plane.env auf. Sie können das Skript nutzen oder denselben Ablauf von Hand ausführen. Der manuelle Weg zeigt, was passiert, und legt die Version fest: Die Datei aus dem Release enthält v1.4.2 als Standard-Tag, die Datei im Hauptzweig dagegen stable.

sudo mkdir -p /opt/plane-app && cd /opt/plane-app
R=https://github.com/makeplane/plane/releases/download/v1.4.2
sudo curl -fsSLo docker-compose.yaml $R/docker-compose.yml
sudo curl -fsSLo plane.env $R/variables.env
sudo chmod 600 plane.env

Verifizieren: grep -c 'APP_RELEASE:-v1.4.2' docker-compose.yaml liefert 9. ls -l plane.env zeigt -rw-------.

Schritt 2: plane.env anpassen

Die Vorlage enthält Standardwerte wie SECRET_KEY=change-this-key-on-deployment, POSTGRES_PASSWORD=plane und für MinIO secret-key. Ersetzen Sie alle. Die Kommentare der Vorlage nennen openssl rand -hex 32 als Erzeuger.

cd /opt/plane-app
set_env() { sudo sed -i "s|^$1=.*|$1=$2|" plane.env; }
PG=$(openssl rand -hex 16); MQ=$(openssl rand -hex 16)
set_env APP_RELEASE v1.4.2
set_env APP_DOMAIN plane.example.com
set_env WEB_URL https://plane.example.com
set_env CORS_ALLOWED_ORIGINS https://plane.example.com
set_env LISTEN_HTTP_PORT 8081
set_env LISTEN_HTTPS_PORT 8444
set_env SECRET_KEY "$(openssl rand -hex 32)"
set_env LIVE_SERVER_SECRET_KEY "$(openssl rand -hex 32)"
set_env AWS_SECRET_ACCESS_KEY "$(openssl rand -hex 24)"
set_env POSTGRES_PASSWORD "$PG"
set_env DATABASE_URL "postgresql://plane:$PG@plane-db/plane"
set_env RABBITMQ_PASSWORD "$MQ"
set_env AMQP_URL "amqp://plane:$MQ@plane-mq:5672/plane"

Der Grund für die beiden URL-Zeilen: In der Compose-Datei steht DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}, die Vorlage lässt DATABASE_URL leer. Ändern Sie nur POSTGRES_PASSWORD, legt PostgreSQL den Benutzer mit dem neuen Passwort an, API und Migrator versuchen es aber weiter mit plane. Gleiches gilt für RabbitMQ und AMQP_URL.

SITE_ADDRESS=:80 bleibt für den Betrieb hinter einem eigenen Reverse Proxy stehen. Wer den Plane-Proxy direkt ins Internet stellt, trägt dort den Domainnamen und in CERT_EMAIL eine Adresse ein, dann holt der integrierte Caddy ein Let's-Encrypt-Zertifikat.

Verifizieren: grep -E '^(SECRET_KEY|POSTGRES_PASSWORD|RABBITMQ_PASSWORD|AWS_SECRET_ACCESS_KEY)=' plane.env zeigt keine Standardwerte mehr. docker compose --env-file plane.env config | grep -E 'DATABASE_URL|AMQP_URL' | sort -u zeigt URLs mit Ihren Passwörtern.

Schritt 3: Ports nur lokal veröffentlichen

Der Dienst proxy veröffentlicht seine Ports ohne Angabe einer Adresse, also auf allen Schnittstellen. Statt die Herstellerdatei zu ändern, legen Sie eine compose.override.yaml an. Compose liest sie automatisch mit, der Tag !override ersetzt die Portliste vollständig statt sie zu ergänzen:

services:
  proxy:
    ports: !override
      - "127.0.0.1:${LISTEN_HTTP_PORT:-8081}:80"
      - "127.0.0.1:${LISTEN_HTTPS_PORT:-8444}:443"

Hinweis: Die Override-Datei wird nur gelesen, wenn Sie docker compose im Projektordner ohne eigenes -f aufrufen. Das Skript setup.sh ruft Compose mit -f docker-compose.yaml auf und ignoriert sie deshalb. Arbeiten Sie nach dieser Anleitung durchgehend mit docker compose --env-file plane.env.

Verifizieren: docker compose --env-file plane.env config | grep -B1 -A3 host_ip zeigt für beide Ports host_ip: 127.0.0.1.

Schritt 4: Stack starten

cd /opt/plane-app
docker compose --env-file plane.env pull
docker compose --env-file plane.env up -d
docker compose --env-file plane.env ps -a --format 'table {{.Service}}\t{{.Status}}'
docker compose --env-file plane.env logs migrator

Der Dienst migrator legt das Datenbankschema an und beendet sich danach mit Exit-Code 0. Alle übrigen Dienste laufen dauerhaft.

Im Test dauerte der Download aller Images rund 45 Sekunden. Der migrator lief gut 2 Minuten und endete mit Zeilen wie Applying sessions.0001_initial... OK, danach lieferte die Oberfläche HTTP 200.

Verifizieren: migrator steht auf Exited (0), alle anderen Dienste auf Up. curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/ liefert 200, curl -s http://127.0.0.1:8081/api/instances/ liefert JSON mit "is_setup_done": false.

Schritt 5: Instanz-Administrator anlegen

Öffnen Sie https://plane.example.com/god-mode/ und legen Sie das Konto des Instanz-Administrators an. Solange das nicht geschehen ist, kann jeder, der die Adresse erreicht, diese Rolle übernehmen. Richten Sie die Instanz deshalb ein, bevor der Proxy sie öffentlich macht, zum Beispiel über einen SSH-Tunnel auf Port 8081.

Im Bereich God Mode legen Sie danach fest:

  • Email: SMTP-Server für Einladungen und Passwort-Zurücksetzen.
  • Authentication: Die Option „Allow anyone to sign up without an invite“ schalten Sie aus, wenn nur eingeladene Personen Zugang erhalten sollen.
  • General: Die Übermittlung anonymer Nutzungsdaten an Plane lässt sich hier abschalten.

Im Test setzte die Registrierung des ersten Administrators is_setup_done auf true. Ein zweiter Versuch wurde mit der Weiterleitung auf /god-mode/?error_code=5150&error_message=ADMIN_ALREADY_EXIST abgewiesen.

Verifizieren: curl -s http://127.0.0.1:8081/api/instances/ | grep -o '"is_setup_done":[a-z]*' liefert "is_setup_done":true. Nach der Anmeldung können Sie einen Workspace und ein erstes Projekt anlegen.

Schritt 6: Reverse Proxy mit HTTPS

Die Herstellerdoku für externe Proxys verlangt SITE_ADDRESS=:80 und freie Ports für den Plane-Proxy, beides ist nach Schritt 2 und 3 gesetzt. Nginx leitet auf den lokalen Port weiter, mit WebSocket-Unterstützung für den Echtzeit-Editor (live):

server {
    listen 443 ssl;
    http2 on;
    server_name plane.example.com;
    ssl_certificate     /etc/letsencrypt/live/plane.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/plane.example.com/privkey.pem;
    client_max_body_size 10M;

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

client_max_body_size passt zu FILE_SIZE_LIMIT=5242880 (5 MB) aus der Vorlage. Wer größere Anhänge erlaubt, erhöht beide Werte. Hintergründe zu Proxy und Zertifikaten finden Sie in Nginx als Reverse Proxy mit TLS und Traefik als Docker-Reverse-Proxy.

Verifizieren: sudo nginx -t meldet syntax is ok. curl -sI https://plane.example.com/ liefert HTTP/2 200. Zwei Personen bearbeiten gleichzeitig eine Seite und sehen die Änderungen des anderen ohne Neuladen.

Schritt 7: Backup und Update

Die Backup-Funktion von setup.sh (Menüpunkt 7) kopiert die Datenverzeichnisse von PostgreSQL, MinIO, RabbitMQ und Valkey aus den laufenden Containern per docker cp. Eine Kopie des PostgreSQL-Verzeichnisses im laufenden Betrieb ist nicht garantiert konsistent. Sichern Sie die Datenbank deshalb zusätzlich als Dump, dazu die Uploads und die plane.env:

cd /opt/plane-app && mkdir -p backup
docker compose --env-file plane.env exec -T plane-db pg_dump -h /var/run/postgresql -U plane -Fc plane > backup/plane-db.dump
docker run --rm -v plane-app_uploads:/data:ro -v "$PWD/backup":/backup alpine tar czf /backup/uploads.tgz -C /data .
sudo cp plane.env compose.override.yaml backup/

Der Parameter -h /var/run/postgresql ist nötig, weil im Container PGHOST=plane-db gesetzt ist. Ohne ihn verbindet sich pg_dump per TCP und bricht im Test mit fe_sendauth: no password supplied ab, die Sicherungsdatei bleibt leer. Mit dem Socket-Pfad ergab eine frische Instanz einen Dump von 627 KB, der sich fehlerfrei in eine neue Datenbank einspielen ließ und den Administrator enthielt.

Für ein Update laden Sie die Release-Dateien der neuen Version, übernehmen Ihre Werte in die neue plane.env und starten neu. Der migrator passt das Schema an. Ein Zurückstellen des Tags nach der Migration ist kein Rollback, dafür brauchen Sie das Backup von vorher.

cd /opt/plane-app
R=https://github.com/makeplane/plane/releases/download/NEUE_VERSION
sudo curl -fsSLo docker-compose.yaml $R/docker-compose.yml
sudo curl -fsSLo variables.env.neu $R/variables.env
diff plane.env variables.env.neu
sudo sed -i "s|^APP_RELEASE=.*|APP_RELEASE=NEUE_VERSION|" plane.env
docker compose --env-file plane.env pull
docker compose --env-file plane.env up -d

Verifizieren: ls -lh backup/ zeigt Dump, Upload-Archiv und Konfiguration. Nach einem Update meldet docker compose --env-file plane.env logs migrator keine Fehler, und docker compose --env-file plane.env images api zeigt den neuen Tag.

Typische Fehler

SymptomUrsacheLösung
Migrator und API können sich nicht an der Datenbank anmeldenPOSTGRES_PASSWORD geändert, DATABASE_URL leerDATABASE_URL mit neuem Passwort setzen (Schritt 2), bei bereits initialisierter Datenbank das Passwort per ALTER ROLE angleichen
port is already allocated für 80 oder 443Proxy-Ports kollidieren mit vorhandenem WebserverLISTEN_HTTP_PORT/LISTEN_HTTPS_PORT ändern und Override aus Schritt 3 anlegen
Override wirkt nicht, Ports offen auf 0.0.0.0Compose mit -f docker-compose.yaml oder über setup.sh gestartetIm Projektordner ohne -f starten oder beide Dateien mit -f angeben
Migrator beendet sich mit FehlerDatenbank nicht erreichbar oder falsche Zugangsdatendocker compose --env-file plane.env logs migrator plane-db prüfen
Uploads schlagen fehlDatei größer als FILE_SIZE_LIMIT oder Proxy-LimitBeide Werte erhöhen, Stack neu starten
Links zeigen auf localhostWEB_URL und CORS_ALLOWED_ORIGINS nicht angepasstÖffentliche HTTPS-Adresse eintragen, up -d

Häufige Fragen

Community oder Commercial Edition?

Die Commercial Edition startet laut Herstellerdoku im Free-Plan mit 12 Plätzen je Workspace und wird über prime-cli installiert. Die Community Edition hat keine Platzgrenze, bietet aber weniger Funktionen. Diese Anleitung behandelt nur die Community Edition.

Warum nicht latest oder stable?

stable wandert mit jedem Release weiter. Ein ungeplantes pull würde dann eine neue Version mit Migration einspielen. Ein fester Tag macht Updates zu einer bewussten Entscheidung.

Brauche ich RabbitMQ und MinIO?

Ja, im Standardaufbau. RabbitMQ verteilt Hintergrundaufgaben an die Worker, MinIO speichert Uploads. Die Compose-Datei erlaubt externe Dienste über AMQP_URL und die AWS_*-Variablen, die Herstellerdoku empfiehlt für den Produktivbetrieb externe Datenbank und externen Speicher.

Fazit

Plane Community Edition bringt ein vollständiges Projektmanagement mit, verlangt aber einen Stack aus 13 Containern und entsprechend Arbeitsspeicher. Die häufigste Stolperfalle liegt in der Konfiguration: Wer Passwörter ändert, muss auch die Verbindungs-URLs anpassen. Mit festem Release-Tag, lokal gebundenem Proxy, sofort angelegtem Instanz-Administrator und einem Datenbank-Dump vor jedem Update bleibt der Betrieb berechenbar. Für einfache Kanban-Boards ohne Zyklen und Module reicht ein leichteres Werkzeug wie PLANKA.

Weiterführende Anleitungen und Quellen