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

HTTPS für Ollama ohne Beeinträchtigung der Streaming-Antworten.

Inhaltsverzeichnis

Das Betreiben von Ollama hinter einem Reverse-Proxy ist der einfachste Weg, um HTTPS, optionale Zugriffskontrolle und 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

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

Um zu erfahren, wie Ollama neben vLLM, Docker Model Runner, LocalAI und den Kompromissen bei der Cloud-Hosting-Infrastruktur passt, lesen Sie LLM-Hosting 2026: Lokal, Self-Hosted & Cloud-Infrastruktur im Vergleich.

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

Für die Benutzeroberfläche und Multi-User-Schichten siehe Open WebUI Übersicht, Quickstart und Alternativen.

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

Für einen reproduzierbaren Ollama-Dienst auf einem einzelnen Knoten in Docker Compose (persistente Volumes, OLLAMA_HOST, NVIDIA-GPUs, Upgrades) siehe Ollama in Docker Compose mit GPU und persistenter Modell-Speicherung.

Warum Sie Ollama proxieren sollten, anstatt Port 11434 freizugeben

Ollama ist darauf ausgelegt, zunächst lokal ausgeführt zu werden. Standardmäßig bindet es sich an localhost auf Port 11434, was hervorragend für eine Entwickler-Workstation ist und eine nicht ganz subtile Andeutung enthält, dass der rohe Port nicht für das Internet gedacht ist.

Ich betrachte Port 11434 als eine interne, kostspielige API. Wenn er aus dem öffentlichen Internet erreichbar ist, kann jeder, der ihn findet, Ihre CPU- oder GPU-Zeit verbrauchen, Ihre Festplatte durch das Herunterladen von Modellen füllen oder einfach Verbindungen offen lassen, bis eine Zeitüberschreibung eintritt. Ein Reverse-Proxy macht Ollama nicht durch Zauber sicherer, aber er bietet Ihnen einen Ort, um die wichtigen Kontrollen am Rand zu platzieren: TLS, Authentifizierung, Timeouts, Rate-Limits und Logs.

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

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

Minimale Architektur und Bindungsstrategie

Eine saubere Minimalversion 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 Weise langweilig.

Erstens: Halten Sie Ollama privat und verlagern Sie die Exposition zum 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 Netzwerkkarte, und verlassen Sie sich auf eine Firewall.

Zweitens: Entscheiden Sie frühzeitig, ob Browser Ollama direkt aufrufen. Wenn ein browserbasiertes Tool Ollama von einer anderen Herkunft aus trift, müssen Sie möglicherweise mit CORS umgehen. Wenn alles über den Proxy von einer Domain aus geliefert 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

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

  • Streaming-Antworten nicht puffern.
  • Lange laufende Anfragen nicht einfach töten, nur weil das Modell eine Weile braucht, um zu sprechen.
  • Falls eine UI WebSockets verwendet (einige tun dies), Upgrade sauber weiterleiten.

Sie können dies einfach halten. In vielen Fällen ist „korrekte WebSocket-Handhabung" nur eine Konfiguration, die Upgrade-sicher ist, selbst wenn der Upstream 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 eingeben, wird Caddy in der Regel Zertifikate automatisch erhalten und erneuern.

Minimale Reverse-Proxy-, HTTPS- und streamingfreundliche Einstellungen:

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

    # Optionale Basic Auth am Rand.
    # Generieren Sie einen Passwort-Hash mit:
    #   caddy hash-password --algorithm bcrypt
    #
    # basic_auth {
    #   alice $2a$12$REDACTED...
    # }

    reverse_proxy 127.0.0.1:11434 {

        # Manche Setups bevorzugen die Fixierung 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 ist geringe Latenz vorzuziehen.
        # NDJSON-Streaming spült normalerweise ohnehin sofort, aber dies macht es explizit.
        flush_interval -1

        transport http {
            # Vermeiden Sie Upstream-Gzip-Verhandlung, wenn sie mit Streaming interferiert.
            compression off

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

Falls Sie bereits ein SSO-Gateway haben (oauth2-proxy, Authelia, authentik outpost usw.), verfügt Caddy über eine opinionierte Forward-Auth-Direktive. Das Muster lautet „Authentifizierung 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, falls 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 Schnur. Der Vorteil ist, dass die Schalter explizit sind, und es hat eingebaute Primivien für Rate-Limiting und Verbindungs-Limiting. Der Stolperstein ist das Puffern: Nginx puffert proxierte 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-Zertifikatpfade (Certbot-Stil)
  • WebSocket-sicheres Upgrade-Forwarding
  • Streaming-freundliches proxy_buffering off
  • Längere Timeouts als das Standard-60s
# /etc/nginx/conf.d/ollama.conf

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

# Optionales Request-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 am Rand.
    # 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;

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

        # WebSocket-Upgrade-Behandlung (harmlos, wenn ungenutzt).
        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;
    }
}

Falls Sie ein SSO-ähnliches Gate in Nginx wünschen, ist das äquivalente Muster auth_request. Nginx sendet eine Sub-Anfrage an Ihren Authentifizierungsdienst und proxiert nur zu Ollama, wenn auth mit 2xx zurückkehrt.

TLS-Automatisierung und Erneuerungsfallen

Für TLS ist die operative Aufteilung einfach.

Bei Caddy ist TLS normalerweise „Teil des Reverse-Proxy". Automatisches HTTPS ist eines seiner Flaggschiff-Features, sodass die Zertifikatsausstellung und -erneuerung an das Laufen von Caddy, funktionierende DNS und das Freigeben der Ports 80 und 443 gebunden sind.

Bei Nginx ist TLS normalerweise „ein separater ACME-Client plus Nginx". Der häufige Ausfallmodus ist keine Kryptografie, sondern die Verrohrung:

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

Ein subtiler Punkt, der für langlebige Dienste wichtig ist, ist, dass Zertifikatslebensdauern bewusst kurz sind. Behandeln Sie Erneuerungen als eine Anforderung an die Hintergrundautomatisierung, nicht als jährliches Kalendereignis.

Authentifizierung, Missbrauchskontrolle und Verifizierung

Das ist der Teil, der einem internetförmigen LLM-Endpunkt einen professionellen Eindruck verleiht.

Authentifizierungsoptionen, von stumpf bis elegant

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

Falls Sie browserfreundliche Login-Flows wünschen, sind forward_auth und auth_request das übliche Muster. Ihr Proxy bleibt zustandslos, und ein Auth-Gateway verwaltet Sitzungen und MFA. Der Kompromiss sind mehr bewegliche Teile.

Falls 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.

Falls Sie überhaupt keinen öffentlichen Zugang benötigen, kann ein reines Netzwerk-Approach sauberer sein. Zum Beispiel kann Tailscale Serve einen lokalen Dienst innerhalb Ihres Tailnet ausliefern, ohne eingehende Ports auf Ihrem Router zu öffnen.

Missbrauchsbasics für eine teure API

Ollama ist eine leistungsstarke lokale API, und ihre Oberfläche geht über Generierung hinaus. Es gibt Endpunkte für Chat, Embeddings, das Auflisten von Modellen 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 niedrigschwellige Kontrollen, die den Tag-eins-Schmerz reduzieren:

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

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

Verifizierungs-Checkliste

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

  1. Grundlegende 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}'

    Falls 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.
    • Falls die UI WebSockets verwendet, stellen Sie sicher, dass Sie keine 400- oder 426-Fehler sehen und die Verbindung während der Generierung offen bleibt.

Falls die curl-Ausgabe nur am Ende erscheint, liegt es fast immer am Puffern am Proxy. Überprüfen Sie erneut proxy_buffering off in Nginx und erwägen Sie, das low-latency-Flushing in Caddy für den Ollama-Site-Block zu erzwingen.