Caddy または Nginx をリバースプロキシとして使用し、HTTPS ストリーミングを介して Ollama にアクセスする設定

ストリーミングレスポンスを断絶させずに HTTPS で Ollama を利用する。

目次

リバースプロキシの背後に Ollama を配置することは、HTTPS を有効にし、オプションのアクセス制御を実装し、予測可能なストリーミング動作を実現するための最もシンプルな方法です。

本記事では、Ollama API への Caddy と Nginx を使用したイングラウンド(Ingress)について解説し、クライアント側のコードについては扱いません。

ollama behind proxy

すでに 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、アップグレード)については、 Docker Compose による GPU と永続モデルストレージ付き Ollama をご覧ください。

ポート 11434 を公開するのではなく、Ollama をプロキシするべき理由

Ollama はまずローカルで動作するように設計されています。デフォルトでは、ポート 11434 にローカルホスト(localhost)でバインドされるため、開発者ワークステーションとしては最適ですが、生ポートがインターネット向けではないという明示的なヒントでもあります。

私はポート 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 (ollama serve on 127.0.0.1:11434)

この構成を最も良い意味で「地味」に保つための実践的なルールが 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」です。一般的な失敗モードは暗号化そのものではなく、配管(plumbing)の問題です:

  • HTTP-01 チャレンジのためにポート 80 が到達可能ではない。
  • 証明書がコンテナ内に保存されているが、永続化されていない。
  • 繰り返し新しいインストールやテストデプロイを行う際のレート制限。

長寿命のサービスにとって重要な微妙な点は、証明書の有効期限が設計上短いということです。更新は年次のカレンダーイベントではなく、バックグラウンドの自動化要件として扱うべきです。

認証、悪用制御、および検証

これが、インターネット向け LLM エンドポイントをプロフェッショナルに感じさせる部分です。

認証オプション:単純から洗練まで

プロキシでの Basic Auth は単純ですが、プライベートエンドポイントには驚くほど効果的です。また、HTTP リクエストと WebSocket のアップグレードの両方に簡単に適用できます。

ブラウザフレンドリーなログインフローを希望する場合、forward_authauth_request が一般的なパターンです。プロキシはステートレスなままにし、認証ゲートウェイがセッションと MFA を管理します。トレードオフは、動くパーツが増えることです。

すでに Open WebUI を実行している場合、そのアプリレベルの認証に依存し、Ollama 自体をプライベートに保つこともできます。その場合、プロキシは Ollama 自体ではなく、Open WebUI を保護します。

パブリックアクセスを全く必要としない場合、ネットワークのみによるアプローチの方がクリーンかもしれません。例えば、Tailscale Serve を使用すると、ルーターでインバウンドポートを開けずに、tailnet 内のローカルサービスを公開できます。

高コスト API 向けの悪用防止の基礎

Ollama は強力なローカル API であり、その範囲は生成を超えています。チャット、埋め込み、モデルのリスト、バージョンチェックなどのエンドポイントがあります。API 全体を敏感な情報として扱ってください。

公式 API リファレンス(エンドポイントとストリーミング): https://docs.ollama.com/api

プロキシレイヤーでは、初日の痛みを減らすための 3 つの低労力制御があります:

  • 生成エンドポイントにおける IP 単位のレート制限。
  • 少数のクライアントがすべてを開いたままにするのを防ぐ接続制限。
  • 一般的な Web デフォルトではなく、モデルとハードウェアの現実に合わせて保守的なタイムアウト。

Ollama レイヤーでは、503 エラーでオーバーロードを拒否することもでき、キューイング用のサーバー側設定もあります。プロキシのレート制限は、そこまで到達する頻度を減らします。

検証チェックリスト

ストリーミング API に使用するのと同じチェックを行ってください。

  1. 基本接続性と TLS

    • curl -sS https://ollama.example.com/api/version
    • curl -sS https://ollama.example.com/api/tags | head
  2. ストリーミングの端から端までの動作確認(バッファリングなし)

    • 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}'
  3. ブラウザ UI の健全性チェック

    • チャット UI を読み込み、レスポンスをトリガーします。
    • UI が WebSocket を使用している場合、400 または 426 エラーが表示されず、生成中も接続が開いていることを確認します。

curl の出力が最後にのみ表示される場合、それはほぼ間違いなくプロキシでのバッファリングが原因です。Nginx の proxy_buffering off を再確認し、Caddy の Ollama サイトブロックで低レイテンシフラッシュを強制することを検討してください。