Caddy または Nginx をリバースプロキシとして使用し、HTTPS ストリーミングを有効にした Ollama
ストリーミング応答を破綻させずに HTTPS で Ollama を利用する。
リバースプロキシの背後で Ollama を実行することは、HTTPS、オプションのアクセス制御、予測可能なストリーミング動作を実現する最も簡単な方法です。
本記事では、クライアントコードではなく、Ollama API 向けの Caddy および Nginx イングレスに焦点を当てます。

すでに Python や Go のクライアントで Ollama と通信している場合、この記事はその欠けている部分、つまり同じ API 向けのイグレスとトランスポートについて説明します。
Ollama が vLLM、Docker Model Runner、LocalAI、クラウドホスティングのトレードオフの文脈でどのように位置づけられるかについては、 LLM ホスティング 2026:ローカル、セルフホスト、クラウドインフラの比較 を参照してください。
リクエスト例とクライアントコードについては、 Ollama CLI チートシート を参照してください。
UI やマルチユーザーレイヤーについては、 Open WebUI の概要、クイックスタート、代替案 を参照してください。
セルフホスティングとデータコントロールの大きな視点については、 LLM セルフホスティングと AI 主権 を参照してください。
Docker Compose による再現可能な単一ノードの Ollama サービス(永続ボリューム、OLLAMA_HOST、NVIDIA GPU、アップグレード)については、
GPU と永続モデルストレージを備えた Docker Compose の Ollama を参照してください。
パブリックなインバウンドポートを持たないリモートデバイス(Tailscale、WireGuard、バインディング、ファイアウォール)については、 パブリックポートなしで Tailscale または WireGuard を通じたリモート Ollama アクセス を参照してください。
ポート 11434 を公開するのではなく Ollama をプロキシするべき理由
Ollama は最初にローカルで実行されるように設計されています。デフォルトでは、localhost のポート 11434 にバインドされ、これは開発者のワークステーションには最適ですが、生ポートはインターネット向けではないという明確なヒントでもあります。
私はポート 11434 を内部的な高コストの API として扱います。これがパブリックインターネットから到達可能であれば、誰かが見つけた場合、CPU や GPU の時間を浪費させたり、モデルをプルしてディスクを埋めたり、タイムアウトするまで接続を開き続けることができます。リバースプロキシは魔法のように Ollama を安全にするわけではありませんが、エッジで重要なコントロール(TLS、認証、タイムアウト、レート制限、ログ)を配置する場所を提供します。
これは重要な理由です。ローカルの Ollama API には、組み込みの認証レイヤーが含まれていないためです。これを公開する場合、通常はエッジで認証を追加するか、信頼されたネットワークからのみ到達可能なプライベートなままにします。
2 つ目の理由は UX です。Ollama はデフォルトでレスポンスをストリーミングします。プロキシが誤った場所でバッファリングしたり圧縮したりすると、ストリーミングが壊れたように感じられ、UI は出力なしで「思考中」のように見えます。
最小構成とバインディング戦略
クリーンな最小構成は以下のようになります。
Client (curl, Python, Go, UI)
|
| HTTPS (オプションの Basic Auth または SSO)
v
Reverse proxy (Caddy または Nginx)
|
| HTTP (プライベート LAN、localhost、または Docker ネットワーク)
v
Ollama server (127.0.0.1:11434 での ollama serve)
この構成を最も良い意味で退屈なもの(= 安定したもの)にするための実践的な 2 つのルールがあります。
まず、Ollama をプライベートに保ち、公開をプロキシに任せます。Caddy や Nginx が同じホスト上で実行されている場合、127.0.0.1:11434 にプロキシし、Ollama のバインドアドレスを変更しないでください。プロキシが他の場所(別のホスト、別の VM、またはコンテナネットワーク)で実行される場合、Ollama をパブリック NIC の 0.0.0.0 ではなくプライベートインターフェースにバインドし、ファイアウォールに依存します。
次に、ブラウザが直接 Ollama を呼び出すかどうかを早期に決定します。ブラウザベースのツールが異なるオリジンから Ollama にアクセスする場合、CORS の問題に対処する必要があるかもしれません。すべてがプロキシ経由で 1 つのドメインから提供される場合( sanity のために推奨)、CORS を完全に回避し、Ollama を厳格に保つことができます。
ストリーミングと WebSocket 用のリバースプロキシ設定
Ollama の API は通常の HTTP であり、そのストリーミングは改行区切りの JSON (NDJSON) です。つまり、プロキシが以下の 3 つのことをうまく行えるようにする必要があります。
- ストリーミングレスポンスをバッファリングしないこと。
- モデルが話すのに時間がかかっただけで、長期間のリクエストを殺さないこと。
- UI が WebSocket を使用する場合(いくつかは使用します)、Upgrade を適切に転送すること。
これはシンプルに保つことができます。多くの場合、「正しい WebSocket 処理」とは、アップストリームが今日 WebSocket を使用していなくても、Upgrade 安全な設定を持っていることです。
Caddy Caddyfile 例
Caddy は「設定を少なくし、デフォルトを多くする」オプションです。サイトアドレスにパブリックドメイン名を指定すると、Caddy は通常自動的に証明書を取得し更新します。
最小限のリバースプロキシ、HTTPS、ストリーミング対応設定:
# ollama.example.com A/AAAA -> your proxy host
ollama.example.com {
# エッジでのオプションの Basic Auth。
# パスワードハッシュを生成するには:
# caddy hash-password --algorithm bcrypt
#
# basic_auth {
# alice $2a$12$REDACTED...
# }
reverse_proxy 127.0.0.1:11434 {
# 一部のセットアップでは、アップストリームの Host ヘッダーをピン留めすることを好みます。
# Ollama のドキュメントでも Nginx 向けにこのパターンが示されています。
header_up Host localhost:11434
# ストリーミングやチャットのようなワークロードの場合、低遅延を優先します。
# NDJSON ストリーミングは通常すぐにフラッシュされますが、これを明示的にします。
flush_interval -1
transport http {
# ストリーミングに干渉する可能性があるアップストリームの gzip 交渉を避けます。
compression off
# Ollama にモデルを読み込み、最初のチャンクを生成する時間を与えます。
response_header_timeout 10m
dial_timeout 10s
}
}
}
すでに SSO ゲートウェイ (oauth2-proxy, Authelia, authentik outpost など) を持っている場合、Caddy には意見のある forward auth 指令があります。パターンは「まず認証、次にプロキシ」です。
ollama.example.com {
forward_auth 127.0.0.1:4180 {
uri /oauth2/auth
# 必要に応じて、ゲートウェイが返す識別子ヘッダーをコピーします。
copy_headers X-Auth-Request-User X-Auth-Request-Email Authorization
}
reverse_proxy 127.0.0.1:11434
}
Nginx サーバーブロック例
Nginx はもう少し自由度を与えます。利点は、ノブが明示的で、レート制限や接続制限のプリミティブが組み込まれていることです。足掛かりとなるのはバッファリングです。Nginx はデフォルトでプロキシされたレスポンスをバッファリングしますが、これは NDJSON ストリーミングに対して望ましくないことです。
この例には以下が含まれます:
- HTTP から HTTPS へのリダイレクト
- TLS 証明書パス (Certbot スタイル)
- WebSocket 安全な Upgrade 転送
- ストリーミング対応の proxy_buffering off
- デフォルトの 60 秒よりも長いタイムアウト
# /etc/nginx/conf.d/ollama.conf
# WebSocket 安全な Connection ヘッダー処理
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
# オプションのリクエストレート制限 (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;
# エッジでのオプションの Basic Auth。
# auth_basic "Ollama";
# auth_basic_user_file /etc/nginx/.htpasswd;
location / {
# オプションのレート制限
# limit_req zone=ollama_rate burst=20 nodelay;
proxy_pass http://127.0.0.1:11434;
# localhost へのプロキシ時に Ollama ドキュメントのパターンに一致させます。
proxy_set_header Host localhost:11434;
# WebSocket Upgrade 処理 (未使用の場合でも無害です)。
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# NDJSON ストリーミングのために重要。
proxy_buffering off;
# トークンを待っている間の 60 秒のアイドルタイムアウトを防ぎます。
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Nginx で SSO スタイルのゲートを実現したい場合は、同等のパターンとして auth_request を使用します。Nginx は認証サービスにサブリクエストを送信し、認証が 2xx を返す場合にのみ Ollama にプロキシします。
TLS 自動化と更新の落とし穴
TLS については、運用上の分割はシンプルです。
Caddy では、TLS は通常「リバースプロキシの一部」です。自動 HTTPS はその主要機能の 1 つであり、証明書の発行と更新は Caddy を実行し続けること、DNS が機能すること、ポート 80 と 443 を公開することに結びついています。
Nginx では、TLS は通常「別々の ACME クライアントと Nginx」です。一般的な障害モードは暗号化ではなく、配管です:
- HTTP-01 チャレンジのためにポート 80 が到達不可能であること。
- 証明書がコンテナに保存されているが、永続化されていないこと。
- 繰り返しインストールやテストデプロイ時でのレート制限。
長寿命のサービスにとって重要な微妙な点は、証明書の寿命は設計上短いということです。更新を年次のカレンダーイベントではなく、バックグラウンド自動化要件として扱ってください。
認証、乱用制御、および検証
これは、インターネット対応の LLM エンドポイントにプロフェッショナルな印象を与える部分です。
認証オプション: 直接的な方法からエレガントな方法まで
プロキシでの Basic Auth は直接的ですが、プライベートエンドポイントには驚くほど効果的です。HTTP リクエストと WebSocket アップグレードの両方に簡単に適用できます。
ブラウザフレンドリなログインフローが必要な場合は、forward auth と auth_request が一般的なパターンです。プロキシはステートレスのままとなり、認証ゲートウェイがセッションと MFA を管理します。トレードオフは、動く部品が増えることです。
すでに Open WebUI を実行している場合、そのアプリレベルの認証に頼り、Ollama 自体をプライベートに保つこともできます。その場合、プロキシは Ollama ではなく Open WebUI を保護します。
パブリックアクセスが全く必要ない場合、ネットワークのみでのアプローチがよりクリーンになる可能性があります。例えば、Tailscale Serve を使用すると、ルーターでインバウンドポートを開けることなく、tailnet 内のローカルサービスを提供できます。完全なパターン (WireGuard、VPN インターフェースでの OLLAMA_HOST、ファイアウォールのピン留め、セキュリティチェックリスト) については、パブリックポートなしで Tailscale または WireGuard を通じたリモート Ollama アクセス を参照してください。
高価な API に対する乱用防止の基本
Ollama は強力なローカル API であり、その表面は生成を超えています。チャット、埋め込み、モデル一覧、バージョンチェックのエンドポイントがあります。API 全体を機密として扱ってください。
公式 API リファレンス (エンドポイントとストリーミング): https://docs.ollama.com/api
プロキシレイヤーでは、初日の痛みを減らすための 3 つの低コストコントロールがあります:
- 生成エンドポイントでの IP 別のレート制限。
- 少数のクライアントがすべてを開いたままにするのを防ぐ接続制限。
- 一般的な Web デフォルトではなく、モデルとハードウェアの現実に合わせて保守的なタイムアウト。
Ollama レイヤーでは、503 エラーで過負荷を拒否することもでき、キューイングのためのサーバーサイドのノブがあります。プロキシのレート制限は、そこに到達する頻度を減らします。
検証チェックリスト
ストリーミング API に対して使用するのと同じチェックを使用してください。
-
基本的な接続性と TLS
curl -sS https://ollama.example.com/api/versioncurl -sS https://ollama.example.com/api/tags | head
-
ストリーミングがエンドツーエンドで機能すること (バッファリングなし)
curl -N https://ollama.example.com/api/generate -H "Content-Type: application/json" -d '{"model":"mistral","prompt":"Write 10 words only.","stream":true}'
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}'
-
ブラウザ UI の健全性
- チャット UI を読み込み、レスポンスをトリガーします。
- UI が WebSocket を使用している場合、400 または 426 エラーが見えないこと、および生成中に接続が開いたままになることを確認します。
curl 出力が最後に表示される場合、ほぼ間違いなくプロキシでのバッファリングです。Nginx での proxy_buffering off を再確認し、Caddy の Ollama サイトブロックで低遅延フラッシュを強制することを検討してください。