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

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

Plane ist eine quelloffene Projektmanagement-Plattform mit 50.000+ GitHub-Stars – Issues, Sprints, Roadmaps und Wikis per Docker Compose auf dem eigenen Server, ohne SaaS-Kosten und ohne Datenweitergabe.

Plane mit Docker installieren: Self-hosted Projektmanagement als Jira-Alternative mit Projektboards, Aufgabenverwaltung, Teams, Berichten, Dashboard und Docker-Container. KI-generiert

Projektmanagement-Software gibt es als SaaS zuhauf – doch wer Kundendaten, Sprints und interne Roadmaps lieber auf dem eigenen Server behalten will, greift zunehmend zu Plane. Die AGPL-3.0-lizenzierte Plattform vereint Issue-Tracking, Sprints (Cycles), Gantt-ähnliche Roadmaps, ein Wiki (Pages) und Echtzeit-Dashboards in einer einzigen selbst gehosteten Applikation. Mit über 50.000 GitHub-Stars und einer aktiven Entwicklercommunity ist Plane die derzeit ausgereifteste Open-Source-Alternative zu Jira, Linear, Monday und ClickUp – und läuft seit v1.0.0 stabil auf Linux (x86_64 und ARM64) per Docker Compose. Diese Anleitung richtet sich an KMU-Admins und Selfhoster, die den kompletten Stack ohne SaaS-Abhängigkeit betreiben wollen.

Voraussetzungen

  1. Docker Engine 24+ und Docker Compose Plugin v2 (Befehl: docker compose, nicht docker-compose) – siehe Docker und Docker Compose auf Linux installieren
  2. Linux-Host, VM oder NAS mit Docker-Unterstützung (Ubuntu 22.04/24.04, Debian 12, CentOS 9, Amazon Linux 2023, macOS oder Windows mit WSL2)
  3. Mindestens 2 CPU-Kerne (x86_64 oder ARM64) und 4 GB RAM (8 GB für Produktion empfohlen)
  4. Mindestens 20 GB freier Festplattenplatz (Images ca. 3–4 GB, Daten wachsend)
  5. Internetzugang zum Herunterladen der Docker-Images
  6. Für Produktionsbetrieb: Domainname und ein vorgelagerter Reverse Proxy für HTTPS – sieh dir dazu Traefik als Docker-Reverse-Proxy mit automatischem HTTPS an
  7. openssl zur Generierung des SECRET_KEY (auf fast jedem Linux-System vorinstalliert)

Eckdaten auf einen Blick

EigenschaftWert
Aktuelle stabile Versionv1.3.1 (Mai 2026)
LizenzAGPL-3.0 (CE kostenlos)
Architekturlinux/amd64 + linux/arm64
Eintrittspunkt (extern)Port 80 (HTTP), Port 443 (HTTPS)
Minimale RAM4 GB (8 GB empfohlen)
Container im Stack12 (inkl. einmaligem Migrator)
ServiceImageZweck
proxymakeplane/plane-proxy:stableNginx-Reverse-Proxy, einziger externer Eintrittspunkt
webmakeplane/plane-frontend:stableReact-Frontend
apimakeplane/plane-backend:stableDjango-REST-API
workermakeplane/plane-backend:stableCelery-Worker für Hintergrundaufgaben
beat-workermakeplane/plane-backend:stableCelery Beat (Cronjobs)
livemakeplane/plane-live:stableNode.js Echtzeit-Kollaboration
adminmakeplane/plane-admin:stableAdmin-Panel
spacemakeplane/plane-space:stableSpace-Modul (öffentliche Boards)
migratormakeplane/plane-backend:stableDjango-Datenbankmigrationen (einmalig)
plane-dbpostgres:15.7-alpinePostgreSQL-Datenbank
plane-redisvalkey/valkey:7.2.11-alpineKey-Value-Store (Redis-kompatibel)
plane-mqrabbitmq:3.13.6-management-alpineMessage-Queue
plane-miniominio/minio:latestS3-kompatibler Objektspeicher für Uploads

Schritt 1: Projektordner anlegen

Lege einen dedizierten Ordner für den Plane-Stack an. Alle Konfigurationsdateien leben hier – es gibt keine weiteren Bind-Mounts, da Plane ausschließlich benannte Docker-Volumes nutzt.

mkdir -p /opt/plane
cd /opt/plane

Verifizieren: Der Ordner existiert und du befindest dich darin.

pwd
# Erwartete Ausgabe: /opt/plane

Schritt 2: SECRET_KEY und Umgebungsvariablen konfigurieren

Der SECRET_KEY ist der kritischste Konfigurationswert: Er schützt JWT-Token-Signing und alle kryptografischen Operationen. Wer den Default-Wert belässt, riskiert kompromittierte Sessions. Generiere ihn einmalig mit openssl und trage ihn direkt in die plane.env ein – danach nie wieder ändern, ohne alle Sessions zu invalidieren.

openssl rand -hex 32
# Beispielausgabe: a3f8c2e1d9b047563a1f2c8e4d6b0a9f5e7c3d1b2a8f4e6c0d2b9a7f3e5c1d8

Erstelle nun die Konfigurationsdatei /opt/plane/plane.env und ersetze alle Pflichtfelder mit deinen eigenen Werten:

# ── Pflicht ──────────────────────────────────────────────────────────────────
SECRET_KEY=DEIN_GENERIERTER_SECRET_KEY_HIER_EINTRAGEN
WEB_URL=http://plane.example.com
CORS_ALLOWED_ORIGINS=http://plane.example.com
APP_DOMAIN=plane.example.com

# ── Datenbank ─────────────────────────────────────────────────────────────────
PGHOST=plane-db
PGDATABASE=plane
POSTGRES_USER=plane
POSTGRES_PASSWORD=sicheresDbPasswort123!
POSTGRES_PORT=5432

# ── Redis / Valkey ────────────────────────────────────────────────────────────
REDIS_HOST=plane-redis
REDIS_PORT=6379

# ── RabbitMQ ──────────────────────────────────────────────────────────────────
RABBITMQ_HOST=plane-mq
RABBITMQ_DEFAULT_USER=plane
RABBITMQ_DEFAULT_PASS=sicheresMqPasswort123!
RABBITMQ_DEFAULT_VHOST=plane

# ── MinIO / Objektspeicher ────────────────────────────────────────────────────
USE_MINIO=1
MINIO_ROOT_USER=minio-access-key
MINIO_ROOT_PASSWORD=minioGeheimPasswort123!
AWS_ACCESS_KEY_ID=minio-access-key
AWS_SECRET_ACCESS_KEY=minioGeheimPasswort123!
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
AWS_S3_BUCKET_NAME=uploads
FILE_SIZE_LIMIT=5242880

# ── Netzwerk / Ports (optional, Defaults funktionieren) ──────────────────────
LISTEN_HTTP_PORT=80
LISTEN_HTTPS_PORT=443

# ── Skalierung (optional) ─────────────────────────────────────────────────────
GUNICORN_WORKERS=2
WEB_REPLICAS=1
API_REPLICAS=1
WORKER_REPLICAS=1

# ── Debug (nie in Produktion auf 1 setzen) ────────────────────────────────────
DEBUG=0
APP_RELEASE=stable

Wichtige Hinweise zur Konfiguration:

  1. WEB_URL und CORS_ALLOWED_ORIGINS müssen identisch und vollständig gesetzt sein (inkl. Protokoll, ohne abschließenden Slash). Weichen sie voneinander ab, scheitern alle API-Aufrufe vom Browser mit CORS-Fehler.
  2. AWS_ACCESS_KEY_ID und MINIO_ROOT_USER müssen denselben Wert haben – dasselbe gilt für das zugehörige Passwort-Paar.
  3. Für lokale Tests kannst du WEB_URL=http://localhost setzen und Port 80 direkt nutzen.

Verifizieren: Die Datei existiert und enthält deinen echten SECRET_KEY (nicht den Platzhalter).

grep "SECRET_KEY" /opt/plane/plane.env
# Erwartete Ausgabe: SECRET_KEY=dein-generierter-wert (kein "changeMe")

Schritt 3: compose.yaml anlegen

Erstelle die Datei /opt/plane/compose.yaml mit dem vollständigen Stack. Der migrator-Service läuft mit restart: "no" genau einmal beim ersten Start und bei Updates – er führt die Django-Datenbankmigrationen durch, bevor api hochfährt.

version: "3.8"

x-app-env: &app-env
  env_file:
    - plane.env

x-db-env: &db-env
  PGHOST: ${PGHOST:-plane-db}
  PGDATABASE: ${PGDATABASE:-plane}
  POSTGRES_USER: ${POSTGRES_USER:-plane}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeMe!}
  POSTGRES_PORT: ${POSTGRES_PORT:-5432}

x-redis-env: &redis-env
  REDIS_HOST: ${REDIS_HOST:-plane-redis}
  REDIS_PORT: ${REDIS_PORT:-6379}

x-mq-env: &mq-env
  RABBITMQ_HOST: ${RABBITMQ_HOST:-plane-mq}
  RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
  RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-plane}
  RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-changeMe!}
  RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_DEFAULT_VHOST:-plane}

x-minio-env: &minio-env
  USE_MINIO: ${USE_MINIO:-1}
  AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-access-key}
  AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-secret-key}
  AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
  AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
  FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}

services:
  plane-db:
    image: postgres:15.7-alpine
    restart: always
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      <<: *db-env
      POSTGRES_DB: ${PGDATABASE:-plane}
    command: postgres -c max_connections=1000
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  plane-redis:
    image: valkey/valkey:7.2.11-alpine
    restart: always
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD-SHELL", "valkey-cli ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  plane-mq:
    image: rabbitmq:3.13.6-management-alpine
    restart: always
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq
    environment:
      <<: *mq-env

  plane-minio:
    image: minio/minio:latest
    restart: always
    volumes:
      - uploads:/export
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER:-access-key}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-secret-key}
    command: server /export --console-address ":9090"
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s
      timeout: 5s
      retries: 5

  migrator:
    image: makeplane/plane-backend:${APP_RELEASE:-stable}
    restart: "no"
    env_file:
      - plane.env
    environment:
      <<: [*db-env, *redis-env, *mq-env, *minio-env]
      SECRET_KEY: ${SECRET_KEY:-changeMe-use-long-random-string}
    command: ./bin/docker-entrypoint-migrator.sh
    depends_on:
      plane-db:
        condition: service_healthy
      plane-redis:
        condition: service_healthy

  api:
    image: makeplane/plane-backend:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    environment:
      <<: [*db-env, *redis-env, *mq-env, *minio-env]
      SECRET_KEY: ${SECRET_KEY:-changeMe-use-long-random-string}
      WEB_URL: ${WEB_URL:-http://localhost}
      CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost}
      DEBUG: ${DEBUG:-0}
      GUNICORN_WORKERS: ${GUNICORN_WORKERS:-1}
    command: ./bin/docker-entrypoint-api.sh
    depends_on:
      migrator:
        condition: service_completed_successfully
      plane-db:
        condition: service_healthy
      plane-redis:
        condition: service_healthy

  worker:
    image: makeplane/plane-backend:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    environment:
      <<: [*db-env, *redis-env, *mq-env, *minio-env]
      SECRET_KEY: ${SECRET_KEY:-changeMe-use-long-random-string}
    command: ./bin/docker-entrypoint-worker.sh
    depends_on:
      api:
        condition: service_started

  beat-worker:
    image: makeplane/plane-backend:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    environment:
      <<: [*db-env, *redis-env, *mq-env, *minio-env]
      SECRET_KEY: ${SECRET_KEY:-changeMe-use-long-random-string}
    command: ./bin/docker-entrypoint-beat.sh
    depends_on:
      api:
        condition: service_started

  live:
    image: makeplane/plane-live:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    environment:
      SECRET_KEY: ${SECRET_KEY:-changeMe-use-long-random-string}
    depends_on:
      api:
        condition: service_started

  web:
    image: makeplane/plane-frontend:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    depends_on:
      api:
        condition: service_started

  space:
    image: makeplane/plane-space:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    depends_on:
      api:
        condition: service_started

  admin:
    image: makeplane/plane-admin:${APP_RELEASE:-stable}
    restart: always
    env_file:
      - plane.env
    depends_on:
      api:
        condition: service_started

  proxy:
    image: makeplane/plane-proxy:${APP_RELEASE:-stable}
    restart: always
    ports:
      - "${LISTEN_HTTP_PORT:-80}:80"
      - "${LISTEN_HTTPS_PORT:-443}:443"
    environment:
      LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
      LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
      WEB_URL: ${WEB_URL:-http://localhost}
    depends_on:
      web:
        condition: service_started
      api:
        condition: service_started
      space:
        condition: service_started
      admin:
        condition: service_started
    volumes:
      - logs:/app/logs
      - proxy_conf:/etc/nginx

volumes:
  pgdata:
  redisdata:
  uploads:
  rabbitmq_data:
  logs:
  proxy_conf:

Ein kurzer Hinweis zur Compose-Datei: Das minio/minio:latest-Tag ist so in der offiziellen Plane-Compose definiert. Für Produktionsumgebungen kannst du ein gepinntes MinIO-Release-Tag einsetzen, um unerwartete Breaking Changes durch MinIO-Majors zu vermeiden.

Verifizieren: Beide Dateien existieren im Projektordner.

ls -la /opt/plane/
# Erwartete Ausgabe:
# -rw-r--r-- 1 root root  xxx plane.env
# -rw-r--r-- 1 root root  xxx compose.yaml

Schritt 4: Stack starten und Images herunterladen

Starte den Stack aus dem Projektordner heraus. Beim ersten Start werden alle Images heruntergeladen (ca. 3–4 GB), was je nach Internetverbindung einige Minuten dauert. Der migrator-Container läuft zuerst und beendet sich dann – das ist korrekt und gewollt.

cd /opt/plane
docker compose up -d

Beobachte den Startvorgang in Echtzeit (optional, mit Ctrl+C abbrechen):

docker compose logs -f migrator
# Warte auf: "Migrations completed" oder ähnliche Abschlussmeldung

Verifizieren: Nach etwa 60–120 Sekunden sollten alle dauerhaften Services laufen und der Migrator abgeschlossen haben.

docker compose ps
# Erwartete Ausgabe (Auszug):
# NAME             STATUS
# plane-admin      Up X minutes
# plane-api        Up X minutes
# plane-beat       Up X minutes
# plane-db         Up X minutes (healthy)
# plane-live       Up X minutes
# plane-migrator   Exited (0)   <-- korrekt!
# plane-minio      Up X minutes (healthy)
# plane-mq         Up X minutes
# plane-proxy      Up X minutes
# plane-redis      Up X minutes (healthy)
# plane-space      Up X minutes
# plane-web        Up X minutes
# plane-worker     Up X minutes

Der migrator mit Exited (0) ist korrekt – Exit-Code 0 bedeutet erfolgreich abgeschlossen. Prüfe den Proxy zusätzlich per HTTP:

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

Schritt 5: Erste Einrichtung im Browser

Öffne http://localhost (bzw. deine konfigurierte WEB_URL) im Browser. Du siehst die Plane-Willkommensseite, auf der du einen Administrator-Account anlegen kannst.

  1. Klicke auf „Get started" und lege den ersten Admin-Account an (E-Mail-Adresse und Passwort).
  2. Danach kannst du einen Workspace erstellen – dies ist der oberste Organisationsrahmen in Plane, vergleichbar mit einer Jira-Instanz.
  3. Innerhalb des Workspace legst du Projekte an; jedes Projekt erhält Issues, Cycles (Sprints), Modules und Pages (Wiki).
  4. Das Admin-Panel erreichst du unter http://localhost/god-mode/ – hier konfigurierst du SMTP, OAuth und weitere instanzweite Einstellungen.

Verifizieren: Die Registrierungsseite lädt vollständig, du kannst einen Account anlegen und dich einloggen.

curl -s http://localhost | grep -i "plane"
# Erwartet: HTML-Ausgabe mit "Plane" im Seitentitel oder Body

Schritt 6: HTTPS und Reverse Proxy (Produktion)

Für den Produktionseinsatz solltest du Plane hinter einem Reverse Proxy mit TLS betreiben. Dafür änderst du in plane.env den Port des Proxy-Containers auf einen internen Port (z. B. 8080) und lässt deinen vorgelagerten Proxy (Nginx, Traefik oder Caddy) den öffentlichen TLS-Verkehr übernehmen. Eine vollständige Anleitung findest du unter Traefik als Docker-Reverse-Proxy mit automatischem HTTPS.

# In plane.env für Traefik/Nginx-Vorschaltung:
LISTEN_HTTP_PORT=8080
WEB_URL=https://plane.example.com
CORS_ALLOWED_ORIGINS=https://plane.example.com

Nach Änderungen an plane.env müssen alle Container neu erstellt werden – ein einfacher Restart genügt nicht:

cd /opt/plane
docker compose up -d --force-recreate

Verifizieren: Der Proxy antwortet nun auf dem neuen internen Port.

curl -I http://localhost:8080
# Erwartete Ausgabe: HTTP/1.1 200 OK oder 302 Found

Schritt 7: Updates durchführen

Updates bei Plane erfordern eine feste Reihenfolge, da Datenbankmigrationen vor dem Neustart der anderen Services laufen müssen. Erstelle vorher unbedingt ein PostgreSQL-Backup – lies dazu PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile.

cd /opt/plane

# 1. Backup der Datenbank
docker compose exec plane-db pg_dump -U plane plane > backup_$(date +%Y%m%d).sql

# 2. Neue Images herunterladen
docker compose pull

# 3. Migrator zuerst starten (Datenbankmigrationen)
docker compose up migrator

# 4. Alle Services neu starten
docker compose up -d --force-recreate

Verifizieren: Nach dem Update laufen alle Services mit den neuen Images.

docker compose ps
# Alle Services: Up (außer migrator: Exited (0))

docker compose logs api | grep -i "version\|starting"
# Zeigt die neue Plane-Version in den Logs

Troubleshooting / Typische Fehler

  1. CORS-Fehler im Browser (API-Aufrufe schlagen fehl): WEB_URL und CORS_ALLOWED_ORIGINS in plane.env stimmen nicht mit dem tatsächlichen Hostnamen überein. Beide Variablen müssen identisch sein, inkl. Protokoll und Port (wenn nicht 80/443), ohne abschließenden Slash. Lösung: Werte anpassen, dann docker compose up -d --force-recreate.
  2. Port 80 bereits belegt (proxy startet nicht): Ein anderer Dienst belegt Port 80. Lösung: LISTEN_HTTP_PORT=8080 in plane.env setzen. Diagnose: docker compose logs proxy zeigt „bind: address already in use".
  3. Datei-Uploads schlagen fehl (MinIO-Bucket fehlt): Nach dem ersten Start muss der Bucket „uploads" in MinIO existieren. Prüfe mit docker compose logs plane-minio. Falls der Bucket fehlt: docker compose exec plane-minio mc mb local/uploads.
  4. Migrator läuft nicht durch (Datenbankfehler): Prüfe ob die Datenbank erreichbar ist: docker compose logs plane-db. Der Healthcheck muss „healthy" anzeigen, bevor der Migrator startet. Häufig ist ein falsch gesetztes POSTGRES_PASSWORD die Ursache.
  5. RabbitMQ akzeptiert neue Credentials nicht: RABBITMQ_DEFAULT_PASS wird nur beim allerersten Start in das Volume geschrieben. Nachträgliche Änderungen in plane.env haben keine Wirkung. Lösung: Volume löschen (docker compose down && docker volume rm plane_rabbitmq_data), dann neuen Stack starten. Achtung: Dadurch gehen ausstehende Queue-Einträge verloren.
  6. Änderungen an plane.env zeigen keine Wirkung: docker compose restart reicht nicht – du benötigst docker compose up -d --force-recreate, damit alle Container die neuen Umgebungsvariablen neu einlesen.
  7. ARM64 / Raspberry Pi mit :canary oder :preview: Diese Tags unterstützen nur linux/amd64. Auf ARM64-Hosts (AWS Graviton, Apple Silicon) immer :stable oder versionierte Tags verwenden.

Häufige Fragen

Brauche ich eine Lizenz für die Community Edition?

Nein. Die Plane CE ist unter AGPL-3.0 vollständig kostenlos nutzbar – für interne Projektverwaltung, auch im KMU-Kontext. Eine kostenpflichtige kommerzielle Lizenz wird nur benötigt, wenn du Plane als Basis für ein eigenes SaaS-Angebot betreiben oder die Commercial Edition mit Priority-Support, erweiterter KI (Plane PI), SAML-SSO-Enterprise und erweiterten Analytics nutzen möchtest.

Wie viele Ressourcen verbraucht Plane im Betrieb?

Die 12 Container zusammen benötigen im Idle ca. 1–2 GB RAM. Minimum sind 2 CPU-Kerne und 4 GB RAM für einen stabilen Betrieb. Für Produktionsumgebungen mit mehreren gleichzeitigen Nutzern empfehlen sich 8 GB RAM und die Erhöhung von GUNICORN_WORKERS auf 2–4.

Kann ich eine externe PostgreSQL-Datenbank oder S3 statt MinIO verwenden?

Ja. Für eine externe Datenbank kannst du DATABASE_URL als vollständigen Connection-String setzen, statt der einzelnen PGHOST/PGDATABASE-Variablen. Für externen S3-Speicher (AWS S3, Cloudflare R2, Hetzner Object Storage) setzt du USE_MINIO=0 und konfigurierst AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY und AWS_S3_ENDPOINT_URL auf den externen Dienst. Dies ist für Produktionsumgebungen ausdrücklich empfohlen, um Datenverlust bei Container-Ausfall zu vermeiden.

Wie richte ich SSO und E-Mail ein?

Plane unterstützt OAuth via GitHub, GitLab, Google und Slack sowie SMTP für E-Mail-Benachrichtigungen. Diese Einstellungen konfigurierst du komfortabel über das Admin-Panel unter http://deinhost/god-mode/ – ohne direktes Bearbeiten von plane.env.

Was ist Valkey und warum kein Redis?

Valkey ist ein BSD-lizenzierter Fork von Redis, der nach der Redis-Lizenzänderung im Jahr 2024 entstand. Plane setzt seit v1.2.x offiziell auf valkey/valkey:7.2.11-alpine. Alle Redis-Clients sind vollständig kompatibel. Ältere Anleitungen, die noch redis:7-alpine nennen, sind veraltet.

Wie sichere ich meine Plane-Daten?

Plane nutzt ausschließlich benannte Docker-Volumes (pgdata, redisdata, uploads, rabbitmq_data). Das wichtigste Volume ist pgdata (PostgreSQL). Für automatisierte Backups nutze pg_dump via Cronjob oder einen Backup-Stack. Mehr dazu in MySQL & PostgreSQL Backup automatisieren mit cron.

Fazit

Plane ist eine der ausgereiftesten Open-Source-Alternativen zu Jira und Linear, die du vollständig unter eigener Kontrolle betreiben kannst. Mit 12 Docker-Containern bringt der Stack zwar etwas mehr Komplexität als ein Single-Container-Tool mit – dafür erhältst du eine vollwertige Projektmanagement-Plattform mit Issues, Sprints, Roadmaps, Wikis und Echtzeit-Kollaboration, die für KMU mit bis zu 50 Nutzern auf einem günstigen VPS problemlos skaliert. Der einzige kritische Schritt beim Setup ist der SECRET_KEY: Wer hier einen echten, zufälligen Wert verwendet und WEB_URL korrekt setzt, vermeidet die häufigsten Fallstricke von Beginn an. Für den Produktionsbetrieb lohnt sich der Schritt zu einem externen PostgreSQL und S3-kompatiblen Objektspeicher – dann steht einem dauerhaften Betrieb nichts mehr im Weg.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
  3. PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
  4. MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump, Rotation und rclone-Cloud-Sync
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb

Offizielle Quellen: Plane Self-Hosting Dokumentation (developers.plane.so) · Plane GitHub-Repository (makeplane/plane)