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

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.

Huly mit Docker installieren: All-in-One Collaboration-Workspace als Notion- und Linear-Ersatz für Dokumente, Aufgaben, Issues, Roadmaps und Teamkommunikation. KI-generiert

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

  1. 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.
  2. 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.
  3. 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.
  4. Mindestens 20 GB freier Speicher – Elasticsearch-Indizes wachsen mit dem Datenvolumen schnell.
  5. Internet-Zugang beim ersten Start (ca. 3–5 GB Download für alle Images plus das Elasticsearch-Plugin).
  6. openssl zur Secret-Generierung (auf nahezu allen Linux-Systemen vorinstalliert).
  7. 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/huly

Prü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.423

Verifizieren: 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.1

Schritt 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/.env

Verifizieren: 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-String

Schritt 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 OK

Schritt 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;
    }
}
EOF

Verifizieren: Die Datei existiert und hat eine sinnvolle Größe:

ls -lh /opt/huly/.huly.nginx
# Erwartete Ausgabe: Datei mit mehreren Hundert Bytes

Schritt 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 -d

Der 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:

  1. 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.
  2. Workspace anlegen: Nach dem Login wirst du aufgefordert, einen neuen Workspace zu benennen.
  3. 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 erwartet

Dienste und Volumes auf einen Blick

DienstImagePort internFunktion
nginxnginx:1.21.380 → 8087Einziger externer Einstiegspunkt
cockroachcockroachdb/cockroach:latest-v24.226257SQL-Primärdatenbank
redpandaredpandadata/redpanda:v24.3.69092Kafka-kompatibler Message-Broker
miniominio/minio:latest9000/9001S3-kompatibler Datei-Speicher
elasticelasticsearch:7.14.29200Volltextsuche (MUSS 7.14.2 sein)
fronthardcoreeng/front:${HULY_VERSION}8080Web-UI
accounthardcoreeng/account:${HULY_VERSION}3000Authentifizierung
transactorhardcoreeng/transactor:${HULY_VERSION}3333Kern-API (WebSocket)
collaboratorhardcoreeng/collaborator:${HULY_VERSION}3078Echtzeit-Docs (Y.js CRDT)
fulltexthardcoreeng/fulltext:${HULY_VERSION}4700Suchindex-Service
rekonihardcoreeng/rekoni-service:${HULY_VERSION}4004Dokument-Parsing
statshardcoreeng/stats:${HULY_VERSION}4900Metriken
kvshardcoreeng/hulykvs:${HULY_VERSION}8094Key-Value-Store
workspacehardcoreeng/workspace:${HULY_VERSION}Workspace-Migrations-Service
VolumeZweckHinweis
elasticElasticsearch-IndizesGrößter Datenspeicher
filesMinIO-UploadsNutzer-Dateien und Anhänge
cr_dataCockroachDB-DatenbankdateienPrimäre Datenquelle – regelmäßig sichern
cr_certsCockroachDB-ZertifikateIntern, kein TLS in dieser Konfiguration
redpandaRedpanda-Message-LogKann 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 -d

Verifizieren: 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 erwartet

Schritt 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 /data

Verifizieren: Die Backup-Datei existiert und hat eine sinnvolle Größe:

ls -lh /opt/huly/backup-*.sql
# Erwartete Ausgabe: Datei mit mindestens einigen KB

Troubleshooting / Typische Fehler

  1. Nginx startet nicht: „no such file or directory: /etc/nginx/conf.d/default.conf" – Die Datei .huly.nginx fehlt im Projektordner. Schritt 4 nachholen und docker compose restart nginx ausführen.
  2. 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.yaml verringern: ES_JAVA_OPTS=-Xms512m -Xmx512m (senkt aber die Suchperformance).
  3. „manifest not found" beim docker compose pull – Die eingetragene HULY_VERSION existiert nicht auf Docker Hub. Aktuellen Tag auf hub.docker.com/r/hardcoreeng/front/tags prüfen und .env anpassen.
  4. 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.
  5. ARM64/Apple Silicon: Elasticsearch startet nicht – Elasticsearch 7.14.2 hat kein offizielles ARM64-Image. Workaround: dem elastic-Service in der compose.yaml platform: linux/amd64 hinzufügen und Rosetta/QEMU-Emulation aktivieren. Die Performance ist deutlich schlechter als nativ.
  6. Erster Start: fulltext-Dienst startet nicht – Elasticsearch braucht beim allerersten Start 2–5 Minuten für die Plugin-Installation. Beobachten mit docker compose logs -f elastic; sobald Elasticsearch „green" meldet, docker compose start fulltext ausführen.
  7. Custom Volume-Pfade: „Permission denied" – Host-Verzeichnisse für VOLUME_ELASTIC_PATH, VOLUME_FILES_PATH und VOLUME_CR_DATA_PATH benötigen chown -R 1000:1000 /pfad. Für den Redpanda-Pfad gilt abweichend chown -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=deinPasswort

Wie 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

  1. Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
  2. Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
  3. MinIO S3 selbst hosten mit Docker: Compose-Anleitung mit Traefik und HTTPS
  4. 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud
  5. 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)