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.

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
- Docker Engine 24+ und Docker Compose Plugin v2 (Befehl:
docker compose, nichtdocker-compose) – siehe Docker und Docker Compose auf Linux installieren - 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)
- Mindestens 2 CPU-Kerne (x86_64 oder ARM64) und 4 GB RAM (8 GB für Produktion empfohlen)
- Mindestens 20 GB freier Festplattenplatz (Images ca. 3–4 GB, Daten wachsend)
- Internetzugang zum Herunterladen der Docker-Images
- Für Produktionsbetrieb: Domainname und ein vorgelagerter Reverse Proxy für HTTPS – sieh dir dazu Traefik als Docker-Reverse-Proxy mit automatischem HTTPS an
opensslzur Generierung des SECRET_KEY (auf fast jedem Linux-System vorinstalliert)
Eckdaten auf einen Blick
| Eigenschaft | Wert |
|---|---|
| Aktuelle stabile Version | v1.3.1 (Mai 2026) |
| Lizenz | AGPL-3.0 (CE kostenlos) |
| Architektur | linux/amd64 + linux/arm64 |
| Eintrittspunkt (extern) | Port 80 (HTTP), Port 443 (HTTPS) |
| Minimale RAM | 4 GB (8 GB empfohlen) |
| Container im Stack | 12 (inkl. einmaligem Migrator) |
| Service | Image | Zweck |
|---|---|---|
| proxy | makeplane/plane-proxy:stable | Nginx-Reverse-Proxy, einziger externer Eintrittspunkt |
| web | makeplane/plane-frontend:stable | React-Frontend |
| api | makeplane/plane-backend:stable | Django-REST-API |
| worker | makeplane/plane-backend:stable | Celery-Worker für Hintergrundaufgaben |
| beat-worker | makeplane/plane-backend:stable | Celery Beat (Cronjobs) |
| live | makeplane/plane-live:stable | Node.js Echtzeit-Kollaboration |
| admin | makeplane/plane-admin:stable | Admin-Panel |
| space | makeplane/plane-space:stable | Space-Modul (öffentliche Boards) |
| migrator | makeplane/plane-backend:stable | Django-Datenbankmigrationen (einmalig) |
| plane-db | postgres:15.7-alpine | PostgreSQL-Datenbank |
| plane-redis | valkey/valkey:7.2.11-alpine | Key-Value-Store (Redis-kompatibel) |
| plane-mq | rabbitmq:3.13.6-management-alpine | Message-Queue |
| plane-minio | minio/minio:latest | S3-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/planeVerifizieren: Der Ordner existiert und du befindest dich darin.
pwd
# Erwartete Ausgabe: /opt/planeSchritt 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: a3f8c2e1d9b047563a1f2c8e4d6b0a9f5e7c3d1b2a8f4e6c0d2b9a7f3e5c1d8Erstelle 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=stableWichtige Hinweise zur Konfiguration:
- 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.
- AWS_ACCESS_KEY_ID und MINIO_ROOT_USER müssen denselben Wert haben – dasselbe gilt für das zugehörige Passwort-Paar.
- Für lokale Tests kannst du
WEB_URL=http://localhostsetzen 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.yamlSchritt 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 -dBeobachte den Startvorgang in Echtzeit (optional, mit Ctrl+C abbrechen):
docker compose logs -f migrator
# Warte auf: "Migrations completed" oder ähnliche AbschlussmeldungVerifizieren: 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 minutesDer 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.
- Klicke auf „Get started" und lege den ersten Admin-Account an (E-Mail-Adresse und Passwort).
- Danach kannst du einen Workspace erstellen – dies ist der oberste Organisationsrahmen in Plane, vergleichbar mit einer Jira-Instanz.
- Innerhalb des Workspace legst du Projekte an; jedes Projekt erhält Issues, Cycles (Sprints), Modules und Pages (Wiki).
- 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 BodySchritt 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.comNach Ä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-recreateVerifizieren: Der Proxy antwortet nun auf dem neuen internen Port.
curl -I http://localhost:8080
# Erwartete Ausgabe: HTTP/1.1 200 OK oder 302 FoundSchritt 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-recreateVerifizieren: 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 LogsTroubleshooting / Typische Fehler
- CORS-Fehler im Browser (API-Aufrufe schlagen fehl):
WEB_URLundCORS_ALLOWED_ORIGINSinplane.envstimmen 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, danndocker compose up -d --force-recreate. - Port 80 bereits belegt (proxy startet nicht): Ein anderer Dienst belegt Port 80. Lösung:
LISTEN_HTTP_PORT=8080inplane.envsetzen. Diagnose:docker compose logs proxyzeigt „bind: address already in use". - 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. - 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 gesetztesPOSTGRES_PASSWORDdie Ursache. - RabbitMQ akzeptiert neue Credentials nicht:
RABBITMQ_DEFAULT_PASSwird nur beim allerersten Start in das Volume geschrieben. Nachträgliche Änderungen inplane.envhaben 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. - Änderungen an plane.env zeigen keine Wirkung:
docker compose restartreicht nicht – du benötigstdocker compose up -d --force-recreate, damit alle Container die neuen Umgebungsvariablen neu einlesen. - ARM64 / Raspberry Pi mit :canary oder :preview: Diese Tags unterstützen nur linux/amd64. Auf ARM64-Hosts (AWS Graviton, Apple Silicon) immer
:stableoder 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
- Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
- MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump, Rotation und rclone-Cloud-Sync
- 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)