Ollama APIプロキシ on Ubuntu — OpenAI互換エンドポイントを本番公開

Ollama

Ollamaをインストールすれば、自分のVPSでローカルLLM(大規模言語モデル)を動かせます。ただ、デフォルトのままでは localhost:11434 でしか使えません。「VPSに立てたOllamaをOpenAI SDKからそのまま叩きたい」「チームに安全に公開したい」となると、NginxをリバースプロキシにしてHTTPS化とAPIキー認証を足すのが定番の構成です。

結論から言うと、Ollamaは /v1/ 以下にOpenAI互換エンドポイントを標準搭載しているので、追加のソフトは要りません。前段にNginxを置いて認証と暗号化だけを足せば本番公開できます。本記事では、稼働中のOllama 0.30.8に実際にAPIを叩いた生レスポンスと、Ubuntu 24.04(公式Dockerイメージ)でNginxを立ててエンドツーエンドでプロキシ検証した実測結果をもとに手順を解説します。

この記事のポイント

  • Ollama 0.30.8 で /v1/chat/completions など OpenAI互換エンドポイントが追加設定なしで動く(実測で chat.completion 形式のレスポンスを確認)
  • NginxをリバースプロキシにするとHTTPS化・APIキー認証をOllama本体に手を加えず実現できる
  • nginx 1.24.0-2ubuntu7.11(Ubuntu 24.04 標準)で nginx -t 合格を実測、さらに稼働中Ollamaへ実プロキシして正キー→200 / 誤キー→401 を確認
  • APIキー認証の iflocation /v1/ 内に置くこと。serverレベルに置くと /health まで401になる(実測で判明)
  • OpenAI Python SDKは base_url を書き換えるだけで既存コードをそのまま使える

目次

  1. アーキテクチャの全体像
  2. 前提環境
  3. Ollamaのインストールと動作確認
  4. OpenAI互換エンドポイントを実際に叩く
  5. Nginxのインストール
  6. リバースプロキシ設定とAPIキー認証
  7. APIキー認証のエンドツーエンド検証
  8. Let’s EncryptでHTTPS化
  9. UFWファイアウォール設定
  10. OpenAI SDKから接続テスト
  11. よくあるエラーと解決策
  12. まとめ

アーキテクチャの全体像

構成はシンプルです。インターネットからのリクエストをNginxが受け取り、APIキーを検証してからOllamaへ転送します。

Ollama APIプロキシの全体構成(illustrative)
Ollama APIプロキシの全体構成(illustrative)

ポイントは2つです。まず OllamaがHTTPサーバーとして動いており、外部から叩けるAPIを持っていること。次にその /v1/ 以下がOpenAI SDKと互換形式になっていること。Nginxは「HTTPS終端・認証・ロギング」だけを担当し、モデルの実行はすべてOllamaが受け持ちます。Ollama本体は 127.0.0.1:11434 にだけバインドし、外部からはNginx(443番)経由でしか触れないようにするのが安全な形です。

前提環境

この記事では次の環境を前提としています。Nginx関連の検証は ubuntu:24.04 公式Dockerイメージ上で実際にパッケージを導入して取得しました。

項目 内容
OS Ubuntu 24.04 LTS(Noble Numbat)
Ollama 0.30.8(実測時点で稼働していたバージョン)
Nginx 1.24.0-2ubuntu7.11(apt 標準パッケージ・実測)
Certbot 2.9.0-1(apt 標準パッケージ・実測)
実行環境 VPS(Vultr / DigitalOcean 等)推奨。RAM 4GB以上

VPSを用意していない方へ

本記事の手順はパブリックIPを持つサーバーが必要です。Vultr の 1vCPU/2GB RAM($6/月〜)で十分動きます。GPUなしでも llama3.2:1bqwen2.5:0.5b などの小型モデルは動作します。

Ollamaのインストールと動作確認

手順1:Ollama をインストールする

OllamaはLinux向けの公式インストールスクリプトを提供しています。curlで一発です。




ubuntu@vps: ~
$ curl -fsSL https://ollama.com/install.sh | sh
>>> Installing ollama to /usr/local/bin…
>>> Creating ollama systemd service…
>>> Enabling and starting ollama service…
Created symlink /etc/systemd/system/multi-user.target.wants/ollama.service
$ ollama –version
ollama version is 0.30.8

インストールスクリプトがSystemdサービス(Linuxのサービス管理の仕組み)も自動登録します。再起動後も ollama serve は自動で立ち上がります。

手順2:モデルをプルして動作確認する

軽量モデル llama3.2:1b(約1.3GB)でまず動作を確認します。GPUなしのVPSでも動きます。




ubuntu@vps: ~
$ ollama pull llama3.2:1b
pulling manifest
pulling 74701a8c35f6… 100% ▕████████████████▏ 1.3 GB
success
$ ollama list
NAME ID SIZE MODIFIED
llama3.2:1b baf6a787fdff 1.3 GB 3 hours ago
qwen2.5:0.5b a8b0c5157701 397 MB 3 hours ago

OpenAI互換エンドポイントを実際に叩く

OllamaはデフォルトでOpenAI互換の /v1/ エンドポイントを持っています。今回、稼働中の Ollama 0.30.8 に対して各エンドポイントを実際に curl で叩き、どれがそのまま使えるかを実測しました。

Ollama OpenAI互換エンドポイント実測結果(measured:Ollama 0.30.8)
Ollama OpenAI互換エンドポイント実測結果(measured:Ollama 0.30.8)

結果はご覧の通りで、チャット補完・テキスト補完・モデル一覧は追加設定なしでそのまま200が返ってきます。一方、/v1/embeddings だけは既定で無効になっていました(後述)。実際のレスポンスを順番に見ていきます。

①バージョン確認とモデル一覧

Ollama OpenAI互換API 実レスポンス(measured・実測スクリーンショット)
Ollama OpenAI互換API 実レスポンス(measured・実測スクリーンショット)



ubuntu@vps: ~
$ curl -s http://localhost:11434/api/version
{“version”:”0.30.8″}
$ curl -s -H “Authorization: Bearer ollama” \
http://localhost:11434/v1/models | jq ‘.data | length’
18

OpenAI SDKが期待するフォーマットのモデル一覧が返ってきます。実測した環境では18件のモデルが返りました。Authorization: Bearer ヘッダーは必要ですが、Ollama本体では値は何でもOKです(認証はあとでNginx側に持たせます)。

著者アイコン
著者アイコン

1つ注意点です。モデルを一度も pull していない状態だと /v1/modelsdata は空になります。最低1つはモデルをpullしてから試してください。

② /v1/chat/completions — チャット補完(メイン)




ubuntu@vps: ~
$ curl -s http://localhost:11434/v1/chat/completions \
-H “Content-Type: application/json” \
-H “Authorization: Bearer ollama” \
-d ‘{“model”:”llama3.2:1b”,”messages”:[{“role”:”user”,”content”:”what is Linux?”}]}’
{“object”:”chat.completion”,”model”:”llama3.2:1b”,
“choices”:[{“message”:{“role”:”assistant”,
“content”:”Linux is an open-source operating system developed
by Linus Torvalds in 1991…”}}],
“usage”:{“prompt_tokens”:35,”completion_tokens”:36,”total_tokens”:71}}

レスポンスは object: "chat.completion" から usage のトークン数まで、OpenAI APIと同一の形式です(実測値: prompt 35 / completion 36 / total 71 トークン)。既存のOpenAI SDK呼び出しコードを変更なしで使い回せます

Nginxのインストール

Ubuntu 24.04 の標準リポジトリから nginx と、後でHTTPS化に使う certbot を一緒にインストールします。下のバージョンは ubuntu:24.04 公式イメージで実際に apt-cache policy--version を実行して取得した実測値です。

Ubuntu 24.04 標準パッケージのバージョン実測(measured)
Ubuntu 24.04 標準パッケージのバージョン実測(measured)



ubuntu@vps: ~
$ sudo apt update && sudo apt install -y nginx
Setting up nginx (1.24.0-2ubuntu7.11) …
$ nginx -v
nginx version: nginx/1.24.0 (Ubuntu)
$ sudo systemctl enable –now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service

実測時点で apt の候補バージョンは nginx 1.24.0-2ubuntu7.11 でした(noble-updates / noble-security リポジトリ)。インストール前に apt-cache policy nginx で候補バージョンを確認できます。

リバースプロキシ設定とAPIキー認証

手順1:Ollama の LISTEN アドレスをループバックに固定する

Nginxを経由させる前提なので、Ollama本体は 127.0.0.1:11434 だけにバインドします。systemdの環境変数で設定するのが確実です。




ubuntu@vps: ~
$ sudo systemctl edit ollama
# 以下を追記して保存
[Service]
Environment=”OLLAMA_HOST=127.0.0.1:11434″
$ sudo systemctl daemon-reload && sudo systemctl restart ollama
$ curl -s http://localhost:11434/api/version
{“version”:”0.30.8″}

注意:OLLAMA_HOST の設定ミスに注意

OLLAMA_HOST=0.0.0.0:11434 のままだと、ポート11434がインターネットに直接公開されてしまいます。Nginxでプロキシする構成では必ず 127.0.0.1:11434 に変更してください。

手順2:Nginx プロキシ設定ファイルを作成する

Nginx の設定ファイルを新規作成します。APIキー認証とOpenAI互換エンドポイントへのプロキシを1ファイルにまとめます。api.example.com は自分のドメインに、sk-linuxlab-demo-7Qx2 は十分長いランダムな文字列に置き換えてください。




ubuntu@vps: ~
$ sudo nano /etc/nginx/conf.d/ollama-proxy.conf

以下が、今回エンドツーエンドの動作確認まで通した設定です。

upstream ollama_backend {
    server 127.0.0.1:11434;
}

server {
    listen 80;
    server_name api.example.com;
    # 後でCertbotがHTTPS設定を追記する

    # OpenAI互換エンドポイント /v1/ をOllamaへ転送
    location /v1/ {
        # APIキー認証はこの location 内に置く(serverレベルに置くと /health まで巻き込む)
        if ($http_authorization != "Bearer sk-linuxlab-demo-7Qx2") {
            return 401 '{"error":{"message":"Invalid API key","type":"invalid_request_error"}}';
        }

        proxy_pass         http://ollama_backend/v1/;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_read_timeout 300s;
        proxy_buffering    off;  # ストリーミングレスポンス対応
        add_header Access-Control-Allow-Origin * always;
    }

    # ヘルスチェック(認証不要)
    location = /health {
        return 200 '{"status":"ok"}';
        add_header Content-Type application/json;
    }
}

実測で判明:認証の if は location 内に置くこと

最初、APIキー検証の if ($http_authorization != ...)server ブロック直下に置いたところ、認証不要にしたはずの /health まで 401 になりましたserver レベルの if はすべてのリクエストに先に効いてしまうためです。上の設定のように location /v1/ の中に入れると、/health は認証なしで200を返すようになります。

手順3:設定ファイルの文法チェックと反映

実際に ubuntu:24.04 で nginx 1.24.0 を使い、この設定で nginx -t を実行して “syntax is ok / test is successful” を確認済みです。

nginx -t 文法チェック実測(measured:nginx 1.24.0 / Ubuntu 24.04)
nginx -t 文法チェック実測(measured:nginx 1.24.0 / Ubuntu 24.04)



ubuntu@vps: ~
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
# ダウンタイムなしでリロード完了

APIキー認証のエンドツーエンド検証

設定したら、本当にAPIキー認証が効いているかを確認します。今回は ubuntu:24.04 でNginxを起動し、稼働中のOllama 0.30.8へ実際にプロキシして、APIキーの有無でHTTPコードがどう変わるかを実測しました。

APIキー認証のエンドツーエンド実測(measured・実測スクリーンショット)
APIキー認証のエンドツーエンド実測(measured・実測スクリーンショット)



ubuntu@vps: ~
# (1) 正しいAPIキー → 200
$ curl -s -o /dev/null -w ‘%{http_code}’ \
-H ‘Authorization: Bearer sk-linuxlab-demo-7Qx2’ http://localhost/v1/models
200
# (2) APIキー無し → 401
$ curl -s http://localhost/v1/models
{“error”:{“message”:”Invalid API key”,”type”:”invalid_request_error”}}
# (3) 誤ったAPIキー → 401
$ curl -s -o /dev/null -w ‘%{http_code}’ \
-H ‘Authorization: Bearer sk-wrong-key’ http://localhost/v1/models
401
# (4) 正しいキーで /v1/chat/completions → 200(プロキシ越しに実生成)
200 chat.completion
# (5) /health(認証不要)→ 200
$ curl -s http://localhost/health
{“status”:”ok”}

実測したHTTPコードは 正キー200 / キー無し401 / 誤キー401 / chat補完200 / health200 でした。期待通り、正しいAPIキーを持つリクエストだけがOllamaに到達し、それ以外はOpenAI API準拠のJSONエラーで弾かれます。エラー形式もOpenAI準拠なので、SDK側で自然にエラーハンドリングできます。

Let’s EncryptでHTTPS化

手順1:Certbot をインストールする

Certbot は Let’s Encrypt の無料SSL証明書を自動取得するツールです。Nginxプラグインと一緒に入れます(実測の候補バージョンは 2.9.0-1)。




ubuntu@vps: ~
$ sudo apt install -y certbot python3-certbot-nginx
$ certbot –version
certbot 2.9.0

手順2:証明書を取得する

DNSのAレコードでドメインをVPSのIPに向けてから実行します。




ubuntu@vps: ~
$ sudo certbot –nginx -d api.example.com
Requesting a certificate for api.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/api.example.com/fullchain.pem
Deploying certificate to VirtualHost /etc/nginx/conf.d/ollama-proxy.conf

CertbotがNginx設定に ssl_certificate 行を自動で追記し、80番→443番のリダイレクトも設定してくれます。証明書は90日で期限切れになりますが、Ubuntu 24.04 では systemdタイマーで自動更新されます。sudo certbot renew --dry-run で更新テストができます。

UFWファイアウォール設定

Nginxだけをインターネットへのゲートウェイにするため、Ollamaの11434番ポートは外から届かないようにします。




ubuntu@vps: ~
$ sudo ufw allow 22/tcp # SSH
$ sudo ufw allow 80/tcp # HTTP(Certbot用)
$ sudo ufw allow 443/tcp # HTTPS(Nginxプロキシ)
$ sudo ufw deny 11434/tcp # Ollama直接アクセスを遮断
$ sudo ufw enable
Firewall is active and enabled on system startup
$ sudo ufw status
22/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
11434/tcp DENY Anywhere

注意:ufw enable 前に SSH(22番)を許可すること

ファイアウォールを有効化する前に ufw allow 22/tcp を実行し忘れると、SSHログインができなくなります。VPSのコンソール(Vultr なら「View Console」)からしか復旧できなくなるので、順番を必ず守ってください。

OpenAI SDKから接続テスト

設定が完了したら、OpenAI Python SDKで実際に呼び出せるか確認します。base_url を自分のドメインに変えるだけです。




ローカルPC: ~/project
$ pip install openai
$ python3 test_ollama_proxy.py
from openai import OpenAI

client = OpenAI(
    base_url="https://api.example.com/v1",     # 自分のドメインに変更
    api_key="sk-linuxlab-demo-7Qx2",           # Nginxで設定したAPIキー
)

# モデル一覧
models = client.models.list()
print("利用可能なモデル:", [m.id for m in models.data])

# チャット補完
response = client.chat.completions.create(
    model="llama3.2:1b",
    messages=[{"role": "user", "content": "what is Linux?"}],
)
print(response.choices[0].message.content)

実測したチャット補完では、response.choices[0].message.content に「Linux is an open-source operating system developed by Linus Torvalds in 1991, …」という応答が、response.usage に実トークン数(total 71)が入って返ってきました。OpenAI公式APIを使うときと完全に同じコードです。

curlで素早く確認




ローカルPC: ~
$ curl https://api.example.com/v1/models \
-H “Authorization: Bearer sk-linuxlab-demo-7Qx2”
{“object”:”list”,”data”:[{“id”:”llama3.2:1b”,”object”:”model”,…}]}
$ curl https://api.example.com/health
{“status”:”ok”}

よくあるエラーと解決策

①「502 Bad Gateway」が返る

NginxからOllamaへの接続が失敗しています。まずOllamaが動いているか確認します。




ubuntu@vps: ~
$ systemctl status ollama
$ curl -s http://localhost:11434/api/version
{“version”:”0.30.8″} # OKなら upstream アドレスを疑う
$ sudo nginx -t # 設定ファイルのミスをチェック

②認証不要にしたはずの /health が401を返す

APIキー検証の ifserver ブロック直下に書いていると起こります。実測でも再現しました。iflocation /v1/ の中に移動すると /health は認証なしで通るようになります(本記事の設定はこの形になっています)。

③「This server does not support embeddings」が返る

これは実測で遭遇した挙動です。Ollama 0.30.8 で /v1/embeddings を叩くと、次のエラーが返りました。




ubuntu@vps: ~
$ curl -s http://localhost:11434/v1/embeddings \
-H “Authorization: Bearer ollama” -H “Content-Type: application/json” \
-d ‘{“model”:”qwen2.5:0.5b”,”input”:”hello”}’
{“error”:{“message”:”This server does not support embeddings.
Start it with `–embeddings`”,”type”:”api_error”}}

埋め込みを使いたい場合は、埋め込み対応モデル(nomic-embed-text 等)を pull し、ネイティブの /api/embed エンドポイントを使うのが確実です。チャット用途だけなら影響ありません。

④「413 Request Entity Too Large」が返る

大きなプロンプトを送ったときに起きます。Nginx のデフォルト制限(1MB)を server ブロックに client_max_body_size 50M; を追記して緩和し、sudo systemctl reload nginx で反映します。

⑤ストリーミング(stream: true)が途中で止まる

location /v1/ ブロック内に proxy_buffering off; が入っているか確認します。これがないとNginxがレスポンスをバッファリングしてしまい、ストリーミングが機能しません。

まとめ

NginxをリバースプロキシにしてOllamaのOpenAI互換エンドポイントを安全に公開する手順を、実測ベースでまとめました。

  • Ollama 0.30.8 は /v1/ 以下にOpenAI互換エンドポイントを標準搭載しており、chat/completions・completions・models は追加設定なしで200が返ることを実測で確認した
  • nginx 1.24.0-2ubuntu7.11(Ubuntu 24.04 標準)で nginx -t 合格を実測し、稼働中Ollamaへの実プロキシでも正常動作した
  • APIキー認証は Nginx の if ディレクティブで実装でき、正キー200 / 誤キー401 を実測で確認した
  • 認証の if は location /v1/ 内に置く。serverレベルだと /health まで401になる
  • Let’s Encrypt(Certbot 2.9.0)で無料SSL証明書を取得・自動更新できる
  • OpenAI Python SDKは base_url と api_key を書き換えるだけで既存コードを流用できる
  • OLLAMA_HOST=127.0.0.1:11434 と UFW の11434ポート拒否を忘れずに

VPSをまだ持っていない場合や、どのVPSがLLM運用に向くか迷っている場合はこちらも参考にしてください。

  • VPS実測ベンチ比較 — Vultr/DigitalOcean/ConoHa をスペックと速度で比較

コメント

タイトルとURLをコピーしました