This is an old revision of the document!
Table of Contents
Root³ Solutions LibreChat Deployment Guide
Stack: LibreChat + LM Studio (Qwen3 27B) + ComfyUI MCP Host: 192.168.1.203 — Nobara Linux, Podman (kein Docker) Installiert: 2026-10-19 URL: http://192.168.1.203:3080
1. Verzeichnisstruktur
Alle Dateien liegen in einem Ordner unter dem Home-Verzeichnis von rootai. Keine systemd-Units, keine separate .env-Datei — alles ist entweder inline in compose.yaml oder in der .env-Datei, die in den Container eingebunden wird.
~/librechat/ ├── compose.yaml # Podman Compose — 2 Services (api + mongodb) ├── librechat.yaml # LibreChat-Konfig — Endpoints, MCP, Interface ├── boot-librechat.sh # Login-Autostart-Skript (LLM zuerst) ├── .env # Secrets + Umgebungsvariablen (nach /app/.env eingebunden) ├── root_solutions_logo.svg # Dein Logo — ersetzt die eingebaute logo.svg ├── index.html # Gepatchtes LibreChat-Index (linkt custom.css) └── custom.css # Logo-Größe + Zentrierung Override
2. compose.yaml (Komplett)
Nur zwei Services: die LibreChat-API und MongoDB. Code-Interpreter wurde entfernt (das ghcr-Image liefert 403 — es wurde aus dem Registry entfernt [1]).
services: api: image: ghcr.io/danny-avila/librechat:latest container_name: librechat-app ports: - "3080:3080" depends_on: - mongodb extra_hosts: - "host.containers.internal:host-gateway" volumes: # Konfig + Branding (Read-only Bind-Mounts) - ./librechat.yaml:/app/librechat.yaml:ro - ./root_solutions_logo.svg:/app/client/dist/assets/logo.svg:ro - ./index.html:/app/client/dist/index.html:ro - ./custom.css:/app/client/dist/custom.css:ro # Dauerhafte Daten (Named Volumes — überleben Container-Neuanlage) - librechat-images:/app/client/public/images - librechat-uploads:/app/api/data/uploads - librechat-logs:/app/api/logs # Umgebungsdatei mit allen Secrets - ./.env:/app/.env:ro environment: - HOST=0.0.0.0 - PORT=3080 - MONGO_URI=mongodb://mongodb:27017/LibreChat - ALLOW_REGISTRATION=true restart: "no" mongodb: image: docker.io/library/mongo:latest container_name: librechat-db volumes: - librechat-db-data:/data/db restart: "no" volumes: librechat-db-data: name: librechat-db-data librechat-images: name: librechat-images librechat-uploads: name: librechat-uploads librechat-logs: name: librechat-logs
Wichtige Design-Entscheidungen:
- restart: “no” auf allen Services — du steuerst den Start über das Boot-Skript, kein Auto-Neustart bei Crash oder Reboot (passt zu deinem open-webui-Pattern)
- host.containers.internal:host-gateway — erlaubt dem Container, LM Studio und ComfyUI auf dem Host per Namen statt harter LAN-IP zu erreichen [2]
- Named Volumes für alle dauerhaften Daten — man kann Container bedenkenlos löschen/erneuern ohne Chat-Verlauf, Uploads oder Datenbank zu verlieren [3]
- docker.io/library/mongo:latest vollqualifiziert — verhindert den interaktiven “Image auswählen”-Prompt, der unbeaufsichtigte Skripte aufhängt
3. .env-Datei
Alle Secrets und Auth-Einstellungen stehen hier. Wird nach /app.env im Container eingebunden. So liest LibreChat in diesem Build seine Konfiguration (das @librechat/data-schemas-Paket erwartet sie dort, nicht nur in Process Env) [4].
# ~/librechat/.env HOST=0.0.0.0 PORT=3080 MONGO_URI=mongodb://mongodb:27017/LibreChat ALLOW_REGISTRATION=true JWT_SECRET=super_secret_token_string_generation_12345 REFRESH_TOKEN_SECRET=super_secret_refresh_token_string_54321 # DAS IST DIE EIGENTLICH WIRKSAME VARIABLE FÜR SIGN-IN IN DIESEM IMAGE-BUILD: JWT_REFRESH_SECRET=super_secret_refresh_token_string_54321
⚠️ Kritischer Hinweis zu JWT_REFRESH_SECRET: Das @librechat/data-schemas-Paket in diesem Image (Zeile 5989 von dist/index.mjs) ruft jwt.sign() mit process.env.JWT_REFRESH_SECRET auf, nicht mit REFRESH_TOKEN_SECRET. Ohne diese Zeile funktioniert die Registrierung, aber der Login liefert einen 500-Fehler “secretOrPrivateKey must have a value”. Beide Zeilen bleiben zur Klarheit erhalten; nur JWT_REFRESH_SECRET wird vom Signing-Code tatsächlich gelesen.
4. librechat.yaml (Komplett)
version: 1.1.2 interface: privacyPolicy: externalUrl: 'https://yourcompany.com' openNewTab: true termsOfService: externalUrl: 'https://yourcompany.com' openNewTab: true endpoints: custom: - name: "LM Studio" # host.containers.internal = der Host, vom Container aus gesehen baseURL: "http://host.containers.internal:1234/v1" apiKey: "lm-studio" models: fetch: true # lädt die Live-Modellliste aus LM Studio default: ["qwen/qwen3.8-27b"] # deine tatsächliche Modell-ID titleConvo: true summarize: false mcpServers: comfyui: type: stdio command: npx args: - "-y" - "comfyui-mcp" # echtes npm-Paket (Oktober 2026 verifiziert) - "--comfyui-url" - "http://host.containers.internal:8188"
Hinweise:
- baseURL ist der korrekte Feldname (nicht “url”) [5]
- fetch: true bedeutet: die Modell-Auswahl füllt sich automatisch aus dem, was in LM Studio geladen ist — kein hartkodieren jeder Modell-ID nötig [6]
- Das ursprünglich geplante “mcp-server-comfyui”-Paket existiert nicht auf npm; comfyui-mcp ist das echte, unterstützt Remote-ComfyUI via –comfyui-url [7]
- Der erste MCP-Aufruf braucht Internet im Container für den npx-Download — folgende Aufrufe sind gecacht
5. Logo-Größe (custom.css)
LibreChat rendert logo.svg in seiner eingebauten CSS auf eine feste kleine Größe, und es gibt keinen Config-Schalter dazu. Lösung: index.html so patchen, dass ein zusätzliches Stylesheet gelinkt wird, dann die img-Regel überschreiben [8].
5a. So wurde es eingerichtet
# 1) Die echte index.html aus dem Container holen (während er läuft) podman exec librechat-app cat /app/client/dist/index.html > ~/librechat/index.html # 2) Einen Link-Tag in <head> einfügen sed -i 's|</head>|<link rel="stylesheet" href="/custom.css"></head>|' ~/librechat/index.html # 3) Das Override erstellen cat > ~/librechat/custom.css <<'EOF' img[src*="logo.svg"] { height: 140px !important; width: auto !important; display: block !important; margin-left: auto !important; margin-right: auto !important; } EOF
5b. Größe nachstellen
~/librechat/custom.css auf der Platte editieren, den px-Wert ändern, Browser hart neu laden (Strg+Shift+R). Kein Container-Neuaufbau nötig — es ist ein Bind-Mount, liest live.
6. boot-librechat.sh (Autostart-Skript)
Läuft über Nobara Login Scripts (System-Einstellungen → Autostart → Login-Skripte). Reihenfolge wie dein bestehendes start-ai-new.sh: LLM zuerst, dann Container, dann Health-Check. Idempotent — sicher bei mehrfacher Auslösung beim Login.
#!/bin/bash # boot-librechat.sh — startet LibreChat-Stack nach dem Login (LM Studio zuerst) LOG=/var/log/librechat-boot.log exec >> "$LOG" 2>&1 echo "=== $(date) librechat-boot ===" PATH="$HOME/.local/bin:$PATH" MODEL="qwen/qwen3.8-27b" # --- 1. Läuft der LM-Studio-Server? ----------------------------------- if ! curl -s --connect-timeout 2 http://localhost:1234/v1/models > /dev/null; then echo "⏳ LM Studio nicht erreichbar — Server wird gestartet..." lms server start || echo "⚠️ lms server start fehlgeschlagen." for i in $(seq 1 15); do curl -s --connect-timeout 2 http://localhost:1234/v1/models > /dev/null && break sleep 2 done fi # --- 2. Ist ein Modell geladen? (no-op, falls schon im RAM) ---------- echo "⏳ Modell wird in LM Studio geladen..." lms load "$MODEL" || echo "⚠️ lms load fehlgeschlagen." sleep 5 # --- 3. LibreChat-Container starten ----------------------------------- if podman ps -a --filter "name=librechat-app" --format '{{.Names}}' | grep -q librechat-app; then echo "📦 LibreChat-Container werden gestartet..." podman start librechat-app librechat-db else echo "⚠️ Container nicht gefunden — erst via Compose anlegen..." cd ~/librechat && podman-compose --in-pod true up -d \ || { echo "❌ Compose fehlgeschlagen."; exit 1; } fi # --- 4. Health-Check --------------------------------------------------- for i in $(seq 1 10); do if curl -s --connect-timeout 2 http://localhost:3080/api/version > /dev/null \ || curl -s --connect-timeout 2 http://localhost:3080/ > /dev/null; then echo "✅ LibreChat-API ist erreichbar." break fi [ "$i" -eq 10 ] && { echo "❌ API tot — letzte 30 Log-Zeilen:"; podman logs --tail 30 librechat-app; exit 1; } sleep 5 done echo "=== $(date) fertig ==="
Autostart-Einrichtung (einmalig):
- Nobara System-Einstellungen → Autostart → + Neu hinzufügen → Login-Skript
- ~/librechat/boot-librechat.sh auswählen
- Ja sagen, wenn nach Ausführbarkeit gefragt wird
- Zum Deaktivieren: Eintrag löschen, oder rm ~/librechat/boot-librechat.sh
Log-Datei: /var/log/librechat-boot.log — mit tail -f /var/log/librechat-boot.log ansehen
7. Befehlsreferenz
| Aktion | Befehl |
|---|---|
| Stack starten (manuell) | cd ~/librechat && podman start librechat-app librechat-db |
| Stack stoppen | podman stop librechat-app librechat-db |
| Logs (App) ansehen | podman logs –tail 100 librechat-app |
| Logs (Mongo) ansehen | podman logs –tail 50 librechat-db |
| Boot-Log ansehen | tail -f /var/log/librechat-boot.log |
| Pod-Status prüfen | podman pod ps |
| LibreChat-Image aktualisieren (behalten alle Daten) | cd ~/librechat && podman-compose down && podman pull ghcr.io/danny-avila/librechat:latest && podman-compose –in-pod true up -d |
| Stack entfernen, Daten behalten | cd ~/librechat && podman-compose down |
| Komplett löschen inkl. Daten | oben + podman volume rm librechat-db-data librechat-images librechat-uploads librechat-logs |
| Nutzer in DB abfragen | podman exec librechat-db mongosh –quiet –eval 'db.getSiblingDB(“LibreChat”).users.findOne({}, {email:1, roles:1})' |
| Live-Modelle von LM Studio prüfen | curl -s http://localhost:1234/v1/models |
8. Fehlerbehebung
8a. Login liefert 500 "secretOrPrivateKey must have a value"
Ursache: Dieser LibreChat-Image-Build liest process.env.JWT_REFRESH_SECRET, nicht REFRESH_TOKEN_SECRET. Der Variablenname ist spezifisch für die in diesem Image enthaltene Version des @librechat/data-schemas-Pakets (bestätigt in dist/index.mjs:5989). Lösung: JWT_REFRESH_SECRET=<Wert> zu ~/librechat/.env hinzufügen, dann neu aufbauen.
8b. "Image auswählen"-Prompt hängt das Boot-Skript
Ursache: Ein nackter Image-Name (z. B. mongo:latest) löst Podmans interaktiven Registry-Auswahlmenü aus, wenn kein lokaler Treffer da ist. Ohne TTY beim Login blockt das ewig. Lösung: In compose.yaml immer vollqualifizierte Namen verwenden — docker.io/library/mongo:latest, ghcr.io/danny-avila/librechat:latest.
8c. Code-Interpreter-Image liefert 403 Forbidden
Ursache: ghcr.io/danny-avila/code-interpreter:latest wurde aus dem Registry entfernt (403 = Repo nicht mehr öffentlich/existent). Die aktuelle offizielle LibreChat-Compose-Datei enthält keinen code-interpreter-Service [9]. Lösung: Service komplett entfernen — für Chat + ComfyUI-MCP nicht nötig.
8d. Logo auf der Login-Seite zu klein
Ursache: LibreChars eingebaute CSS skaliert logo.svg auf eine feste kompakte Dimension. Es gibt keinen Config-Schalter dafür im interface-Objekt [10]. Lösung: Eine gepatchte index.html mounten, die custom.css verlinkt, und dann mit img[src*=“logo.svg”] { height: 140px !important; } überschreiben.
8e. podman-compose --pod Flag wird nicht erkannt
Ursache: Podman Desktop liefert kein podman-compose mit; das dnf-Paket ist v1.x (containers/podman-compose) [11], das einen anderen Flag-Namen als die pipx-Version verwendet. Lösung: podman-compose –in-pod true up -d statt –pod verwenden.
8f. "agent_id is required in request body" beim ersten Chat
Ursache: Die Unterhaltung wurde erstellt, bevor der LM-Studio-Endpoint im Modell-Picker ausgewählt war — die Anfrage lief an den Agents-Endpunkt. Lösung: Neue Unterhaltung starten und im Picker explizit LM Studio + Modell wählen, vor dem Senden.
9. Was funktioniert / Verifiziert
| Komponente | Status | Hinweis |
|---|---|---|
| Logo (groß + zentriert) | ✅ Im Browser verifiziert | custom.css-Mount, 140px |
| Auth (Registrierung + Login) | ✅ Funktioniert | JWT_REFRESH_SECRET-Fix angewendet |
| LM-Studio-Chat | ✅ “Hello!”-Antwort bestätigt | Qwen3 27B geladen |
| ComfyUI MCP-Server | ✅ “running on stdio” in Logs | comfyui-mcp-Paket |
| Admin-Zugang | ✅ Erster registrierter Nutzer ist Admin [1] | Rollen-Dropdown = Sichtfilter, keine Kontorolle |
| Autostart (LLM zuerst) | ✅ Nobara Login-Skript eingerichtet | /var/log/librechat-boot.log |
| Datenbeständigkeit | ✅ Named Volumes | Überleben Container-Neuanlage |
| Podman-Desktop-Gruppierung | ✅ pod_librechat, 2 Container | –in-pod true |
Noch nicht getestet: ComfyUI-Bildgenerierung End-to-End aus LibreChat heraus (den Chat bitten, ein Bild zu generieren).
