Ollama bakom en omvänd proxy med Caddy eller Nginx för HTTPS-strömning

HTTPS för Ollama utan att störa strömande svar.

Sidinnehåll

Att köra Ollama bakom en omvänd proxy är det enklaste sättet att få HTTPS, valfri åtkontroll och förutsägbart strömmande beteende.

Detta inlägg fokuserar på Caddy och Nginx-ingress för Ollama-API:t, inte på klientkod.

ollama behind proxy

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 molnhostingens för- och nackdelar, se LLM-hosting 2026: Lokalt, Self-Hosted och molninfrastruktur jämfört.

För exempel på anrop och klientkod, se Ollama CLI-fuskblad.

För användargränssnitt och lager för flera användare, se Översikt, snabbstart och alternativ för Open WebUI.

För den större bilden av self-hosting och datakontroll, se LLM self-hosting och AI-suveränitet.

För en reproducerbar Ollama-tjänst på en enda nod i Docker Compose (beständiga volymer, OLLAMA_HOST, NVIDIA-GPU:er, uppgraderingar), se Ollama i Docker Compose med GPU och beständig modelllagring.

För fjärrenheter utan publika inkommande portar (Tailscale, WireGuard, binding, brandvägg), se Fjärråtkomst till Ollama via Tailscale eller WireGuard, inga publika portar.

Varför du bör proxya Ollama istället för att exponera port 11434

Ollama är designad att köras lokalt först. I grundkonfigurationen binder den till localhost på port 11434, vilket är utmärkt för en utvecklararbetsstation och en icke-så-subtil hint om att den råa porten inte är avsedd att vara internetexponerad.

Jag behandlar port 11434 som en intern, kostsam API. Om den är nåbar från det offentliga internet kan vem som helst som hittar den bränna din CPU- eller GPU-tid, fylla din disk genom att dra ner modeller, eller bara hålla anslutningar öppna tills något timeoutas. En omvänd proxy gör inte Ollama säkrare genom magi, men den ger dig en plats att placera de kontroller som gäller vid kanten: TLS, autentisering, timeouts, hastighetsbegränsningar och loggar.

Detta är viktigt eftersom den lokala Ollama-API:t inte levereras med en inbyggd autentiseringslager. Om du exponerar den lägger du vanligtvis till auth vid kanten eller håller den privat och nåbar endast över ett tillförlitligt nätverk.

Den andra anledningen är användarupplevelsen (UX). Ollama strömmar svar som standard. Om proxyn buffrar eller komprimerar på fel ställe känns strömmandet trasigt och gränssnitten ser ut som att de “tänker” utan utdata.

Minimal arkitektur och bindningsstrategi

En ren minimal konfiguration 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 container-nätverk), bind Ollama till ett privat gränssnitt, inte 0.0.0.0 på det publika nätverkskortet, och lita på en brandvägg.

Andra, bestäm tidigt om webbläsare kommer att anropa Ollama direkt. Om ett verktyg baserat i webbläsaren 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 förnuft) 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 nyradelad JSON (NDJSON). Det betyder att du vill ha en proxy som kan göra tre saker bra:

  • Buffra inte strömmade svar.
  • Avsluta inte långkörande anrop bara för att modellen tog en stund att prata.
  • Om ett gränssnitt använder WebSockets (vissa gör det), forwarda Upgrade smidigt.

Du kan hålla detta enkelt. I många fall är “korrekt WebSockets-hantering” bara att ha en konfiguration som är Upgrade-säker, även om upstream inte använder WebSockets idag.

Caddy Caddyfile-exempel

Caddy är alternativet med “mindre konfiguration, fler standardvärden”. Om du sätter ett publikt domännamn i adressen kommer Caddy vanligtvis att skaffa och förnya certifikat automatiskt.

Minimal omvänd proxy, HTTPS och strömmarvä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 uppställningar föredrar att fästa upstreams Host-header.
        # Ollamas egna dokument 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 flushar vanligtvis direkt ändå, men detta gör det explicit.
        flush_interval -1

        transport http {
            # Undvik upstream gzip-negotiering om det stör strömmande.
            compression off

            # Ge Ollama tid att ladda en modell och producera den första chunken.
            response_header_timeout 10m
            dial_timeout 10s
        }
    }
}

Om du redan har en SSO-gate (oauth2-proxy, Authelia, authentik outpost etc.), har Caddy en åsiktsfull forward auth-direktiv. 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 gateway returnerar, om du behöver dem.
        copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
    }

    reverse_proxy 127.0.0.1:11434
}

Nginx server block-exempel

Nginx ger dig lite mer tyglängd. Fördelen är att reglarna är explicita, och den har inbyggda primitiver för hastighetsbegränsning och anslutningsbegränsning. Fällan är buffring: Nginx buffrar proxade svar som standard, vilket är motsatsen till vad du vill för NDJSON-strömmande.

Detta exempel inkluderar:

  • HTTP till HTTPS-omriktning
  • TLS-certifikatvägar (Certbot-stil)
  • WebSocket-säker Upgrade-forwarding
  • Strömmarvänlig proxy_buffering off
  • Längre timeouts än standard 60s
# /etc/nginx/conf.d/ollama.conf

# WebSocket-säker hantering av Connection-huvudet
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

# Valfri begäran för hastighetsbegränsning (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 Ollama-dokumentmönster när man proxyar till localhost.
        proxy_set_header Host localhost:11434;

        # WebSocket Upgrade-hantering (ofarlig om inte 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 inaktiva timeouts medan man väntar på token.
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

Om du vill ha en SSO-stil gate i Nginx är det ekvivalenta mönstret auth_request. Nginx skickar en sub-request till din auth-tjänst och proxar bara till Ollama när auth returnerar 2xx.

TLS-automatisering och förnyelsefällor

För TLS är den operativa uppdelningen enkel.

Med Caddy är TLS vanligtvis “en del av den omvända proxyn”. Automatisk HTTPS är en av dess flaggskeppsfunktioner, så certifikatutgivning och förnyelse är kopplade till att hålla Caddy igång, ha fungerande DNS och exponera portar 80 och 443.

Med Nginx är TLS vanligtvis “en separat ACME-klient plus Nginx”. Det vanliga misslyckandet är inte kryptografi, det är rördragning:

  • Port 80 är inte nåbar för HTTP-01-utmaningar.
  • Certifikat lagras i en container men inte beständigt.
  • Hastighetsbegränsningar vid upprepade nya installationer eller testdeployments.

En subtil punkt som är viktig för långlivade tjänster är att certifikatlängder är korta per design. Behandla förnyelser som ett bakgrundsautomatiseringskrav, inte ett årligt kalenderhändelse.

Autentisering, missbrukskontroll och verifiering

Detta är den del som gör en internetexponerad LLM-endpoint känns professionell.

Autentiseringsalternativ, från grovt till elegant

Basic Auth vid proxyn är grovt, men förvånande effektivt för en privat endpoint. Det är också enkelt att applicera på både HTTP-anrop och WebSocket-upgrades.

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 auth-gateway äger sessioner och MFA. Kostnaden är mer 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 då Open WebUI, inte Ollama direkt.

Om du inte behöver offentlig åtkomst alls kan en nätverksenbart approach vara renare. Till exempel kan Tailscale Serve exponera en lokal tjänst inuti ditt tailnet utan att öppna inkommande portar på din router. För fulla mönster (WireGuard, OLLAMA_HOST på VPN-gränssnitt, brandväggsfästning, säkerhetschecklista), se Fjärråtkomst till Ollama via Tailscale eller WireGuard, inga publika portar.

Missbruksbasics för en dyr API

Ollama är ett kraftfullt lokalt API, och dess yta sträcker sig bortom generering. Den 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åg-insatser som minskar smärtan första dagen:

  • Hastighetsbegränsning per IP på genereringsendpoints.
  • Anslutningsbegränsningar för att stoppa ett litet antal klienter från att hålla allt öppet.
  • Konservativa timeouts som matchar din modell och hårdvarurealitet, inte generiska webbutgångsvärden.

På Ollama-lagret kan den också avvisa överbelastning med 503 och har serverbaserade reglar för köning. Proxyhastighetsbegränsning håller dig från att hamna där så ofta.

Verifieringschecklista

Använd samma kontroller som du skulle göra för vilken strömmande API som helst.

  1. Grundläggande anslutning och TLS

    • curl -sS https://ollama.example.com/api/version
    • curl -sS https://ollama.example.com/api/tags | head
  2. Strömmande fungerar från början till slut (ingen buffring)

    • curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Skriv 10 ord bara.","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":"Skriv 10 ord bara.","stream":true}'
  3. Webbläsar-UI-förnuft

    • Ladda din chatt-UI och utlösa ett svar.
    • Om UI:n 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 dyker upp i slutet är det nästan alltid buffring vid proxyn. Kontrollera proxy_buffering off i Nginx igen, och överväg att tvinga låg-latens-flush i Caddy för Ollama-site-blocken.

Prenumerera

Få nya inlägg om system, infrastruktur och AI-ingenjörskonst.