Langfuse selbst hosten: LLM-Observability und Audit-Logging für KI-Anwendungen
Langfuse ist die selbst gehostete Observability-Plattform für LLM-Anwendungen: vollständige Traces, Kosten- und Qualitätsmetriken sowie DSGVO-konformes Audit-Logging – als logische Ergänzung zu LiteLLM-Proxy und Ollama.

Wer KI-Anwendungen mit LLMs betreibt, weiß: Ohne Sichtbarkeit in das, was die Modelle tatsächlich tun, ist weder sinnvolles Debugging noch Compliance-Nachweis möglich. Genau hier setzt Langfuse an – eine MIT-lizenzierte Observability-Plattform, die als selbst gehostete Lösung vollständige Traces, Token-Kosten, Latenz-Metriken und Audit-Logs für jeden einzelnen LLM-Aufruf aufzeichnet. Entwickelt von einer Berliner GmbH, lässt sie sich nahtlos in bestehende Setups mit LiteLLM-Proxy oder Ollama einbinden und hält alle Daten in der eigenen Infrastruktur – ohne Cloud-Abhängigkeit.
Voraussetzungen
- Server/VM: Linux (Debian/Ubuntu empfohlen), mindestens 4 CPU-Kerne, 16 GB RAM, 100 GB SSD-Speicher
- Docker Engine ab Version 24.x mit Docker Compose Plugin installiert (nicht das veraltete
docker-compose-Binary) - Git für den Repository-Klon
- OpenSSL zur Secret-Generierung (auf allen gängigen Linux-Distributionen vorinstalliert)
- Offene Firewallports: 3000 (Web-UI) und optional 9090 (MinIO); alle anderen Dienste bleiben intern
- Domain oder statische IP für
NEXTAUTH_URL(bei Produktivbetrieb zwingend, bei lokalem Test reichtlocalhost) - Optional: eine bestehende LiteLLM-Konfiguration (
litellm_config.yaml) für die Gateway-Integration
Schritt 1: Architektur verstehen
Bevor du mit der Installation beginnst, lohnt ein Blick auf die Interna. Langfuse ist kein monolithischer Dienst, sondern ein koordinierter Stack aus sechs Komponenten mit klar getrennten Zuständigkeiten:
| Dienst | Port(s) | Rolle | Volume |
|---|---|---|---|
| langfuse-web | 3000 | Web-UI + REST-API-Endpunkt | — |
| langfuse-worker | 3030 | Async-Verarbeitung, LLM-Evaluierungen | — |
| PostgreSQL | 5432 | Transaktionsdaten – Nutzer, Projekte, Konfiguration (OLTP) | postgres-data |
| ClickHouse | 8123 / 9000 | Observability-Daten – Traces, Metriken (OLAP) | clickhouse-data |
| Redis / Valkey | 6379 | Caching und Job-Queue | redis-data |
| MinIO | 9090 | S3-kompatibler Blob-Storage für Traces und Medien | minio-data |
Die Trennung zwischen PostgreSQL (OLTP) und ClickHouse (OLAP) ist bewusst: PostgreSQL verwaltet strukturierte Stammdaten mit hohen Schreibkonsistenzanforderungen, während ClickHouse für die analytischen Abfragen über Millionen von Trace-Einträgen optimiert ist. Nach außen müssen nur zwei Ports erreichbar sein – Port 3000 für die Web-Oberfläche und Port 9090 für MinIO. PostgreSQL, ClickHouse und Redis sind an 127.0.0.1 gebunden und dürfen nicht extern erreichbar sein.
Schritt 2: Repository klonen und Secrets generieren
Langfuse wird direkt aus dem offiziellen GitHub-Repository bezogen. Das Repository enthält eine fertige docker-compose.yml mit allen sechs Diensten:
# Repository klonen
git clone https://github.com/langfuse/langfuse.git
cd langfuse
# Secrets generieren – NEXTAUTH_SECRET und SALT (Base64)
openssl rand -base64 32
# ENCRYPTION_KEY – zwingend 256 Bit = exakt 64 Hex-Zeichen
openssl rand -hex 32Wichtig: Führe den openssl rand -hex 32-Befehl für den ENCRYPTION_KEY zweimal aus, damit du separate Werte für NEXTAUTH_SECRET (Base64) und ENCRYPTION_KEY (Hex) erhältst. Ein häufiger Fehler ist, openssl rand -base64 32 auch für den ENCRYPTION_KEY zu verwenden – das erzeugt Base64, nicht Hex, und führt zu einem Startfehler.
Schritt 3: Umgebungsvariablen konfigurieren
Alle Konfiguration erfolgt über Umgebungsvariablen in der docker-compose.yml. Die folgende Tabelle zeigt alle Pflichtfelder:
| Variable | Beispielwert | Hinweis |
|---|---|---|
| DATABASE_URL | postgresql://langfuse:PW@postgres:5432/langfuse | PostgreSQL-Verbindung |
| NEXTAUTH_URL | http://localhost:3000 | Bei VM-Betrieb: echte IP/Domain! |
| NEXTAUTH_SECRET | (openssl rand -base64 32) | Session-Validierung |
| SALT | (openssl rand -base64 32) | API-Key-Hashing |
| ENCRYPTION_KEY | (openssl rand -hex 32) | 256 Bit, exakt 64 Hex-Zeichen |
| CLICKHOUSE_MIGRATION_URL | clickhouse://clickhouse:9000 | TCP-Protokoll für Migrationen |
| CLICKHOUSE_URL | http://clickhouse:8123 | HTTP-Protokoll für Abfragen |
| CLICKHOUSE_CLUSTER_ENABLED | false | Pflicht für Single-Node! |
| REDIS_CONNECTION_STRING | redis://redis:6379 | — |
| LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE | true | Pflicht für MinIO-Kompatibilität |
Die vollständige Konfiguration der relevanten Umgebungsvariablen für langfuse-web und langfuse-worker:
# Auszug aus docker-compose.yml – Env-Vars für langfuse-web und langfuse-worker
# Alle CHANGEME-Platzhalter durch generierte Secrets ersetzen!
environment:
DATABASE_URL: postgresql://langfuse:CHANGEME@postgres:5432/langfuse
NEXTAUTH_URL: http://localhost:3000 # Bei VM: http://<server-ip>:3000
NEXTAUTH_SECRET: CHANGEME # openssl rand -base64 32
SALT: CHANGEME # openssl rand -base64 32
ENCRYPTION_KEY: CHANGEME # openssl rand -hex 32 (64 Hex-Zeichen!)
CLICKHOUSE_MIGRATION_URL: clickhouse://clickhouse:9000
CLICKHOUSE_URL: http://clickhouse:8123
CLICKHOUSE_USER: clickhouse
CLICKHOUSE_PASSWORD: CHANGEME
CLICKHOUSE_CLUSTER_ENABLED: "false" # PFLICHT für Single-Container!
REDIS_CONNECTION_STRING: redis://redis:6379
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: langfuse
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: http://minio:9000
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: minio
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: CHANGEME
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
# UTC-Zeitzone für alle Datenbankcontainer erzwingen
TZ: UTCKritischer Hinweis zur Zeitzone: PostgreSQL und ClickHouse müssen zwingend in UTC betrieben werden. Wird stattdessen Europe/Berlin gesetzt, liefern ClickHouse-Abfragen leere oder falsche Ergebnisse – ohne jede Fehlermeldung im Log. Setze TZ=UTC explizit als Umgebungsvariable in allen Containern, auch wenn der Docker-Host eine andere Zeitzone verwendet.
Schritt 4: Stack starten
# Stack im Hintergrund starten
docker compose up -d
# Logs des Web-Containers verfolgen
docker compose logs -f langfuse-webDer Stack benötigt 2–3 Minuten bis zur vollständigen Betriebsbereitschaft. Datenbankmigrationen für PostgreSQL und ClickHouse laufen beim ersten Start automatisch ab.
Verifizieren: Sobald langfuse-web im Log die Meldung Ready ausgibt, ist der Dienst erreichbar. Öffne http://localhost:3000 (oder http://<server-ip>:3000) im Browser – die Langfuse-Registrierungsseite sollte erscheinen. Mit docker compose ps kannst du den Status aller sechs Container prüfen: alle sollten den Status running oder Up zeigen.
Schritt 5: Erstes Projekt einrichten (manuell oder automatisiert)
Nach dem ersten Login legst du eine Organisation und ein Projekt an. Langfuse generiert dann ein Public Key-/Secret Key-Paar (Format: pk-lf-... / sk-lf-...), das alle Integrationen benötigen.
Für Infrastructure-as-Code-Setups (CI/CD, automatisches Deployment) lässt sich die Ersteinrichtung auch vollständig über LANGFUSE_INIT_*-Umgebungsvariablen automatisieren:
# Headless-Initialisierung per Umgebungsvariablen
# WICHTIG: Werte NICHT in doppelte Anführungszeichen einschließen!
environment:
LANGFUSE_INIT_ORG_ID: meine-org
LANGFUSE_INIT_ORG_NAME: Meine Organisation
LANGFUSE_INIT_PROJECT_ID: mein-ki-projekt
LANGFUSE_INIT_PROJECT_NAME: Mein KI-Projekt
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: pk-lf-...
LANGFUSE_INIT_PROJECT_SECRET_KEY: sk-lf-...
LANGFUSE_INIT_USER_EMAIL: admin@example.com
LANGFUSE_INIT_USER_PASSWORD: CHANGEMESchritt 6: LiteLLM-Proxy integrieren
Wer bereits einen LiteLLM-Proxy als LLM-Gateway betreibt, verbindet diesen mit einem einzigen Callback-Eintrag in der litellm_config.yaml. Traces werden dabei asynchron im Hintergrund gesendet – die Latenz der KI-Anwendung bleibt unberührt:
# litellm_config.yaml – Ergänzung für Langfuse-Integration
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: sk-xxx
- model_name: ollama/llama3.2
litellm_params:
model: ollama/llama3.2
api_base: http://ollama:11434
general_settings:
callbacks: ["langfuse_otel"]Zusätzlich benötigt der LiteLLM-Container drei Umgebungsvariablen:
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_OTEL_HOST=http://langfuse-web:3000 # interne Docker-Netzwerk-URLVerifizieren: Sende nach der Konfiguration eine Testanfrage über den LiteLLM-Proxy. In der Langfuse-Web-UI unter „Traces" sollte innerhalb weniger Sekunden ein neuer Eintrag erscheinen, der Prompt, Antwort, Token-Verbrauch und Latenz enthält.
Schritt 7: Python SDK für direkte Integration
Für Anwendungen, die das Python SDK nutzen, lassen sich Traces auch manuell senden – etwa in eigenen Agenten-Pipelines oder bei der Nutzung von Frameworks wie LangChain oder LlamaIndex:
pip install langfuse
from langfuse import Langfuse
lf = Langfuse(
public_key="pk-lf-...",
secret_key="sk-lf-...",
host="http://localhost:3000"
)
# Trace mit einer Generation anlegen
trace = lf.trace(name="mein-llm-aufruf", user_id="user-123")
generation = trace.generation(
name="openai-call",
model="gpt-4o-mini",
input={"messages": [{"role": "user", "content": "Hallo"}]},
output="Hallo! Wie kann ich helfen?",
usage={"prompt_tokens": 10, "completion_tokens": 20}
)
lf.flush() # Sicherstellen, dass alle Traces gesendet wurdenDie Telemetrie-Hierarchie in Langfuse folgt dem Schema Trace → Session → Observation (Span / Generation / Event). Eine Generation repräsentiert einen einzelnen LLM-Aufruf, ein Span einen logischen Verarbeitungsschritt (z. B. Retrieval), ein Event einen diskrete Aktion ohne Zeitdauer.
Troubleshooting / Typische Fehler
ClickHouse liefert leere Ergebnisse – kein Fehler im Log
Ursache: PostgreSQL oder ClickHouse läuft nicht in UTC. Prüfe mit docker compose exec clickhouse clickhouse-client --query "SELECT timezone()" – das Ergebnis muss UTC sein. Lösung: TZ=UTC als Umgebungsvariable in allen Containern setzen und den Stack neu starten.
Start schlägt fehl mit „ENCRYPTION_KEY must be 64 hex characters"
Ursache: Der Key wurde mit openssl rand -base64 32 statt openssl rand -hex 32 generiert. Base64 erzeugt eine andere Zeichenanzahl. Lösung: Neuen Key mit dem korrekten Befehl generieren und in der Konfiguration ersetzen.
ClickHouse-Befehle schlagen alle fehl
Ursache: CLICKHOUSE_CLUSTER_ENABLED ist nicht auf false gesetzt. Der Standardwert ist true (Cluster-Modus), der für Single-Container-Setups nicht funktioniert. Lösung: Variable explizit auf false setzen.
OAuth-Authentifizierung schlägt fehl bei VM-Betrieb
Ursache: NEXTAUTH_URL zeigt auf localhost statt auf die tatsächliche IP oder Domain. Lösung: NEXTAUTH_URL=http://<server-ip>:3000 oder https://langfuse.example.com setzen.
MinIO-Bucket-Zugriff schlägt fehl mit „invalid endpoint"
Ursache: LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE ist nicht gesetzt. MinIO erfordert Path-Style-Zugriff. Lösung: Variable auf true setzen.
API-Aufrufe schlagen nach dem Start fehl
Ursache: Der Stack ist noch nicht vollständig hochgefahren. Die Initialisierung dauert 2–3 Minuten. Erst wenn docker compose logs langfuse-web das Wort Ready enthält, ist der Dienst betriebsbereit.
LANGFUSE_INIT_* führt zu Parse-Fehlern
Ursache: Werte wurden in doppelte Anführungszeichen eingeschlossen (z. B. LANGFUSE_INIT_ORG_NAME: "Meine Org"). Docker Compose interpretiert diese anders als erwartet. Lösung: Anführungszeichen bei LANGFUSE_INIT_*-Variablen weglassen.
Häufige Fragen
Kann ich Langfuse komplett ohne Internetverbindung betreiben?
Ja. Nach dem einmaligen docker compose pull benötigt der Stack keine ausgehende Internetverbindung mehr. Langfuse unterstützt vollständig air-gapped-Betrieb – alle Komponenten kommunizieren nur intern über das Docker-Netzwerk.
Wie verbinde ich meinen bestehenden LiteLLM-Proxy?
In litellm_config.yaml unter general_settings den Eintrag callbacks: ["langfuse_otel"] hinzufügen und die drei Umgebungsvariablen LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY und LANGFUSE_OTEL_HOST im LiteLLM-Container setzen. Kein Neustart der LLM-Backends notwendig.
Welche Datenbank speichert was?
PostgreSQL übernimmt alle Transaktionsdaten: Nutzer, Projekte, API-Keys, Konfiguration. ClickHouse speichert sämtliche Observability-Daten: Traces, Generierungen, Metriken und Evaluierungsergebnisse. Die Trennung ermöglicht blitzschnelle analytische Abfragen über Millionen von Einträgen, ohne die OLTP-Performance zu beeinträchtigen.
Wie funktioniert DSGVO-konforme Verarbeitung personenbezogener Daten in Traces?
Langfuse bietet drei eingebaute Mechanismen: Data Masking (Verschleierung sensibler Felder vor der Speicherung), Data Retention (automatisches Löschen nach konfigurierbaren Zeiträumen) und Data Deletion (manuelle Löschanfragen). Diese Features decken die Anforderungen aus Art. 5 DSGVO ab. Ein Data Processing Agreement (DPA) ist für Langfuse Cloud verfügbar – bei Self-Hosted bist du selbst Verantwortlicher.
Wann sollte ich von Docker Compose auf Kubernetes wechseln?
Docker Compose eignet sich ausdrücklich nur für Test- und Low-Scale-Betrieb: Es gibt keine Hochverfügbarkeit, kein automatisches Scaling und kein eingebautes Backup-Management. Sobald Langfuse geschäftskritisch wird oder mehr als eine Handvoll Nutzer bedient, empfiehlt Langfuse den Wechsel auf Kubernetes via Helm-Chart oder Terraform-Templates für AWS, Azure oder GCP.
Wie aktualisiere ich auf eine neue Version?
Im geklonten Repository ein git pull ausführen, dann docker compose pull && docker compose up -d. Datenbankmigrationen für PostgreSQL und ClickHouse laufen beim Start automatisch ab – außer die Automigration wurde mit LANGFUSE_AUTO_POSTGRES_MIGRATION_DISABLED=true oder LANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLED=true deaktiviert.
Fazit
Langfuse schließt eine Lücke, die in vielen selbst gehosteten KI-Stacks klafft: die Frage, was die Modelle tatsächlich tun, was sie kosten und ob die Antwortqualität den Anforderungen genügt. Als MIT-lizenzierte, in Berlin entwickelte Plattform ist sie eine natürliche Ergänzung zu Ollama und LiteLLM – und liefert gleichzeitig das Fundament für DSGVO-konformes Audit-Logging und EU-AI-Act-Compliance-Dokumentation. Der Aufwand für die Erstinstallation ist überschaubar; die Fallstricke rund um UTC-Zeitzone, ENCRYPTION_KEY-Format und ClickHouse-Cluster-Modus sind bekannt und lassen sich mit den Hinweisen aus dieser Anleitung zuverlässig vermeiden. Für produktive Deployments mit Hochverfügbarkeitsanforderungen ist der Weg zu Kubernetes der nächste logische Schritt.
Weiterführende Anleitungen und Quellen
- LiteLLM mit Docker installieren: zentrales LLM-Gateway für alle Modelle
- Ollama und Open WebUI mit Docker: eigenes lokales KI-Sprachmodell ohne Cloud
- Lokale KI datenschutzkonform betreiben: DSGVO-Checkliste für On-Premise-LLM-Deployments
- RAG produktiv betreiben: Chunking, Hybrid-Search, Reranking und Antwortqualität messen
- Langfuse Self-Hosting Dokumentation (offiziell)
- Langfuse Docker Compose Deployment (offiziell)
- Langfuse Environment Variables Configuration (offiziell)
- Langfuse DSGVO / GDPR (offiziell)