Ollama bakom en omvänd proxy med Caddy eller Nginx för HTTPS-strömmande
HTTPS för Ollama utan att bryta strömmande svar.
Att köra Ollama bakom en omvänd proxy är det enklaste sättet att få HTTPS, tillval för åtkomstkontroll och förutsägbar strömmande beteende.
Detta inlägg fokuserar på Caddy och Nginx-ingress för Ollama-API:t, inte på klientkod.

Om du redan har Python- eller Go-klienter som pratar med Ollama, är detta inlägg den saknade biten: ingress och transport för samma API.
För hur Ollama passar in bredvid vLLM, Docker Model Runner, LocalAI och molnhärbete, se LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared.
För exempel på förfrågningar och klientkod, se Ollama CLI Cheatsheet.
För användargränssnitt och lager för flera användare, se Open WebUI overview, quickstart and alternatives.
För den större bilden av självhospitering och datakontroll, se LLM self-hosting and AI sovereignty.
För en reproducerbar Ollama-tjänst för en nod i Docker Compose (beständiga volymer, OLLAMA_HOST, NVIDIA-GPU:er, uppdateringar), se
Ollama in Docker Compose with GPU and Persistent Model Storage.
Varför du bör proxya Ollama istället för att exponera port 11434
Ollama är utformat för att köras lokalt först. Som standard binder det sig till localhost på port 11434, vilket är bra för en utvecklingsarbetsstation och en inte så subtil hint om att den råa porten inte är tänkt att vara internetexponerad.
Jag behandlar port 11434 som en intern, kostsam API. Om den är nåbar från det offentliga internet kan alla som hittar den bränna din CPU- eller GPU-tid, fylla din disk genom att dra ner modeller, eller bara hålla anslutningarna öppna tills något timeoutar. En omvänd proxy gör inte Ollama säkrare genom magi, men det ger dig en plats att placera de kontroller som spelar roll vid kanten: TLS, autentisering, tidsgränser, hastighetsbegränsningar och loggar.
Detta spelar roll eftersom den lokala Ollama-API:t inte levereras med ett inbyggt autentiseringslager. Om du exponerar det lägger du typiskt till auth vid kanten eller håller det privat och endast nåbart över ett betroget nätverk.
Den andra anledningen är användarupplevelsen. Ollama strömmar svar som standard. Om proxyn buffrar eller komprimerar på fel ställe, känns strömmandet trasigt och användargränssnitten verkar “tänka” utan att producera något utdata.
Minimal arkitektur och bindningsstrategi
En ren minimal version ser ut så här:
Client (curl, Python, Go, UI)
|
| HTTPS (valfri Basic Auth eller SSO)
v
Omvänd proxy (Caddy eller Nginx)
|
| HTTP (privat LAN, localhost eller Docker-nätverk)
v
Ollama-server (ollama serve på 127.0.0.1:11434)
Två praktiska regler håller detta tråkigt på bästa sätt.
Först, håll Ollama privat och flytta exponeringen till proxyn. Om Caddy eller Nginx körs på samma värd, proxya till 127.0.0.1:11434 och ändra inte Ollamas bindningsadress. Om proxyn körs någon annanstans (separat värd, separat VM eller ett behållarnätverk), bind Ollama till ett privat gränssnitt, inte 0.0.0.0 på den offentliga NIC:n, och lita på en brandvägg.
Andra, bestäm dig tidigt om webbläsare ska anropa Ollama direkt. Om ett verktyg baserat på webbläsare träffar Ollama från ett annat ursprung, kan du behöva hantera CORS. Om allt serveras från ett domän via proxyn (rekommenderat för att hålla det enkelt), kan du ofta undvika CORS helt och hålla Ollama strikt.
Konfigurationer för omvänd proxy för strömmande och WebSockets
Ollamas API är vanligt HTTP, och dess strömmande är newline-delimited JSON (NDJSON). Det innebär att du vill ha en proxy som kan göra tre saker bra:
- Buffra inte strömande svar.
- Mörda inte långkörande förfrågningar bara för att modellen tog lite tid att prata.
- Om ett UI använder WebSockets (vissa gör det), skicka vidare Upgrade rent.
Du kan hålla detta enkelt. I många fall är “korrekt hantering av WebSockets” bara att ha en konfiguration som är Upgrade-säker även om upstream inte använder WebSockets idag.
Exempel på Caddy Caddyfile
Caddy är alternativet med “mindre konfiguration, fler standardvärden”. Om du lägger in ett offentligt domännamn i adressen för webbplatsen, kommer Caddy typiskt att skaffa och förnya certifikat automatiskt.
Minimal omvänd proxy, HTTPS och strömmande-vänliga inställningar:
# ollama.example.com A/AAAA -> din proxy-värd
ollama.example.com {
# Valfri Basic Auth vid kanten.
# Generera ett lösenordshash med:
# caddy hash-password --algorithm bcrypt
#
# basic_auth {
# alice $2a$12$REDACTED...
# }
reverse_proxy 127.0.0.1:11434 {
# Vissa konfigurationer föredrar att fastlåsa upstreams Host-huvud.
# Ollamas egna dokumentation visar detta mönster för Nginx.
header_up Host localhost:11434
# För strömmande eller chattliknande arbetsbelastningar, föredra låg latens.
# NDJSON-strömmande spolar vanligtvis omedelbart ändå, men detta gör det explicit.
flush_interval -1
transport http {
# Undvik upstream-gzip-negoitering om det stör strömmandet.
compression off
# Ge Ollama tid att ladda en modell och producera den första biten.
response_header_timeout 10m
dial_timeout 10s
}
}
}
Om du redan har en SSO-port (oauth2-proxy, Authelia, authentik outpost, etc.), har Caddy en åsiktsfull direktiv för forward auth. Mönstret är “auth först, sedan proxy”:
ollama.example.com {
forward_auth 127.0.0.1:4180 {
uri /oauth2/auth
# Kopiera identitetshuvudena som din port returnerar, om du behöver dem.
copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
}
reverse_proxy 127.0.0.1:11434
}
Exempel på Nginx server block
Nginx ger dig lite mer frihet. Fördelen är att knopparna är explicita, och det har inbyggda primitiv för hastighetsbegränsning och anslutningsbegränsning. Fallgropen är buffring: Nginx buffrar proxade svar som standard, vilket är motsatsen till vad du vill ha för NDJSON-strömmande.
Detta exempel inkluderar:
- Omdirigering från HTTP till HTTPS
- Sökvägar för TLS-certifikat (Certbot-stil)
- WebSocket-säker uppgradering (Upgrade) vidarebefordran
- Strömmande-vänlig proxy_buffering av
- Längre tidsgränser än standarden 60s
# /etc/nginx/conf.d/ollama.conf
# WebSocket-säker hantering av Connection-huvud
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
# Valfri hastighetsbegränsning för förfrågningar (IP-baserad)
# 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;
# Valfri Basic Auth vid kanten.
# auth_basic "Ollama";
# auth_basic_user_file /etc/nginx/.htpasswd;
location / {
# Valfri hastighetsbegränsning
# limit_req zone=ollama_rate burst=20 nodelay;
proxy_pass http://127.0.0.1:11434;
# Matcha mönstret i Ollama-dokumentationen när man proxar till localhost.
proxy_set_header Host localhost:11434;
# WebSocket Upgrade-hantering (ofarlig om ej använd).
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Kritiskt för NDJSON-strömmande.
proxy_buffering off;
# Förhindra 60s inaktivitetstidsgränser medan man väntar på token.
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Om du vill ha en SSO-stil port i Nginx, är det ekvivalenta mönstret auth_request. Nginx skickar en underförfrågan till din autentiserings tjänst, och proxar bara till Ollama när auth returnerar 2xx.
Gotchas för TLS-automatisering och förnyelse
För TLS är den operativa uppdelningen enkel.
Med Caddy är TLS vanligtvis “en del av den omvända proxyn”. Automatisk HTTPS är ett av dess flaggskepp, så certifikatutgivningen och förnyelsen är kopplad till att hålla Caddy igång, ha fungerande DNS och exponera port 80 och 443.
Med Nginx är TLS vanligtvis “en separat ACME-klient plus Nginx”. Det vanliga misslyckandet är inte kryptografi, det är rörliga delar:
- Port 80 är inte nåbar för HTTP-01-utmaningar.
- Certifikat lagras i en behållare men inte persisteras.
- Hastighetsbegränsningar vid upprepade nya installationer eller testdeployment.
En subtil punkt som spelar roll för långlivade tjänster är att certifikattidsåldrar är korta av design. Behandla förnyelser som ett bakgrundsautomatiseringkrav, inte ett årligt kalenderhändelse.
Autentisering, missbrukskontroll och verifiering
Detta är den del som gör att en internetexponerad LLM-endpunkt känns professionell.
Autentiseringsalternativ, från grovt till elegant
Basic Auth vid proxyn är grovt, men överraskande effektivt för en privat endpoint. Det är också enkelt att applicera på både HTTP-förfrågningar och WebSocket-uppgraderingar.
Om du vill ha webbläsarvänliga inloggningsflöden, är forward auth och auth_request det vanliga mönstret. Din proxy förblir tillståndslös, och en autentiseringsport äger sessioner och MFA. Kompromissen är fler rörliga delar.
Om du redan kör Open WebUI, kan du också lita på dess app-nivåautentisering och hålla Ollama själv privat. Proxyn skyddar sedan Open WebUI, inte Ollama direkt.
Om du inte behöver offentlig åtkomst alls, kan en nätverksenbart-ansats vara renare. Till exempel kan Tailscale Serve exponera en lokal tjänst inuti ditt tailnet utan att öppna inkommande portar på din router.
Grundläggande missbruk för en dyr API
Ollama är en kraftfull lokal API, och dess yta sträcker sig bortom generering. Det har endpoints för chatt, inbäddningar, listning av modeller och versionskontroller. Behandla hela API:t som känsligt.
Officiell API-referens (endpoints och strömmande): https://docs.ollama.com/api
På proxy-lagret finns det tre låginsatskontroller som minskar smärtan första dagen:
- Hastighetsbegränsning per IP på genererings-endpoints.
- Anslutningsbegränsningar för att stoppa ett litet antal klienter från att hålla allt öppet.
- Konservativa tidsgränser som matchar din modell och hårdvarurealitet, inte generiska webbbaserade standardvärden.
På Ollama-lagret kan det också avvisa överbelastning med 503 och har server-sidiga knoppar för köning. Proxy-hastighetsbegränsning håller dig från att komma dit lika ofta.
Verifieringschecklista
Använd samma kontroller som du skulle använda för vilken strömmande API som helst.
-
Grundläggande konnektivitet och TLS
curl -sS https://ollama.example.com/api/versioncurl -sS https://ollama.example.com/api/tags | head
-
Strömmande fungerar från ända till ända (ingen buffring)
curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'
Om du är bakom Basic Auth:
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}'
-
Webbläsar-UI-sanity
- Ladda din chatt-UI och utlösa ett svar.
- Om UI:t använder WebSockets, bekräfta att du inte ser 400- eller 426-fel och att anslutningen hålls öppen under generering.
Om curl-utdata bara visas i slutet, är det nästan alltid buffring vid proxyn. Kontrollera proxy_buffering off i Nginx, och överväg att tvinga låglatens-spolning i Caddy för Ollama-webbplatsblocken.