Huly mit Docker installieren: All-in-One Collaboration-Workspace als Notion- und Linear-Ersatz
Huly vereint Projektmanagement, HR, Chat und Docs in einem Docker-Stack – Open-Source-Ersatz für Notion, Linear und Slack. Diese Anleitung zeigt den vollständigen Weg: compose.yaml, .env mit Secrets, Nginx-Routing und Verifikation nach jedem Schritt.

Wer im Team mehrere SaaS-Tools gleichzeitig bezahlt – ein Tool für Aufgaben, eines für Docs, eines für Chat – kennt das Problem: Kontext geht zwischen den Apps verloren, und die monatliche Rechnung wächst mit jedem neuen Mitarbeiter. Huly ist eine Apache-2.0-lizenzierte Open-Source-Plattform mit über 26.000 GitHub Stars, die genau diese Lücke schließt. Ein einziger Docker-Stack liefert Projektmanagement (Issues, Sprints, Roadmaps), HR-Workflows, Echtzeit-Kollaboration an Dokumenten und einen integrierten Team-Chat – ohne externen SaaS-Anbieter. Diese Anleitung richtet sich an KMU-Admins und ambitionierte Selfhoster, die den Stack auf einem Linux-Host oder einer VM dauerhaft betreiben wollen.
Voraussetzungen
- Docker Engine >= 24.x mit dem Docker Compose Plugin >= 2.x – falls noch nicht installiert, findest du die Einrichtung in der Anleitung Docker und Docker Compose auf Linux installieren.
- Linux-Host oder VM mit x86_64/amd64-Architektur. ARM64 (Apple Silicon, Raspberry Pi) wird wegen Elasticsearch 7.14.2 nicht vollständig unterstützt – dazu mehr im Troubleshooting-Abschnitt.
- Mindestens 2 vCPUs und 8 GB RAM, empfohlen 4 vCPUs und 16 GB RAM. Elasticsearch allein belegt 1–2 GB Heap; zusammen mit CockroachDB, Redpanda und den neun Applikationsdiensten ist alles unter 8 GB RAM ein ernstes OOM-Risiko.
- Mindestens 20 GB freier Speicher – Elasticsearch-Indizes wachsen mit dem Datenvolumen schnell.
- Internet-Zugang beim ersten Start (ca. 3–5 GB Download für alle Images plus das Elasticsearch-Plugin).
- openssl zur Secret-Generierung (auf nahezu allen Linux-Systemen vorinstalliert).
- 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
Lege einen dedizierten Ordner für den Huly-Stack an. Alle Konfigurationsdateien landen dort nebeneinander.
sudo mkdir -p /opt/huly
cd /opt/hulyPrüfe, welcher Image-Tag aktuell verfügbar ist. Das offizielle huly-selfhost-Repository hat keine GitHub-Releases – maßgebliche Quelle für aktuelle Tags ist ausschließlich Docker Hub:
# Aktuelle Tags prüfen (Browser):
# https://hub.docker.com/r/hardcoreeng/front/tags
# Zum Zeitpunkt dieser Anleitung: v0.7.423Verifizieren: Das Verzeichnis existiert und Docker ist einsatzbereit:
ls -la /opt/huly
docker --version # z.B. Docker version 26.1.4
docker compose version # z.B. Docker Compose version v2.27.1Schritt 2: .env-Datei mit Secrets anlegen
Huly teilt ein gemeinsames SECRET als JWT-Signaturschlüssel über alle Dienste hinweg. Ein Mismatch zwischen Diensten führt zu sofortigen Authentifizierungsfehlern – deshalb generierst du alle Secrets einmalig und speicherst sie in der .env-Datei, bevor du irgendeinen Container startest.
# 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.423
# Netzwerk
HOST_ADDRESS=localhost:8087
HTTP_PORT=8087
HTTP_BIND=
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=cockroachdb://selfhost:${CR_PASS}@cockroach:26257/defaultdb?sslmode=disable
# Redpanda
REDPANDA_ADMIN_USER=superadmin
REDPANDA_ADMIN_PWD=${RP_PASS}
# Darstellung
TITLE=Huly Self Host
DEFAULT_LANGUAGE=en
LAST_NAME_FIRST=true
# Optionale Volume-Pfade (leer = Docker named volumes)
VOLUME_ELASTIC_PATH=
VOLUME_FILES_PATH=
VOLUME_CR_DATA_PATH=
VOLUME_CR_CERTS_PATH=
VOLUME_REDPANDA_PATH=
EOF
# Datei vor anderen Benutzern schützen
chmod 600 /opt/huly/.envVerifizieren: Alle Secrets sind gesetzt und nicht leer:
grep -E "^SECRET=|^CR_USER_PASSWORD=|^REDPANDA_ADMIN_PWD=" /opt/huly/.env
# Erwartete Ausgabe: drei Zeilen mit je einem langen Hex-StringSchritt 3: compose.yaml erstellen
Die folgende compose.yaml entspricht dem offiziellen huly-selfhost-Stack. Elasticsearch ist auf Version 7.14.2 festgepinnt – eine neuere Version würde ohne weitere Konfigurationsanpassungen nicht funktionieren. MinIO läuft mit den Standard-Zugangsdaten minioadmin/minioadmin, die in sechs Diensten hinterlegt sind; für den Produktionsbetrieb musst du diese an allen Stellen gemeinsam ändern.
name: ${DOCKER_NAME:-huly}
services:
nginx:
image: "nginx:1.21.3"
ports:
- "${HTTP_BIND:-}${HTTP_PORT:-8087}:80"
volumes:
- ./.huly.nginx:/etc/nginx/conf.d/default.conf
restart: unless-stopped
networks:
- huly_net
depends_on:
- front
- account
- transactor
- collaborator
cockroach:
image: cockroachdb/cockroach:latest-v24.2
command: start-single-node --accept-sql-without-tls
environment:
- COCKROACH_DATABASE=${CR_DATABASE:-defaultdb}
- COCKROACH_USER=${CR_USERNAME:-selfhost}
- COCKROACH_PASSWORD=${CR_USER_PASSWORD}
volumes:
- ${VOLUME_CR_DATA_PATH:-cr_data}:/cockroach/cockroach-data
- ${VOLUME_CR_CERTS_PATH:-cr_certs}:/cockroach/certs
restart: unless-stopped
networks:
- huly_net
redpanda:
image: docker.redpanda.com/redpandadata/redpanda:v24.3.6
command:
- redpanda
- start
- --kafka-addr internal://0.0.0.0:9092,external://0.0.0.0:19092
- --advertise-kafka-addr internal://redpanda:9092,external://localhost:19092
- --pandaproxy-addr internal://0.0.0.0:8082,external://0.0.0.0:18082
- --advertise-pandaproxy-addr internal://redpanda:8082,external://localhost:18082
- --schema-registry-addr internal://0.0.0.0:8081,external://0.0.0.0:18081
- --rpc-addr redpanda:33145
- --advertise-rpc-addr redpanda:33145
- --mode dev-container
- --smp 1
- --default-log-level=info
volumes:
- ${VOLUME_REDPANDA_PATH:-redpanda}:/var/lib/redpanda/data
environment:
- REDPANDA_SUPERUSER_USERNAME=${REDPANDA_ADMIN_USER:-superadmin}
- REDPANDA_SUPERUSER_PASSWORD=${REDPANDA_ADMIN_PWD}
healthcheck:
test: ['CMD', 'rpk', 'cluster', 'info', '-X', 'user=${REDPANDA_ADMIN_USER:-superadmin}', '-X', 'pass=${REDPANDA_ADMIN_PWD}']
interval: 10s
timeout: 5s
retries: 10
restart: unless-stopped
networks:
- huly_net
minio:
image: "minio/minio"
command: server /data --address ":9000" --console-address ":9001"
volumes:
- ${VOLUME_FILES_PATH:-files}:/data
healthcheck:
test: ['CMD', 'mc', 'ready', 'local']
interval: 5s
retries: 10
restart: unless-stopped
networks:
- huly_net
elastic:
image: "elasticsearch:7.14.2"
command: |
/bin/sh -c "./bin/elasticsearch-plugin list | grep -q ingest-attachment || yes | ./bin/elasticsearch-plugin install --silent ingest-attachment;
/usr/local/bin/docker-entrypoint.sh eswrapper"
volumes:
- ${VOLUME_ELASTIC_PATH:-elastic}:/usr/share/elasticsearch/data
environment:
- ELASTICSEARCH_PORT_NUMBER=9200
- BITNAMI_DEBUG=true
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms1024m -Xmx1024m
- http.cors.enabled=true
- http.cors.allow-origin=http://localhost:8082
healthcheck:
test: curl -s http://localhost:9200/_cluster/health | grep -vq '"status":"red"'
interval: 20s
retries: 10
restart: unless-stopped
networks:
- huly_net
rekoni:
image: hardcoreeng/rekoni-service:${HULY_VERSION}
environment:
- SECRET=${SECRET}
deploy:
resources:
limits:
memory: 500M
restart: unless-stopped
networks:
- huly_net
transactor:
image: hardcoreeng/transactor:${HULY_VERSION}
environment:
- SERVER_PORT=3333
- SERVER_SECRET=${SECRET}
- DB_URL=${CR_DB_URL}
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
- FRONT_URL=http://${HOST_ADDRESS}
- ACCOUNTS_URL=http://account:3000
- FULLTEXT_URL=http://fulltext:4700
- STATS_URL=http://stats:4900
- LAST_NAME_FIRST=${LAST_NAME_FIRST:-true}
- QUEUE_CONFIG=redpanda:9092
depends_on:
cockroach:
condition: service_started
redpanda:
condition: service_healthy
minio:
condition: service_healthy
restart: unless-stopped
networks:
- huly_net
collaborator:
image: hardcoreeng/collaborator:${HULY_VERSION}
environment:
- COLLABORATOR_PORT=3078
- SECRET=${SECRET}
- ACCOUNTS_URL=http://account:3000
- STATS_URL=http://stats:4900
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
restart: unless-stopped
networks:
- huly_net
account:
image: hardcoreeng/account:${HULY_VERSION}
environment:
- SERVER_PORT=3000
- SERVER_SECRET=${SECRET}
- DB_URL=${CR_DB_URL}
- TRANSACTOR_URL=ws://transactor:3333;ws${SECURE:+s}://${HOST_ADDRESS}/_transactor
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
- FRONT_URL=http${SECURE:+s}://${HOST_ADDRESS}
- STATS_URL=http${SECURE:+s}://${HOST_ADDRESS}/_stats
- MODEL_ENABLED=*
- ACCOUNTS_URL=http${SECURE:+s}://${HOST_ADDRESS}/_accounts
- ACCOUNT_PORT=3000
- QUEUE_CONFIG=redpanda:9092
depends_on:
cockroach:
condition: service_started
redpanda:
condition: service_healthy
restart: unless-stopped
networks:
- huly_net
workspace:
image: hardcoreeng/workspace:${HULY_VERSION}
environment:
- SERVER_SECRET=${SECRET}
- DB_URL=${CR_DB_URL}
- TRANSACTOR_URL=ws://transactor:3333;ws${SECURE:+s}://${HOST_ADDRESS}/_transactor
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
- MODEL_ENABLED=*
- ACCOUNTS_URL=http://account:3000
- STATS_URL=http://stats:4900
- QUEUE_CONFIG=redpanda:9092
- ACCOUNTS_DB_URL=${CR_DB_URL}
depends_on:
cockroach:
condition: service_started
restart: unless-stopped
networks:
- huly_net
front:
image: hardcoreeng/front:${HULY_VERSION}
environment:
- SERVER_PORT=8080
- SERVER_SECRET=${SECRET}
- LOVE_ENDPOINT=http${SECURE:+s}://${HOST_ADDRESS}/_love
- ACCOUNTS_URL=http${SECURE:+s}://${HOST_ADDRESS}/_accounts
- ACCOUNTS_URL_INTERNAL=http://account:3000
- REKONI_URL=http${SECURE:+s}://${HOST_ADDRESS}/_rekoni
- CALENDAR_URL=http${SECURE:+s}://${HOST_ADDRESS}/_calendar
- GMAIL_URL=http${SECURE:+s}://${HOST_ADDRESS}/_gmail
- TELEGRAM_URL=http${SECURE:+s}://${HOST_ADDRESS}/_telegram
- STATS_URL=http${SECURE:+s}://${HOST_ADDRESS}/_stats
- UPLOAD_URL=/files
- ELASTIC_URL=http://elastic:9200
- COLLABORATOR_URL=ws${SECURE:+s}://${HOST_ADDRESS}/_collaborator
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
- TITLE=${TITLE:-Huly Self Host}
- DEFAULT_LANGUAGE=${DEFAULT_LANGUAGE:-en}
- LAST_NAME_FIRST=${LAST_NAME_FIRST:-true}
- DESKTOP_UPDATES_CHANNEL=${DESKTOP_CHANNEL:-}
- DISABLED_FEATURES=auto-translate,mailboxes
restart: unless-stopped
networks:
- huly_net
fulltext:
image: hardcoreeng/fulltext:${HULY_VERSION}
environment:
- SERVER_SECRET=${SECRET}
- DB_URL=${CR_DB_URL}
- FULLTEXT_DB_URL=http://elastic:9200
- ELASTIC_INDEX_NAME=huly_storage_index
- STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
- REKONI_URL=http://rekoni:4004
- ACCOUNTS_URL=http://account:3000
- STATS_URL=http://stats:4900
- QUEUE_CONFIG=redpanda:9092
depends_on:
elastic:
condition: service_healthy
restart: unless-stopped
networks:
- huly_net
stats:
image: hardcoreeng/stats:${HULY_VERSION}
environment:
- PORT=4900
- SERVER_SECRET=${SECRET}
restart: unless-stopped
networks:
- huly_net
kvs:
image: hardcoreeng/hulykvs:${HULY_VERSION}
depends_on:
cockroach:
condition: service_started
ports:
- "8094:8094"
environment:
- HULY_DB_CONNECTION=${CR_DB_URL}
- HULY_TOKEN_SECRET=${SECRET}
restart: unless-stopped
networks:
- huly_net
volumes:
elastic:
files:
cr_data:
cr_certs:
redpanda:
mongodb:
networks:
huly_net:Verifizieren: Die YAML-Syntax ist korrekt:
cd /opt/huly
docker compose config --quiet && echo "Syntax OK"
# Erwartete Ausgabe: Syntax OKSchritt 4: Nginx-Konfiguration erstellen
Der Nginx-Container erwartet eine Konfigurationsdatei unter .huly.nginx im Projektordner. Ohne diese Datei startet Nginx nicht – das ist ein häufiger Fallstrick beim manuellen Aufsetzen ohne das offizielle setup.sh-Skript.
cat > /opt/huly/.huly.nginx <<'EOF'
server {
listen 80;
server_name _;
client_max_body_size 256M;
location / {
proxy_pass http://front:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /_transactor {
proxy_pass http://transactor:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location /_accounts {
proxy_pass http://account:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /_collaborator {
proxy_pass http://collaborator:3078;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location /files {
proxy_pass http://minio:9000;
proxy_set_header Host $host;
}
location /_rekoni {
proxy_pass http://rekoni:4004;
proxy_set_header Host $host;
}
location /_stats {
proxy_pass http://stats:4900;
proxy_set_header Host $host;
}
}
EOFVerifizieren: Die Datei existiert und hat eine sinnvolle Größe:
ls -lh /opt/huly/.huly.nginx
# Erwartete Ausgabe: Datei mit mehreren Hundert BytesSchritt 5: Stack starten
Vor dem ersten Start lädst du alle Images herunter (ca. 3–5 GB), damit du Image-Pull-Fehler frühzeitig erkennst:
cd /opt/huly
docker compose pull
docker compose up -dDer allererste Start dauert 3–8 Minuten: Elasticsearch installiert beim Hochfahren automatisch das ingest-attachment-Plugin. CockroachDB und Redpanda benötigen ebenfalls 30–60 Sekunden zur Initialisierung.
Verifizieren: Status aller 14 Dienste prüfen – alle sollten nach ca. 5 Minuten Up oder healthy zeigen:
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 (healthy)
# huly-minio-1 minio/minio Up (healthy)
# huly-elastic-1 elasticsearch:7.14.2 Up (healthy)
# huly-front-1 hardcoreeng/front:v0.7.423 Up
# HTTP-Erreichbarkeit prüfen:
curl -I http://localhost:8087
# Erwartete Ausgabe: HTTP/1.1 200 OK (oder 302 Found)Schritt 6: Ersten Workspace im Browser einrichten
Öffne http://localhost:8087 im Browser. Der Ablauf beim ersten Aufruf:
- Account erstellen: Klicke auf „Create account", gib E-Mail und Passwort ein. Ohne konfigurierten SMTP-Server entfällt die E-Mail-Bestätigung – der Account ist sofort aktiv.
- Workspace anlegen: Nach dem Login wirst du aufgefordert, einen neuen Workspace zu benennen.
- Mitglieder einladen: Unter „Settings → Members" kannst du weitere Nutzer hinzufügen. Ohne SMTP musst du Einladungslinks manuell weitergeben oder SMTP nachkonfigurieren (siehe FAQ).
Verifizieren: Login funktioniert, Projekt anlegen und Aufgabe erstellen möglich. Echtzeit-Synchronisation zwischen zwei Browser-Tabs zeigt Änderungen sofort (Collaborator-Dienst aktiv):
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 → 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 | minio/minio:latest | 9000/9001 | S3-kompatibler Datei-Speicher |
| 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 | Key-Value-Store |
| workspace | hardcoreeng/workspace:${HULY_VERSION} | – | Workspace-Migrations-Service |
| Volume | Zweck | Hinweis |
|---|---|---|
| elastic | Elasticsearch-Indizes | Größter Datenspeicher |
| files | MinIO-Uploads | 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
Vor jedem Update die MIGRATION.md im huly-selfhost-Repository lesen – besonders beim Versionssprung von 0.6.x auf 0.7.x ist ein gesonderter Migrationsprozess nötig. Ein blindes docker compose pull && docker compose up -d kann dabei die Datenbank beschädigen.
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
# 4. Images laden und Stack starten
docker compose pull
docker compose up -dVerifizieren: Alle Dienste zeigen die neue Version und laufen ohne Fehler:
docker compose ps
docker compose logs --tail=30 account workspace
# Keine Migrations-Fehler oder "model mismatch"-Meldungen erwartetSchritt 8: Datenbank-Backup einrichten
CockroachDB ist die primäre Datenquelle – ein regelmäßiges Backup ist Pflicht. Elasticsearch-Indizes lassen sich im Notfall aus CockroachDB neu aufbauen. Eine vollständige Backup-Strategie inklusive Rotation und Off-Site-Sync beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen.
cd /opt/huly
# CockroachDB-Dump
docker compose exec cockroach cockroach dump defaultdb \
--insecure --user=selfhost > /opt/huly/backup-$(date +%Y%m%d).sql
# MinIO-Dateien sichern (Volume direkt kopieren)
docker run --rm \
--volumes-from huly-minio-1 \
-v /opt/backup:/backup \
alpine tar czf /backup/minio-$(date +%Y%m%d).tar.gz /dataVerifizieren: Die Backup-Datei existiert und hat eine sinnvolle Größe:
ls -lh /opt/huly/backup-*.sql
# Erwartete Ausgabe: Datei mit mindestens einigen KBTroubleshooting / Typische Fehler
- Nginx startet nicht: „no such file or directory: /etc/nginx/conf.d/default.conf" – Die Datei
.huly.nginxfehlt im Projektordner. Schritt 4 nachholen unddocker compose restart nginxausführen. - Elasticsearch wird nie „healthy", OOM-Kill in den Logs – Zu wenig RAM. Auf Systemen unter 8 GB stirbt Elasticsearch häufig mit OOM-Kill. RAM erhöhen oder Heap in der
compose.yamlverringern:ES_JAVA_OPTS=-Xms512m -Xmx512m(senkt aber die Suchperformance). - „manifest not found" beim
docker compose pull– Die eingetrageneHULY_VERSIONexistiert nicht auf Docker Hub. Aktuellen Tag auf hub.docker.com/r/hardcoreeng/front/tags prüfen und.envanpassen. - Login schlägt mit „401 unauthorized" fehl – Unterschiedliche
SECRET-Werte in den Diensten. Passiert, wenn das Secret nach dem Erststart geändert wurde ohne alle Dienste gleichzeitig neu zu starten. Lösung:docker compose down && docker compose up -d– niemals einzelne Dienste neu starten. - ARM64/Apple Silicon: Elasticsearch startet nicht – Elasticsearch 7.14.2 hat kein offizielles ARM64-Image. Workaround: dem
elastic-Service in dercompose.yamlplatform: linux/amd64hinzufügen und Rosetta/QEMU-Emulation aktivieren. Die Performance ist deutlich schlechter als nativ. - Erster Start:
fulltext-Dienst startet nicht – Elasticsearch braucht beim allerersten Start 2–5 Minuten für die Plugin-Installation. Beobachten mitdocker compose logs -f elastic; sobald Elasticsearch „green" meldet,docker compose start fulltextausführen. - Custom Volume-Pfade: „Permission denied" – Host-Verzeichnisse für
VOLUME_ELASTIC_PATH,VOLUME_FILES_PATHundVOLUME_CR_DATA_PATHbenötigenchown -R 1000:1000 /pfad. Für den Redpanda-Pfad gilt abweichendchown -R 101:101 /pfad.
Häufige Fragen
Wie richte ich E-Mail-Benachrichtigungen ein?
Ergänze deine .env um SMTP-Variablen und starte den Stack neu. Wichtig: SMTP und Amazon SES dürfen nicht gleichzeitig konfiguriert sein.
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=noreply@example.com
SMTP_PASS=deinPasswortWie aktiviere ich HTTPS für den Produktionsbetrieb?
Setze SECURE=true in der .env und passe HOST_ADDRESS auf deinen Domainnamen an (ohne Port, z. B. huly.example.com). Stelle einen vorgelagerten Reverse Proxy (Traefik, Caddy oder System-Nginx) vor den Docker-Nginx, der SSL terminiert und Anfragen auf Port 8087 weiterleitet. 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) – erkennbar am DISABLED_FEATURES-Parameter im front-Dienst. Video-Calls erfordern eine eigene LiveKit-Instanz, der KI-Chatbot benötigt einen OpenAI API Key plus MongoDB. Cloudexklusive Features wie ein dediziertes Backup-System und PDF-Generierung sind nicht enthalten.
Kann ich MinIO durch externen S3-Speicher ersetzen?
Ja. Ändere STORAGE_CONFIG in allen sechs betroffenen Diensten (transactor, collaborator, account, workspace, front, fulltext) auf die S3-kompatible URL deines Anbieters. Für die Produktion solltest du in jedem Fall die Standard-Zugangsdaten minioadmin/minioadmin ersetzen – sie stehen derzeit in allen sechs Service-Definitionen hardcodiert. Wie du ein eigenes MinIO-Backend aufbaust, zeigt MinIO S3 selbst hosten mit Docker.
Wie sichere ich den Stack gegen unbefugten Zugriff ab?
Im Grundbetrieb schützt das gemeinsame SECRET die interne API-Kommunikation. Für den öffentlichen Betrieb sind HTTPS (Pflicht), eine Firewall und das regelmäßige Einspielen von Updates essenziell. Den Server selbst absichern beschreibt VPS absichern und härten: UFW, SSH-Keys und Fail2Ban.
Fazit
Huly ist technisch ambitioniert: 14 Docker-Dienste, drei spezialisierte Infrastruktur-Komponenten und ein gemeinsames Secret-Konzept verlangen beim Aufsetzen mehr Sorgfalt als ein typischer Einzel-Container. Wer diese Hürde nimmt, bekommt einen vollständigen Collaboration-Stack ohne monatliche Lizenzkosten und ohne externe Cloud-Abhängigkeiten. Für ein Team von 5–50 Personen, das Notion, Linear und Slack durch eine einzige self-hosted Plattform ersetzen will, ist Huly zum aktuellen Zeitpunkt die funktional vollständigste Open-Source-Option. Der größte operative Aufwand liegt im Betrieb: Elasticsearch-Pflege, regelmäßige CockroachDB-Backups und das sorgfältige Lesen der MIGRATION.md vor jedem Update sind keine Kann-Optionen, sondern Pflicht.
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
- MinIO S3 selbst hosten mit Docker: Compose-Anleitung mit Traefik und HTTPS
- 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
- VPS absichern und härten: UFW, SSH-Keys und Fail2Ban
Offizielle Quellen: Huly Self-Hosting Dokumentation · huly-selfhost Repository auf GitHub · hardcoreeng/front auf Docker Hub (aktuelle Tags)