Ollama derrière un proxy inversé avec Caddy ou Nginx pour le streaming HTTPS
HTTPS Ollama sans interrompre les réponses en streaming.
Exécuter Ollama derrière un reverse proxy est le moyen le plus simple d’obtenir HTTPS, un contrôle d’accès facultatif et un comportement de streaming prévisible.
Cet article se concentre sur l’ingress Caddy et Nginx pour l’API Ollama, et non sur le code client.

Si vous avez déjà des clients Python ou Go communiquant avec Ollama, cet article est la pièce manquante : l’ingress et le transport pour la même API.
Pour comprendre comment Ollama s’intègre avec vLLM, Docker Model Runner, LocalAI et les compromis liés à l’hébergement cloud, consultez LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared.
Pour des exemples de requêtes et du code client, consultez Ollama CLI Cheatsheet.
Pour les couches d’interface utilisateur et multi-utilisateurs, consultez Open WebUI overview, quickstart and alternatives.
Pour avoir une vue d’ensemble sur l’auto-hébergement et le contrôle des données, consultez LLM self-hosting and AI sovereignty.
Pour un service Ollama sur un nœud unique et reproductible dans Docker Compose (volumes persistants, OLLAMA_HOST, GPU NVIDIA, mises à jour), consultez
Ollama in Docker Compose with GPU and Persistent Model Storage.
Pourquoi il faut proxifier Ollama plutôt qu’exposer le port 11434
Ollama est conçu pour s’exécuter localement en priorité. Par défaut, il se lie au localhost sur le port 11434, ce qui est idéal pour une station de développement et constitue une indication subtile que le port brut n’est pas destiné à être exposé sur Internet.
Je considère le port 11434 comme une API interne à coût élevé. Si elle est accessible depuis Internet public, toute personne qui la trouve peut épuiser votre temps CPU ou GPU, remplir votre disque en téléchargeant des modèles, ou simplement maintenir les connexions ouvertes jusqu’à ce qu’un délai d’expiration se produise. Un reverse proxy ne rend pas Ollama plus sûr par magie, mais il vous offre un endroit pour placer les contrôles essentiels en bordure : TLS, authentification, délais d’expiration, limites de débit et journaux.
Cela est important car l’API locale Ollama ne dispose pas d’une couche d’authentification intégrée. Si vous l’exposez, vous ajoutez généralement l’authentification en bordure ou la maintenez privée et accessible uniquement via un réseau de confiance.
La seconde raison concerne l’expérience utilisateur (UX). Ollama diffuse les réponses par défaut. Si le proxy tamponne ou compresse au mauvais endroit, le streaming semble cassé et les interfaces utilisateur (UI) ont l’air de “réfléchir” sans produire de sortie.
Architecture minimale et stratégie de liaison
Une architecture minimale propre ressemble à ceci :
Client (curl, Python, Go, UI)
|
| HTTPS (Authentification de base ou SSO optionnelle)
v
Reverse proxy (Caddy ou Nginx)
|
| HTTP (LAN privé, localhost ou réseau Docker)
v
Serveur Ollama (ollama serve sur 127.0.0.1:11434)
Deux règles pratiques permettent de garder cela simple de la meilleure manière.
Premièrement, gardez Ollama privé et déplacez l’exposition vers le proxy. Si Caddy ou Nginx s’exécute sur le même hôte, proxifiez vers 127.0.0.1:11434 et ne modifiez pas l’adresse de liaison d’Ollama. Si le proxy s’exécute ailleurs (hôte séparé, VM séparée ou réseau de conteneur), liez Ollama à une interface privée, pas à 0.0.0.0 sur l’interface réseau publique, et comptez sur un pare-feu.
Deuxièmement, décidez tôt si les navigateurs appelleront Ollama directement. Si un outil basé sur le navigateur touche Ollama depuis un autre origine, vous devrez peut-être gérer CORS. Si tout est servi depuis un seul domaine via le proxy (recommandé pour la santé mentale), vous pouvez souvent éviter CORS entirely et garder Ollama strict.
Configurations de reverse proxy pour le streaming et WebSockets
L’API d’Ollama est du HTTP classique, et son streaming est du JSON délimité par des nouvelles lignes (NDJSON). Cela signifie que vous voulez un proxy capable de faire trois choses bien :
- Ne pas tamponner les réponses en streaming.
- Ne pas tuer les requêtes longues simplement parce que le modèle a mis du temps à répondre.
- Si une UI utilise WebSockets (certaines le font), transmettre Upgrade proprement.
Vous pouvez garder cela simple. Dans de nombreux cas, un “traitement correct des WebSockets” consiste simplement à avoir une configuration sécurisée pour Upgrade, même si l’amont n’utilise pas WebSockets aujourd’hui.
Exemple de Caddyfile
Caddy est l’option “moins de config, plus de défauts”. Si vous placez un nom de domaine public dans l’adresse du site, Caddy obtiendra et renouvellera généralement les certificats automatiquement.
Paramètres minimaux pour le reverse proxy, HTTPS et compatibles streaming :
# ollama.example.com A/AAAA -> votre hôte proxy
ollama.example.com {
# Authentification de base optionnelle en bordure.
# Générez un hachage de mot de passe avec :
# caddy hash-password --algorithm bcrypt
#
# basic_auth {
# alice $2a$12$REDACTED...
# }
reverse_proxy 127.0.0.1:11434 {
# Certains environnements préfèrent fixer l'en-tête Host amont.
# La propre documentation d'Ollama montre ce modèle pour Nginx.
header_up Host localhost:11434
# Pour les charges de travail de streaming ou de chat, privilégiez une faible latence.
# Le streaming NDJSON vide généralement immédiatement, mais cela le rend explicite.
flush_interval -1
transport http {
# Évitez la négociation gzip amont si elle interfère avec le streaming.
compression off
# Donnez à Ollama le temps de charger un modèle et de produire le premier chunk.
response_header_timeout 10m
dial_timeout 10s
}
}
}
Si vous avez déjà une passerelle SSO (oauth2-proxy, Authelia, authentik outpost, etc.), Caddy dispose d’une directive d’authentification forward. Le modèle est “auth d’abord, puis proxy” :
ollama.example.com {
forward_auth 127.0.0.1:4180 {
uri /oauth2/auth
# Copiez les en-têtes d'identité que votre passerelle retourne, si nécessaire.
copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
}
reverse_proxy 127.0.0.1:11434
}
Exemple de bloc serveur Nginx
Nginx vous donne un peu plus de liberté. L’avantage est que les paramètres sont explicites et qu’il dispose de primitives intégrées pour la limitation de débit et de connexion. Le piège est le tamponnage : Nginx tamponne les réponses proxifiées par défaut, ce qui est l’inverse de ce que vous voulez pour le streaming NDJSON.
Cet exemple inclut :
- Redirection HTTP vers HTTPS
- Chemins des certificats TLS (style Certbot)
- Transmission Upgrade sécurisée pour WebSocket
- proxy_buffering désactivé pour être compatible avec le streaming
- Des délais d’expiration plus longs que la valeur par défaut de 60s
# /etc/nginx/conf.d/ollama.conf
# Gestion sécurisée de l'en-tête Connection pour WebSocket
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
# Limitation de débit optionnelle (basée sur l'IP)
# 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;
# Authentification de base optionnelle en bordure.
# auth_basic "Ollama";
# auth_basic_user_file /etc/nginx/.htpasswd;
location / {
# Limitation de débit optionnelle
# limit_req zone=ollama_rate burst=20 nodelay;
proxy_pass http://127.0.0.1:11434;
# Correspondre au modèle de la documentation Ollama lors de la proxification vers localhost.
proxy_set_header Host localhost:11434;
# Gestion de la mise à niveau WebSocket (inoffensif si inutilisé).
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Critique pour le streaming NDJSON.
proxy_buffering off;
# Empêcher les délais d'expiration de 60s pendant l'attente des jetons.
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Si vous voulez une porte de style SSO dans Nginx, le modèle équivalent est auth_request. Nginx envoie une sous-requête à votre service d’authentification et ne proxifie vers Ollama que lorsque l’authentification retourne 2xx.
Pièges de l’automatisation et du renouvellement TLS
Pour TLS, la séparation opérationnelle est simple.
Avec Caddy, le TLS fait généralement “partie du reverse proxy”. L’HTTPS automatique est l’une de ses fonctionnalités phares, donc l’émission et le renouvellement des certificats sont couplés au maintien de Caddy en cours d’exécution, à un DNS fonctionnel et à l’exposition des ports 80 et 443.
Avec Nginx, le TLS est généralement “un client ACME séparé plus Nginx”. Le mode d’échec courant n’est pas cryptographique, c’est la plomberie :
- Port 80 inaccessible pour les défis HTTP-01.
- Certificats stockés dans un conteneur mais non persistés.
- Limites de débit lors d’installations fraîches répétées ou de déploiements de test.
Un point subtil qui compte pour les services de longue durée est que la durée de vie des certificats est courte par conception. Traitez les renouvellements comme une exigence d’automatisation en arrière-plan, et non comme un événement annuel.
Authentification, contrôle des abus et vérification
C’est la partie qui donne une touche professionnelle à un endpoint LLM exposé sur Internet.
Options d’authentification, du brutal à l’élégant
L’authentification de base au niveau du proxy est brutale, mais étonnamment efficace pour un endpoint privé. Elle est également facile à appliquer aux requêtes HTTP et aux mises à niveau WebSocket.
Si vous voulez des flux de connexion conviviaux pour les navigateurs, forward auth et auth_request sont les modèles courants. Votre proxy reste sans état, et une passerelle d’authentification gère les sessions et l’authentification à deux facteurs (MFA). Le compromis est plus de pièces mobiles.
Si vous exécutez déjà Open WebUI, vous pouvez également vous fier à son authentification au niveau de l’application et garder Ollama lui-même privé. Le proxy protège alors Open WebUI, et non Ollama directement.
Si vous n’avez pas besoin d’accès public du tout, une approche réseau uniquement peut être plus propre. Par exemple, Tailscale Serve peut exposer un service local à l’intérieur de votre tailnet sans ouvrir de ports entrants sur votre routeur.
Bases du contrôle des abus pour une API coûteuse
Ollama est une API locale puissante, et sa surface va au-delà de la génération. Il dispose d’endpoints pour le chat, les embeddings, la liste des modèles et les vérifications de version. Traitez toute l’API comme sensible.
Référence officielle de l’API (endpoints et streaming) : https://docs.ollama.com/api
Au niveau du proxy, il existe trois contrôles à faible effort qui réduisent la douleur du premier jour :
- Limitation de débit par IP sur les endpoints de génération.
- Limites de connexion pour empêcher un petit nombre de clients de maintenir tout ouvert.
- Des délais d’expiration conservateurs qui correspondent à votre réalité de modèle et de matériel, et non aux défauts web génériques.
Au niveau d’Ollama, il peut également rejeter la surcharge avec 503 et dispose de paramètres côté serveur pour la file d’attente. La limitation de débit du proxy vous empêche d’arriver là aussi souvent.
Liste de vérification
Utilisez les mêmes vérifications que vous utiliseriez pour n’importe quelle API de streaming.
-
Connectivité de base et TLS
curl -sS https://ollama.example.com/api/versioncurl -sS https://ollama.example.com/api/tags | head
-
Le streaming fonctionne de bout en bout (sans tamponnement)
curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'
Si vous êtes derrière une authentification de base :
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}'
-
Vérification de l’interface utilisateur du navigateur
- Chargez votre interface de chat et déclenchez une réponse.
- Si l’UI utilise WebSockets, confirmez que vous ne voyez pas d’erreurs 400 ou 426 et que la connexion reste ouverte pendant la génération.
Si la sortie curl n’apparaît qu’à la fin, il s’agit presque toujours d’un tamponnement au niveau du proxy. Révisez proxy_buffering off dans Nginx, et envisagez de forcer l’écoulement à faible latence dans Caddy pour le bloc de site Ollama.