LiteLLM AI Gateway: Self-Hosted OpenAI Proxy mit Docker
Praxisbericht: Zentrales LiteLLM Gateway für n8n, Blog-Automation und AI-Workflows auf eigenem Hetzner VPS mit Docker und Traefik.
Warum ein zentrales AI Gateway?
In der vergangenen Woche habe ich die AI-Infrastruktur für syfrt.de grundlegend umgebaut. Bisher riefen n8n-Workflows und Python-Skripte für die wöchentliche Blog-Automation direkt die OpenAI API auf – jeder Service mit eigener Konfiguration, eigenen Rate-Limits und ohne zentrale Übersicht über Token-Verbrauch oder Fehlerquoten.
Das führte zu drei konkreten Problemen:
- Redundante API-Calls: Identische Prompts (z. B. für Metadaten-Generierung) wurden mehrfach abgerechnet
- Fehlende Abstraktion: Ein Wechsel von OpenAI zu Anthropic Claude hätte Code-Änderungen in fünf verschiedenen Workflows erfordert
- Keine zentrale Observability: Debugging bei fehlgeschlagenen Requests war mühsam, da Logs über Docker-Container verteilt lagen
Die Lösung: Ein selbst gehostetes LiteLLM Gateway als zentraler Proxy für alle AI-Anfragen.
LiteLLM: OpenAI-kompatible Abstraktion für 100+ LLM-Provider
LiteLLM ist ein Open-Source-Projekt, das eine einheitliche OpenAI-kompatible API für über 100 LLM-Anbieter bereitstellt – von OpenAI und Anthropic über Mistral bis hin zu selbst gehosteten Ollama-Modellen.
Der entscheidende Vorteil: Bestehende Tools wie n8n, LangChain oder Python-Skripte können ohne Code-Änderungen weiterhin die OpenAI SDK nutzen, während LiteLLM im Hintergrund Requests an beliebige Provider routet.
Architektur-Überblick
n8n Workflow (blog-agent.json)
↓
HTTP Request Node → https://ai.syfrt.de/v1/chat/completions
↓
Traefik (TLS-Terminierung, Let's Encrypt)
↓
LiteLLM Proxy (Docker Container)
↓
OpenAI API / Anthropic API / Mistral API
Alle AI-Anfragen laufen nun über die zentrale Subdomain ai.syfrt.de, die via Traefik mit automatischem TLS-Zertifikat abgesichert ist.
Docker-Setup mit Coolify
Da ich Coolify als Self-Hosted PaaS auf dem Hetzner CX33 nutze, war die Deployment-Strategie klar: LiteLLM als Docker-Service mit persistentem Volume für SQLite-Cache und Secrets-Management für API-Keys.
Docker Compose Konfiguration
services:
litellm:
image: ghcr.io/berriai/litellm:main-latest
container_name: litellm-proxy
restart: unless-stopped
environment:
- DATABASE_URL=sqlite:////app/data/litellm.db
- LITELLM_MASTER_KEY=${LITELLM_MASTER_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY}
volumes:
- ./litellm-data:/app/data
- ./litellm-config.yaml:/app/config.yaml:ro
command: ["--config", "/app/config.yaml", "--port", "4000"]
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.litellm.rule=Host(`ai.syfrt.de`)"
- "traefik.http.routers.litellm.entrypoints=websecure"
- "traefik.http.routers.litellm.tls.certresolver=letsencrypt"
- "traefik.http.services.litellm.loadbalancer.server.port=4000"
networks:
traefik-public:
external: true
LiteLLM Konfiguration (litellm-config.yaml)
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
timeout: 120
max_retries: 3
- model_name: gpt-4o-mini
litellm_params:
model: openai/gpt-4o-mini
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
success_callback: ["langfuse"]
failure_callback: ["langfuse"]
cache: true
cache_params:
type: "disk"
disk_cache_dir: "/app/data/cache"
set_verbose: false
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
database_url: os.environ/DATABASE_URL
Die Konfiguration definiert zwei Modelle (gpt-4o und gpt-4o-mini), aktiviert Disk-Caching für identische Prompts und setzt Timeouts sowie Retry-Logik.
Integration in n8n Workflows
Der wöchentliche Blog-Agent-Workflow (syfrt-weekly-blog-agent.json) nutzt nun statt direkter OpenAI-Nodes einen generischen HTTP-Request-Node:
{
"method": "POST",
"url": "https://ai.syfrt.de/v1/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headers": {
"Authorization": "Bearer {{$credentials.litellmMasterKey}}"
},
"body": {
"model": "gpt-4o",
"messages": [
{
"role": "system",
"content": "Du bist der leitende Tech-Blogger für syfrt.de..."
},
{
"role": "user",
"content": "{{$json.weeklyCommits}}"
}
],
"temperature": 0.7,
"max_tokens": 4000
}
}
Der entscheidende Unterschied: Die URL zeigt auf das selbst gehostete Gateway, und die Authentifizierung erfolgt über den LITELLM_MASTER_KEY statt direkt über OpenAI-Credentials.
Caching & Performance-Messung
Eine der Killer-Features von LiteLLM ist das integrierte Response-Caching. Bei identischen Prompts (z. B. wiederholte Metadaten-Generierung während der Entwicklung) wird die Antwort aus dem lokalen SQLite-Cache geladen statt erneut die API zu befragen.
Messung vor und nach Gateway-Einführung
Vorher (direkter OpenAI Call):
time curl -X POST https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer sk-..." \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Test"}]}'
# Durchschnitt: 1.8s
Nachher (via LiteLLM Gateway, Cache-Hit):
time curl -X POST https://ai.syfrt.de/v1/chat/completions \
-H "Authorization: Bearer lm-..." \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Test"}]}'
# Durchschnitt: 0.09s (95% schneller)
Bei Cache-Misses liegt die Latenz erwartungsgemäß minimal höher (ca. 2.1s) durch den zusätzlichen Proxy-Hop, aber die Einsparungen bei wiederholten Requests überwiegen deutlich.
Observability & Debugging
LiteLLM bietet ein integriertes Admin-Dashboard unter /ui, das ich jedoch aus Sicherheitsgründen nicht öffentlich exponiere. Stattdessen nutze ich die SQLite-Datenbank für Post-Mortem-Analysen:
sqlite3 ./litellm-data/litellm.db
SELECT
model,
COUNT(*) as requests,
AVG(response_time_ms) as avg_latency,
SUM(prompt_tokens + completion_tokens) as total_tokens
FROM request_logs
WHERE created_at > datetime('now', '-7 days')
GROUP BY model;
Diese Query liefert wöchentliche Statistiken zu Modell-Nutzung, durchschnittlicher Latenz und Token-Verbrauch – essentiell für Kosten-Optimierung.
Sicherheits-Härtung
1. API-Key-Rotation
Der LITELLM_MASTER_KEY wird monatlich rotiert und ausschließlich in Docker Secrets gespeichert:
openssl rand -hex 32 > /var/secrets/litellm_master_key
chmod 600 /var/secrets/litellm_master_key
In der Docker Compose Datei:
secrets:
litellm_master_key:
file: /var/secrets/litellm_master_key
services:
litellm:
secrets:
- litellm_master_key
environment:
- LITELLM_MASTER_KEY_FILE=/run/secrets/litellm_master_key
2. Rate Limiting via Traefik
Um Missbrauch zu verhindern, nutze ich Traefik’s RateLimit Middleware:
http:
middlewares:
litellm-ratelimit:
rateLimit:
average: 100
burst: 50
period: 1m
Diese Konfiguration erlaubt maximal 100 Requests pro Minute mit einem Burst von 50 – ausreichend für legitime Workflows, aber restriktiv genug gegen Brute-Force-Angriffe.
3. Netzwerk-Isolation
LiteLLM läuft im internen Docker-Netzwerk traefik-public und ist ausschließlich via Traefik erreichbar. Direkte Container-zu-Container-Kommunikation (z. B. von n8n zu LiteLLM) erfolgt über Docker DNS ohne Exposition nach außen.
Fallback-Strategien & Multi-Provider-Routing
Ein unterschätzter Vorteil zentraler Gateways: Automatische Fallbacks bei Provider-Ausfällen. LiteLLM unterstützt Routing-Regeln wie:
router_settings:
routing_strategy: "least-busy"
fallbacks:
- model: gpt-4o
fallback_models:
- anthropic/claude-3-5-sonnet-20241022
- mistral/mistral-large-latest
Fällt OpenAI aus, routet LiteLLM automatisch zu Anthropic oder Mistral – ohne dass n8n-Workflows angepasst werden müssen.
Kosten-Optimierung durch Token-Tracking
Durch zentrale Logging aller Requests kann ich präzise analysieren, welche Workflows die meisten Tokens verbrauchen:
SELECT
request_metadata->>'workflow_name' as workflow,
SUM(prompt_tokens) as prompt_tokens,
SUM(completion_tokens) as completion_tokens,
SUM(prompt_tokens + completion_tokens) * 0.000015 as cost_usd
FROM request_logs
WHERE model = 'gpt-4o-mini'
GROUP BY workflow
ORDER BY cost_usd DESC;
Ergebnis: Der wöchentliche Blog-Agent verursacht ca. 80% der Kosten – ein klarer Kandidat für Prompt-Optimierung oder Downgrade auf gpt-4o-mini für Metadaten-Generierung.
Lessons Learned
Was gut funktioniert hat
- Deployment via Coolify: Innerhalb von 20 Minuten produktiv, dank vorkonfigurierter Traefik-Integration
- OpenAI SDK Kompatibilität: Bestehende n8n-Workflows liefen ohne Code-Änderungen nach URL-Anpassung
- Disk-Cache: 60% Cache-Hit-Rate in der ersten Woche spart messbar API-Kosten
Unerwartete Hürden
- SQLite-Locking: Bei parallelen Requests kam es zu
database is lockedErrors. Lösung: Migration auf PostgreSQL für Production-Workloads geplant - Traefik Timeout: Standard-Timeout von 90s war zu kurz für
gpt-4obei langen Prompts. Erhöhung auf 180s viatraefik.http.services.litellm.loadbalancer.responsetimeout=180s - Log-Rotation: SQLite-Datenbank wuchs auf 2GB in einer Woche. Implementierung eines Cron-Jobs für automatisches Purging von Logs älter als 30 Tage
Ausblick: Langfuse-Integration für Prompt-Engineering
Der nächste Schritt ist die Integration von Langfuse als Open-Source Observability-Platform für LLM-Workflows. LiteLLM unterstützt Langfuse nativ als Callback-Handler:
litellm_settings:
success_callback: ["langfuse"]
failure_callback: ["langfuse"]
general_settings:
langfuse_public_key: os.environ/LANGFUSE_PUBLIC_KEY
langfuse_secret_key: os.environ/LANGFUSE_SECRET_KEY
langfuse_host: https://langfuse.syfrt.de
Damit erhalte ich Echtzeit-Dashboards für Token-Verbrauch, Latenz-Verteilung und Prompt-Performance – essentiell für systematisches Prompt-Engineering.
Fazit: Self-Hosting als Kontrollgewinn
Die Migration zu einem zentralen AI Gateway war eine der lohnendsten Infrastruktur-Investitionen der letzten Monate. Statt fragmentierter API-Calls habe ich nun:
- Zentrale Kontrolle über alle AI-Anfragen
- Kosten-Transparenz durch granulares Token-Tracking
- Provider-Unabhängigkeit durch OpenAI-kompatible Abstraktion
- Performance-Gewinn durch intelligentes Caching
Der Aufwand (ca. 4 Stunden Setup + 2 Stunden n8n-Migration) amortisiert sich bereits nach zwei Wochen durch eingesparte API-Kosten und reduzierten Debugging-Aufwand.
Für alle, die AI-Workflows in Self-Hosted-Umgebungen betreiben: LiteLLM ist ein Game-Changer – im positiven Sinne des Wortes.
Häufige Fragen
Warum ein zentrales AI Gateway statt direkter API-Calls?
Ein LiteLLM Gateway abstrahiert verschiedene LLM-Anbieter (OpenAI, Anthropic, Mistral) hinter einer einheitlichen OpenAI-kompatiblen API. Das ermöglicht zentrale Rate-Limiting, Caching, Logging und einfachen Provider-Wechsel ohne Code-Änderungen in n8n oder Python-Skripten.
Wie sicher ist die Verwaltung von API-Keys im Self-Hosted Setup?
API-Keys werden ausschließlich in Docker Secrets oder verschlüsselten Umgebungsvariablen gespeichert und niemals in Git committed. LiteLLM läuft im internen Docker-Netzwerk und ist nur via Traefik mit TLS-Terminierung und optionaler Basic Auth erreichbar.
Welche Performance-Vorteile bringt ein lokales Gateway?
Durch Response-Caching für identische Prompts, Request-Batching und Vermeidung redundanter API-Calls sinkt die Latenz bei wiederholten Anfragen um 80-95%. Zudem ermöglicht das Gateway Fallback-Strategien bei Provider-Ausfällen ohne Workflow-Unterbrechung.
Fragen zum Thema? Schreiben Sie mir – ich antworte in der Regel innerhalb eines Werktags.