Ollama hinter einem Reverse-Proxy mit Caddy oder Nginx für HTTPS-Streaming

HTTPS mit Ollama, ohne die Streaming-Antworten zu beeinträchtigen.

Inhaltsverzeichnis

Das Betreiben von Ollama hinter einem Reverse-Proxy ist der einfachste Weg, HTTPS, optionale Zugriffskontrolle und ein vorhersagbares Streaming-Verhalten zu erhalten.

Dieser Beitrag konzentriert sich auf den Caddy- und Nginx-Eingang für die Ollama-API, nicht auf Client-Code.

ollama behind proxy

Wenn Sie bereits Python- oder Go-Clients haben, die mit Ollama kommunizieren, ist dieser Beitrag das fehlende Puzzleteil: Der Eingang und der Transport für dieselbe API.

Für Details dazu, wie Ollama neben vLLM, Docker Model Runner, LocalAI und den Kompromissen bei der Cloud-Hosting-Infrastruktur passt, siehe LLM-Hosting in 2026: Lokal, Self-Hosted und Cloud-Infrastruktur im Vergleich.

Für Anfragebeispiele und Client-Code siehe Ollama CLI Cheatsheet.

Für UI- und Multi-User-Schichten siehe Open WebUI Überblick, Quickstart und Alternativen.

Für das große Ganze zur Self-Hosting- und Datenkontrolle siehe LLM-Self-Hosting und AI-Souveränität.

Für einen reproduzierbaren Single-Node-Ollama-Dienst in Docker Compose (persistenten Volumes, OLLAMA_HOST, NVIDIA-GPUs, Upgrades) siehe Ollama in Docker Compose mit GPU und persistentem Modell-Speicher.

Für Remote-Geräte ohne öffentliche eingehende Ports (Tailscale, WireGuard, Binding, Firewall) siehe Remote-Ollama-Zugriff über Tailscale oder WireGuard, keine öffentlichen Ports.

Warum Sie Ollama proxieren sollten, anstatt Port 11434 freizugeben

Ollama ist so konzipiert, dass es primär lokal läuft. Standardmäßig bindet es sich an localhost auf Port 11434, was großartig für einen Entwickler-Arbeitsplatz ist und ein nicht ganz so subtiler Hinweis darauf ist, dass der rohe Port nicht für das Internet gedacht ist.

Ich betrachte Port 11434 als eine interne, teure API. Wenn sie aus dem öffentlichen Internet erreichbar ist, kann jeder, der sie findet, Ihre CPU- oder GPU-Zeit verbrauchen, Ihre Festplatte durch das Herunterladen von Modellen füllen oder einfach Verbindungen offen halten, bis ein Timeout eintritt. Ein Reverse-Proxy macht Ollama nicht durch Magie sicherer, aber er gibt Ihnen einen Ort, an dem Sie die wichtigsten Kontrollen an der Kante platzieren können: TLS, Authentifizierung, Timeouts, Rate-Limits und Logs.

Dies ist wichtig, weil die lokale Ollama-API nicht mit einer integrierten Authentifizierungsschicht ausgeliefert wird. Wenn Sie sie freigegeben, fügen Sie die Authentifizierung typischerweise an der Kante hinzu oder halten Sie sie privat und nur über ein vertrauenswürdiges Netzwerk erreichbar.

Der zweite Grund ist die UX (Benutzererfahrung). Ollama streamt Antworten standardmäßig. Wenn der Proxy an der falschen Stelle puffert oder komprimiert, wirkt das Streaming defekt und UIs sehen so aus, als ob sie „nachdenken" würden, ohne Ausgabe zu liefern.

Minimale Architektur und Bindungsstrategie

Eine saubere Minimum-Architektur sieht so aus:

Client (curl, Python, Go, UI)
        |
        | HTTPS (optionale Basic Auth oder SSO)
        v
Reverse-Proxy (Caddy oder Nginx)
        |
        | HTTP (privates LAN, localhost oder Docker-Netzwerk)
        v
Ollama-Server (ollama serve auf 127.0.0.1:11434)

Zwei praktische Regeln halten dies auf die beste Art und Weise langweilig.

Erstens: Halten Sie Ollama privat und verlagern Sie die Exposition auf den Proxy. Wenn Caddy oder Nginx auf demselben Host laufen, proxieren Sie zu 127.0.0.1:11434 und ändern Sie die Bindungsadresse von Ollama nicht. Wenn der Proxy woanders läuft (separater Host, separate VM oder ein Container-Netzwerk), binden Sie Ollama an eine private Schnittstelle, nicht an 0.0.0.0 auf der öffentlichen NIC, und verlassen Sie sich auf eine Firewall.

Zweitens: Entscheiden Sie früh, ob Browser Ollama direkt aufrufen werden. Wenn ein browserbasiertes Tool Ollama von einer anderen Herkunft aus trifft, müssen Sie möglicherweise CORS (Cross-Origin Resource Sharing) behandeln. Wenn alles über den Proxy von einer Domain aus bereitgestellt wird (empfohlen für die Vernunft), können Sie CORS oft ganz vermeiden und Ollama streng halten.

Reverse-Proxy-Konfigurationen für Streaming und WebSockets

Ollama-API ist reguläres HTTP, und sein Streaming ist zeilenbasiertes JSON (NDJSON). Das bedeutet, dass Sie einen Proxy benötigen, der drei Dinge gut kann:

  • Keine Streaming-Antworten puffern.
  • Lange laufende Anfragen nicht nur deshalb abbrechen, weil das Modell eine Weile zum Sprechen benötigt hat.
  • Wenn eine UI WebSockets verwendet (manche tun das), das Upgrade sauber weiterleiten.

Sie können dies einfach halten. In vielen Fällen ist “korrekte WebSocket-Behandlung” einfach eine Konfiguration, die Upgrade-sicher ist, auch wenn das Upstream-System heute keine WebSockets verwendet.

Caddy Caddyfile-Beispiel

Caddy ist die Option mit “weniger Konfiguration, mehr Standards”. Wenn Sie einen öffentlichen Domainnamen in die Site-Adresse setzen, wird Caddy typischerweise Zertifikate automatisch ausstellen und erneuern.

Minimale Reverse-Proxy, HTTPS und streamingfreundliche Einstellungen:

# ollama.example.com A/AAAA -> Ihr Proxy-Host
ollama.example.com {

    # Optionale Basic Auth an der Kante.
    # Passwort-Hash generieren mit:
    #   caddy hash-password --algorithm bcrypt
    #
    # basic_auth {
    #   alice $2a$12$REDACTED...
    # }

    reverse_proxy 127.0.0.1:11434 {

        # Einige Setups bevorzugen das Fixieren des Upstream-Host-Headers.
        # Ollamas eigene Docs zeigen dieses Muster für Nginx.
        header_up Host localhost:11434

        # Für Streaming- oder chatähnliche Workloads, bevorzugen Sie niedrige Latenz.
        # NDJSON-Streaming spült in der Regel sowieso sofort, aber dies macht es explizit.
        flush_interval -1

        transport http {
            # Vermeiden Sie Upstream-Gzip-Verhandlung, wenn sie das Streaming beeinträchtigt.
            compression off

            # Geben Sie Ollama Zeit, ein Modell zu laden und das erste Chunk zu produzieren.
            response_header_timeout 10m
            dial_timeout 10s
        }
    }
}

Wenn Sie bereits ein SSO-Gateway haben (oauth2-proxy, Authelia, authentik outpost, etc.), hat Caddy eine opinionierte Direktive für Forward-Auth. Das Muster ist “Auth zuerst, dann Proxy”:

ollama.example.com {
    forward_auth 127.0.0.1:4180 {
        uri /oauth2/auth
        # Kopieren Sie die Identitäts-Header, die Ihr Gateway zurückgibt, wenn Sie sie benötigen.
        copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
    }

    reverse_proxy 127.0.0.1:11434
}

Nginx Server-Block-Beispiel

Nginx gibt Ihnen etwas mehr Spielraum. Der Vorteil ist, dass die Regler explizit sind, und es hat integrierte Primitive für Rate-Limiting und Verbindungslimitierung. Die Fallgrube ist das Puffern: Nginx puffert proxysierte Antworten standardmäßig, was das Gegenteil von dem ist, was Sie für NDJSON-Streaming wollen.

Dieses Beispiel enthält:

  • HTTP-zu-HTTPS-Redirect
  • TLS-Zertifikat-Pfade (Certbot-Stil)
  • WebSocket-sicheres Upgrade-Weiterleiten
  • Streaming-freundliches proxy_buffering off
  • Längere Timeouts als die Standard-60s
# /etc/nginx/conf.d/ollama.conf

# WebSocket-sichere Behandlung des Connection-Headers
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

# Optionales Anfrage-Rate-Limiting (IP-basiert)
# limit_req_zone $binary_remote_addr zone=ollama_rate:10m rate=10r/s;

server {
    listen 80;
    server_name ollama.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ollama.example.com;

    ssl_certificate     /etc/letsencrypt/live/ollama.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ollama.example.com/privkey.pem;

    # Optionale Basic Auth an der Kante.
    # auth_basic "Ollama";
    # auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        # Optionales Rate-Limit
        # limit_req zone=ollama_rate burst=20 nodelay;

        proxy_pass http://127.0.0.1:11434;

        # Match Ollama-Docs-Muster beim Proxieren zu localhost.
        proxy_set_header Host localhost:11434;

        # WebSocket-Upgrade-Behandlung (harmlos, wenn nicht verwendet).
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Kritisch für NDJSON-Streaming.
        proxy_buffering off;

        # Verhindern Sie 60s-Idle-Timeouts beim Warten auf Tokens.
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

Wenn Sie ein SSO-artiges Gate in Nginx wollen, ist das äquivalente Muster auth_request. Nginx sendet eine Subrequest an Ihren Auth-Dienst und proxysiert nur zu Ollama, wenn Auth 2xx zurückgibt.

TLS-Automatisierung und Erneuerungs-Fallen

Für TLS ist die operative Aufteilung einfach.

Mit Caddy ist TLS normalerweise “Teil des Reverse-Proxy”. Automatisches HTTPS ist eines seiner Flaggschiff-Features, sodass Zertifikatsausstellung und -erneuerung mit dem Laufen von Caddy, funktionierendem DNS und der Exposition der Ports 80 und 443 gekoppelt sind.

Mit Nginx ist TLS normalerweise “ein separater ACME-Client plus Nginx”. Der häufige Fehlermodus ist nicht Kryptografie, sondern die Verkabelung:

  • Port 80 ist für HTTP-01-Herausforderungen nicht erreichbar.
  • Zertifikate werden in einem Container gespeichert, aber nicht persistent gemacht.
  • Rate-Limits bei wiederholten frischen Installationen oder Test-Deployments.

Ein subtiler Punkt, der für langlebige Dienste wichtig ist, ist, dass Zertifikatslaufzeiten per Design kurz sind. Behandeln Sie Erneuerungen als Hintergrundautomatisierungsanforderung, nicht als jährliches Kalenderereignis.

Authentifizierung, Missbrauchskontrolle und Verifizierung

Das ist der Teil, der einem internetfähigen LLM-Endpunkt ein professionelles Gefühl verleiht.

Authentifizierungsoptionen, von stumpf bis elegant

Basic Auth am Proxy ist stumpf, aber überraschend effektiv für einen privaten Endpunkt. Es ist auch einfach sowohl auf HTTP-Anfragen als auch auf WebSocket-Upgrades anwendbar.

Wenn Sie browserfreundliche Login-Flows wollen, sind Forward-Auth und auth_request das gängige Muster. Ihr Proxy bleibt zustandslos, und ein Auth-Gateway besitzt Sitzungen und MFA. Der Kompromiss sind mehr bewegliche Teile.

Wenn Sie bereits Open WebUI betreiben, können Sie sich auch auf dessen App-Level-Authentifizierung verlassen und Ollama selbst privat halten. Der Proxy schützt dann Open WebUI, nicht direkt Ollama.

Wenn Sie gar keinen öffentlichen Zugriff benötigen, kann ein rein netzwerkbasierter Ansatz sauberer sein. Zum Beispiel kann Tailscale Serve einen lokalen Dienst innerhalb Ihres Tailnet aussetzen, ohne eingehende Ports an Ihrem Router zu öffnen. Für vollständige Muster (WireGuard, OLLAMA_HOST auf VPN-Schnittstellen, Firewall-Pinning, Sicherheitscheckliste) siehe Remote-Ollama-Zugriff über Tailscale oder WireGuard, keine öffentlichen Ports.

Missbrauchsbasis für eine teure API

Ollama ist eine leistungsstarke lokale API, und ihre Oberfläche geht über die Generierung hinaus. Es hat Endpunkte für Chat, Embeddings, Modellauflistung und Versionsprüfungen. Behandeln Sie die gesamte API als sensibel.

Offizielle API-Referenz (Endpunkte und Streaming): https://docs.ollama.com/api

Auf der Proxy-Ebene gibt es drei Low-Effort-Kontrollen, die den Schmerz am ersten Tag reduzieren:

  • Rate-Limiting pro IP an Generierungs-Endpunkten.
  • Verbindungslimits, um eine kleine Anzahl von Clients zu stoppen, die alles offen halten.
  • Konservative Timeouts, die Ihrer Modell- und Hardware-Realität entsprechen, nicht generischen Web-Standards.

Auf der Ollama-Ebene kann es auch Überlastung mit 503 ablehnen und hat serverseitige Regler für Warteschlangen. Proxy-Rate-Limiting hält Sie davon ab, so oft dorthin zu kommen.

Verifizierungscheckliste

Verwenden Sie dieselben Checks, die Sie für jede Streaming-API verwenden würden.

  1. Basis-Konnektivität und TLS

    • curl -sS https://ollama.example.com/api/version
    • curl -sS https://ollama.example.com/api/tags | head
  2. Streaming funktioniert von Ende zu Ende (kein Puffern)

    • curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'

    Wenn Sie hinter Basic Auth sind:

    • curl -N -u alice:REDACTED https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'
  3. Browser-UI-Sanity

    • Laden Sie Ihre Chat-UI und lösen Sie eine Antwort aus.
    • Wenn die UI WebSockets verwendet, bestätigen Sie, dass Sie keine 400- oder 426-Fehler sehen und die Verbindung während der Generierung offen bleibt.

Wenn die curl-Ausgabe nur am Ende erscheint, liegt es fast immer am Puffern am Proxy. Überprüfen Sie proxy_buffering off in Nginx und zwingen Sie niedrige Latenz-Spülung in Caddy für den Ollama-Site-Block.