Huly mit Docker installieren: All-in-One Collaboration-Workspace als Notion- und Linear-Ersatz
Huly vereint Projektmanagement, Dokumente und Chat in einem Docker-Stack. Die Anleitung zeigt die offizielle compose.yml, die .env mit Secrets, das Nginx-Routing, Sicherung und Updates mit Prüfschritt nach jedem Schritt.
Werbung Mit * 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

Huly ist eine Open-Source-Plattform unter Apache-2.0-Lizenz: Ein Docker-Stack liefert Projektmanagement, Dokumente mit gemeinsamer Bearbeitung und Team-Chat ohne externen SaaS-Anbieter. Die Anleitung richtet sich an Administratoren in KMU, die den Stack auf einem Linux-Host oder einer VM dauerhaft betreiben.
Voraussetzungen
- Docker Engine >= 24.x mit dem Docker Compose Plugin >= 2.x. Die Einrichtung beschreibt die Anleitung Docker und Docker Compose auf Linux installieren.
- Linux-Host oder VM mit x86_64 (amd64) oder ARM64. Alle Images des Stacks, auch
elasticsearch:7.14.2, werden laut Docker Hub für beide Architekturen angeboten. - Mindestens 2 vCPUs und 8 GB RAM, empfohlen 4 vCPUs und 16 GB RAM (Herstellerangabe). Elasticsearch belegt allein 1 GB Heap; unter 8 GB RAM beendet der Kernel Dienste per OOM-Kill.
- Mindestens 20 GB freier Speicher für Images (rund 3 bis 5 GB) und Indizes.
- openssl und curl für Secrets und Downloads.
- Für HTTPS in Produktion: ein vorgelagerter Reverse Proxy sowie eine eigene Domain. Das Setup mit Traefik beschreibt Traefik als Docker-Reverse-Proxy mit automatischem HTTPS.
Schritt 1: Projektordner anlegen und Versionen prüfen
Legen Sie einen eigenen Ordner an und laden Sie compose.yml und .huly.nginx aus dem offiziellen Repository hcengineering/huly-selfhost. So stimmen Dienste, Variablen und Nginx-Routen mit dem Stand des Herstellers überein.
$ sudo mkdir -p /opt/huly
$ sudo chown "$USER": /opt/huly
$ cd /opt/huly
$ curl -fsSLO https://raw.githubusercontent.com/hcengineering/huly-selfhost/main/compose.yml
$ curl -fsSLO https://raw.githubusercontent.com/hcengineering/huly-selfhost/main/.huly.nginxDie freigegebene Version steht in .template.huly.conf und in der MIGRATION.md (aktuell v0.7.426). Docker Hub zeigt häufiger neuere v- und s-Tags; für Selfhost empfiehlt der Hersteller die in der MIGRATION.md aufgeführten v-Tags.
ls -la /opt/huly zeigt compose.yml und .huly.nginx, docker compose version meldet v2.x.
Schritt 2: .env-Datei mit Secrets anlegen
Huly nutzt ein gemeinsames SECRET als JWT-Signaturschlüssel für alle Dienste; abweichende Werte lassen jede Anmeldung scheitern. Erzeugen Sie alle Secrets einmalig in der .env, bevor ein Container startet. Die compose.yml setzt kaum Standardwerte, die .env muss vollständig sein.
# Secrets einmalig generieren
APP_SECRET=$(openssl rand -hex 32)
CR_PASS=$(openssl rand -hex 16)
RP_PASS=$(openssl rand -hex 16)
cat > /opt/huly/.env <<EOF
# Huly Stack: Konfiguration
DOCKER_NAME=huly
HULY_VERSION=v0.7.426
DESKTOP_CHANNEL=0.7.426
# Netzwerk (HTTP_BIND: IP ohne Port, z. B. 127.0.0.1 hinter einem Reverse Proxy)
HOST_ADDRESS=localhost:8087
HTTP_PORT=8087
HTTP_BIND=127.0.0.1
SECURE=
# Gemeinsames JWT-Secret (muss in allen Diensten identisch sein)
SECRET=${APP_SECRET}
# CockroachDB
CR_DATABASE=defaultdb
CR_USERNAME=selfhost
CR_USER_PASSWORD=${CR_PASS}
CR_DB_URL=postgres://selfhost:${CR_PASS}@cockroach:26257/defaultdb
# Redpanda
REDPANDA_ADMIN_USER=superadmin
REDPANDA_ADMIN_PWD=${RP_PASS}
# Darstellung
TITLE=Huly
DEFAULT_LANGUAGE=de
LAST_NAME_FIRST=true
# Optionale Volume-Pfade (leer = benannte Docker-Volumes)
VOLUME_ELASTIC_PATH=
VOLUME_FILES_PATH=
VOLUME_CR_DATA_PATH=
VOLUME_CR_CERTS_PATH=
VOLUME_REDPANDA_PATH=
EOF
chmod 600 /opt/huly/.envgrep -E "^SECRET=|^CR_USER_PASSWORD=|^REDPANDA_ADMIN_PWD=" /opt/huly/.env zeigt drei Zeilen mit je einem langen Hex-Wert.
Schritt 3: compose.yml prüfen und anpassen
Die compose.yml definiert 14 Dienste (Tabelle unten). Vor dem Start wichtig:
- Dateispeicher: Der Dienst heißt weiterhin
minio, nutzt seit September 2026 aber das S3-kompatible Imagepgsty/silo, daminio/minioauf Docker Hub nicht mehr abrufbar ist („pull access denied“). Die Zugangsdatenminioadmin/minioadminstehen fest in denSTORAGE_CONFIG-Zeilen; der Dienst ist nur im internen Netzhuly_neterreichbar. - Ports: Nach außen veröffentlichen nur
nginx(${HTTP_BIND}:${HTTP_PORT}) undkvs(8094:8094, alle Schnittstellen). Binden Siekvsan localhost. - Elasticsearch ist auf
7.14.2festgelegt, die übrigen Huly-Dienste folgenHULY_VERSION.
$ cd /opt/huly
$ sed -i 's/ - 8094:8094/ - 127.0.0.1:8094:8094/' compose.yml
$ grep -n "image:" compose.ymldocker compose config --quiet && echo "Syntax OK" gibt Syntax OK aus, und docker compose config | grep -A1 host_ip zeigt für beide veröffentlichten Ports 127.0.0.1.
Schritt 4: Nginx-Konfiguration prüfen
Der Nginx-Container bindet ./.huly.nginx als default.conf ein. Fehlt die Datei, legt Docker ein leeres Verzeichnis an und Nginx startet nicht. Die Datei enthält alle Routen: / auf front:8080, /_accounts, /_transactor, /_collaborator, /_rekoni und /_stats mit rewrite auf den Pfad ohne Präfix sowie WebSocket-Weiterleitung. Ohne diese rewrite-Regeln schlagen Anmeldungen fehl.
$ grep -E "location|proxy_pass" /opt/huly/.huly.nginxDie Ausgabe enthält unter anderem proxy_pass http://front:8080; und proxy_pass http://account:3000/;. file /opt/huly/.huly.nginx meldet eine Textdatei, kein Verzeichnis.
Schritt 5: Stack starten
Laden Sie zuerst alle Images (rund 3 bis 5 GB), damit Pull-Fehler vor dem Start auffallen:
$ cd /opt/huly
$ docker compose pull
$ docker compose up -dDer erste Start dauert 3 bis 8 Minuten, vor allem wegen der Plugin-Installation in Elasticsearch. Auf einem Host unter der Mindestanforderung (1 CPU, 3 GB RAM, deshalb ohne Elasticsearch, fulltext und kvs) liefen mit v0.7.426 Nginx, Weboberfläche, account, transactor, workspace, collaborator, CockroachDB, Redpanda und der Dateispeicher an; config.json meldete die Version. Eine Registrierung scheiterte dort am Speichermangel („504 Gateway Time-out“).
Nach etwa 5 Minuten zeigen alle 14 Dienste Up, minio und elastic zusätzlich (healthy). redpanda meldet mit der offiziellen compose.yml (unhealthy), weil der Healthcheck Zugangsdaten mitsendet, obwohl SASL im Entwicklungsmodus abgeschaltet ist (Meldung „ILLEGAL_SASL_STATE“). Die übrigen Dienste hängen nicht von diesem Status ab; prüfen Sie Redpanda mit docker compose exec redpanda rpk cluster info:
$ cd /opt/huly
$ docker compose ps
# Erwartetes Bild (Auszug):
# huly-nginx-1 nginx:1.21.3 Up
# huly-cockroach-1 cockroachdb/cockroach:latest-v24.2 Up
# huly-redpanda-1 redpandadata/redpanda:v24.3.6 Up (unhealthy)
# huly-minio-1 pgsty/silo Up (healthy)
# huly-elastic-1 elasticsearch:7.14.2 Up (healthy)
# huly-front-1 hardcoreeng/front:v0.7.426 Up
# HTTP-Erreichbarkeit prüfen:$ curl -I http://localhost:8087# Erwartete Ausgabe: HTTP/1.1 200 OK$ curl -s http://localhost:8087/config.json# Erwartete Ausgabe: JSON mit "VERSION":"0.7.426"Schritt 6: Ersten Workspace im Browser einrichten
Öffnen Sie http://localhost:8087 im Browser. Der Ablauf beim ersten Aufruf:
- Konto erstellen: Klicken Sie auf „Sign up“ und geben Sie E-Mail-Adresse und Passwort ein. Ohne SMTP-Server entfällt die E-Mail-Bestätigung, das Konto ist sofort aktiv.
- Workspace anlegen: Nach der Anmeldung vergeben Sie einen Namen für den Workspace.
- Mitglieder einladen: per Einladungslink, ohne Mail-Dienst geben Sie ihn selbst weiter (siehe Häufige Fragen).
Sie können ein Projekt und eine Aufgabe anlegen, eine Änderung erscheint ohne Neuladen in einem zweiten Browser-Tab:
$ docker compose logs --tail=20 account transactor collaborator# Keine "unauthorized", "connection refused" oder "ECONNRESET"-Fehler erwartetDienste und Volumes auf einen Blick
| Dienst | Image | Port intern | Funktion |
|---|---|---|---|
| nginx | nginx:1.21.3 | 80, außen 8087 | Einziger externer Einstiegspunkt |
| cockroach | cockroachdb/cockroach:latest-v24.2 | 26257 | SQL-Primärdatenbank |
| redpanda | redpandadata/redpanda:v24.3.6 | 9092 | Kafka-kompatibler Message-Broker |
| minio | pgsty/silo | 9000/9001 | S3-kompatibler Dateispeicher |
| elastic | elasticsearch:7.14.2 | 9200 | Volltextsuche (MUSS 7.14.2 sein) |
| front | hardcoreeng/front:${HULY_VERSION} | 8080 | Web-UI |
| account | hardcoreeng/account:${HULY_VERSION} | 3000 | Authentifizierung |
| transactor | hardcoreeng/transactor:${HULY_VERSION} | 3333 | Kern-API (WebSocket) |
| collaborator | hardcoreeng/collaborator:${HULY_VERSION} | 3078 | Echtzeit-Docs (Y.js CRDT) |
| fulltext | hardcoreeng/fulltext:${HULY_VERSION} | 4700 | Suchindex-Service |
| rekoni | hardcoreeng/rekoni-service:${HULY_VERSION} | 4004 | Dokument-Parsing |
| stats | hardcoreeng/stats:${HULY_VERSION} | 4900 | Metriken |
| kvs | hardcoreeng/hulykvs:${HULY_VERSION} | 8094 (127.0.0.1) | Key-Value-Store |
| workspace | hardcoreeng/workspace:${HULY_VERSION} | keiner | Workspace-Migrations-Service |
| Volume | Zweck | Hinweis |
|---|---|---|
| elastic | Elasticsearch-Indizes | Größter Datenspeicher |
| files | Uploads im Dateispeicher | Nutzer-Dateien und Anhänge |
| cr_data | CockroachDB-Datenbankdateien | Primäre Datenquelle, regelmäßig sichern |
| cr_certs | CockroachDB-Zertifikate | Intern, kein TLS in dieser Konfiguration |
| redpanda | Redpanda-Message-Log | Kann bei Bedarf neu aufgebaut werden |
Schritt 7: Updates einspielen
Lesen Sie vor jedem Update die MIGRATION.md; für 0.6.x auf 0.7.x ist ein eigener Migrationsweg (Backup und Restore in eine neue Installation) vorgeschrieben. Vergleichen Sie compose.yml und .huly.nginx mit dem Repository.
$ cd /opt/huly# 1. MIGRATION.md prüfen:
# https://github.com/hcengineering/huly-selfhost/blob/main/MIGRATION.md
# 2. Stack stoppen$ docker compose down# 3. Neue Version in .env setzen$ sed -i 's/^HULY_VERSION=.*/HULY_VERSION=v0.7.xxx/' .env # neue Version einsetzen
$ sed -i 's/^DESKTOP_CHANNEL=.*/DESKTOP_CHANNEL=0.7.xxx/' .env# 4. Images laden und Stack starten$ docker compose pull
$ docker compose up -ddocker compose ps zeigt die neuen Image-Tags, docker compose logs --tail=30 account workspace enthält keine Migrationsfehler.
Schritt 8: Datenbank-Backup einrichten
CockroachDB und der Dateispeicher enthalten alle Daten; den Elasticsearch-Index baut Huly bei Bedarf neu auf. Rotation und externe Kopien beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
cockroach dump existiert in CockroachDB 24.2 nicht mehr. Für eine konsistente Sicherung stoppen Sie den Stack kurz und archivieren die Volumes cr_data und files. Für Sicherungen im laufenden Betrieb liefert das Repository das Skript backup-create.sh (Workspace-Backup über das Huly-Tool).
cd /opt/huly
sudo mkdir -p /opt/backup
docker compose stop
for v in cr_data files; do
docker run --rm -v huly_${v}:/data:ro -v /opt/backup:/backup alpine \
tar czf /backup/huly-${v}-$(date +%Y%m%d).tar.gz -C /data .
done
docker compose startDer Volume-Name setzt sich aus DOCKER_NAME und Volume zusammen (huly_cr_data), prüfbar mit docker volume ls.
ls -lh /opt/backup/huly-* zeigt zwei Archive mit plausibler Größe, tar tzf listet deren Inhalt ohne Fehler.
Troubleshooting / Typische Fehler
- Nginx startet nicht: „no such file or directory: /etc/nginx/conf.d/default.conf“
.huly.nginxfehlt. Löschen Sie ein von Docker angelegtes gleichnamiges Verzeichnis, laden Sie die Datei wie in Schritt 1 und führen Siedocker compose up -d nginxaus. Bei „host not found in upstream“ läuft ein Zieldienst (z. B.collaborator) nicht; starten Sie den kompletten Stack.- Elasticsearch wird nie „healthy“, OOM-Kill in den Logs
Zu wenig RAM. RAM erhöhen oder den Heap in der
compose.yamlverringern:ES_JAVA_OPTS=-Xms512m -Xmx512m(senkt aber die Suchperformance).- „manifest not found“ beim
docker compose pull:HULY_VERSIONexistiert nicht. Version in der MIGRATION.md oder auf hub.docker.com/r/hardcoreeng/front/tags prüfen und.envanpassen.- „pull access denied for minio/minio“
Ältere Fassungen der
compose.ymlnutzen nochminio/minio. Ersetzen Sie das Image durchpgsty/silowie in der aktuellencompose.ymldes Herstellers.- Login schlägt mit „401 unauthorized“ fehl
Unterschiedliche
SECRET-Werte. Lösung:docker compose down && docker compose up -d.- Anmeldung schlägt fehl, UI lädt aber
Prüfen Sie zuerst
docker compose logs -f account. Häufige Ursache:HOST_ADDRESSoderSECUREpassen nicht zur aufgerufenen Adresse.- Erster Start
fulltext-Dienst startet nicht: Die Elasticsearch-Plugin-Installation dauert beim ersten Start einige Minuten (docker compose logs -f elastic);fulltextverbindet sich danach selbst neu, sonstdocker compose restart fulltext.- Eigene Volume-Pfade: „Permission denied“
Die Host-Verzeichnisse benötigen
chown -R 1000:1000 /pfad, der Redpanda-Pfadchown -R 101:101 /pfad.
Häufige Fragen
Wie richte ich E-Mail-Benachrichtigungen ein?
Ergänzen Sie in der compose.yml einen Dienst mail (Image hardcoreeng/mail:${HULY_VERSION}, PORT=8097, SOURCE = Absenderadresse, SMTP-Zugang) und tragen Sie MAIL_URL=http://mail:8097 bei account und transactor ein. SMTP und Amazon SES schließen sich aus. Das vollständige Beispiel steht im README.
mail:
image: hardcoreeng/mail:${HULY_VERSION}
environment:
- PORT=8097
- SOURCE=noreply@example.com
- SMTP_HOST=smtp.example.com
- SMTP_PORT=587
- SMTP_USERNAME=noreply@example.com
- SMTP_PASSWORD=IhrPasswort
restart: unless-stopped
networks:
- huly_netWie aktiviere ich HTTPS für den Produktionsbetrieb?
Setzen Sie SECURE=true in der .env und HOST_ADDRESS auf Ihren Domainnamen ohne Port (z. B. huly.example.com). Ein Reverse Proxy (Traefik, Caddy oder Nginx auf dem Host) terminiert TLS, leitet an 127.0.0.1:8087 weiter und muss WebSockets durchreichen. Das Traefik-Setup ist in der Anleitung Traefik als Docker-Reverse-Proxy mit automatischem HTTPS beschrieben.
Welche Features fehlen in der Self-hosted-Version?
Standardmäßig deaktiviert sind automatische Übersetzung (auto-translate) und Mailboxen (mailboxes), siehe DISABLED_FEATURES im Dienst front. Audio- und Videoanrufe brauchen eine eigene LiveKit-Instanz, der KI-Bot einen OpenAI-API-Schlüssel und MongoDB. Dienste wie print stehen nur auskommentiert in der compose.yml.
Kann ich MinIO durch externen S3-Speicher ersetzen?
Ja. Ändern Sie STORAGE_CONFIG in allen sechs betroffenen Diensten (transactor, collaborator, account, workspace, front, fulltext) auf die S3-kompatible Adresse Ihres Anbieters. Die Zugangsdaten minioadmin/minioadmin stehen fest in allen sechs Dienstdefinitionen und im Dienst minio; ändern Sie sie nur gemeinsam. Ein eigenes S3-Backend beschreibt SeaweedFS mit Docker selbst hosten.
Wie sichere ich den Stack gegen unbefugten Zugriff ab?
Für den öffentlichen Betrieb gehören HTTPS, eine Firewall, HTTP_BIND=127.0.0.1 hinter dem Proxy und regelmäßige Updates dazu. Den Server selbst absichern beschreibt VPS absichern und härten: UFW, SSH-Keys und Fail2Ban.
Fazit
Huly verlangt mit 14 Diensten mehr Sorgfalt als ein einzelner Container. Der Aufwand liegt im Betrieb: ausreichend RAM für Elasticsearch, Sicherung nach Schritt 8 und vor jedem Update der Abgleich nach Schritt 7. Mehr zu Healthchecks, Secrets und Betrieb ohne Root-Rechte steht in Docker Compose absichern: Secrets, Healthchecks und Non-Root.
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
- S3-Speicher nach dem MinIO-Aus: SeaweedFS mit Docker selbst hosten
- 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
- VPS absichern und härten: UFW, SSH-Keys und Fail2Ban
- Linux-Server absichern mit UFW und Fail2ban
Offizielle Quellen: MIGRATION.md · Huly Self-Hosting Dokumentation · huly-selfhost Repository auf GitHub · hardcoreeng/front auf Docker Hub (aktuelle Tags)


