自己ホスト型 LLM API ゲートウェイ:アーキテクチャと運用
Docker Compose、マルチプロバイダチャネル、スコープ付きキー、利用ログ、OpenAI 互換エンドポイントを備えた LLM API ゲートウェイを自己ホストします。
自己ホスト型 LLM API ゲートウェイとは、自社ネットワークまたはクラウドアカウントで運用するソフトウェアです。OpenAI 互換リクエストを受け付け、呼び出し元を認証し、一つ以上の上流モデルプロバイダへトラフィックをルーティングし、運用とコスト管理のために利用状況を記録します。単純なリバースプロキシとは異なり、これはコントロールプレーンです。キー、モデル別名、チャネル資格情報、クォータ、リクエスト履歴がリクエスト経路と並んで存在します。この記事では、自己ホストが妥当な状況、本リポジトリのような Go ベースのゲートウェイで想定されるアーキテクチャ、モデルアクセスを所有者不在のブラックボックスにしない運用方法を説明します。
薄い中継とコントロールプレーンのどちらにするかをまだ検討している場合は、先に LLM プロキシと AI ゲートウェイ を参照してください。このページでは、ゲートウェイの責務が必要だと判断済みで、デプロイ可能な基準構成を求めていることを前提とします。
自己ホストを標準選択にすべき状況
次の条件のうち少なくとも二つに該当する場合は、ゲートウェイの自己ホストを検討してください。
- プロバイダ API キーをすべてのアプリケーション環境へ配布できない
- 複数の製品またはチームが、異なる予算のもとでモデルアクセスを共有する
- 自社の保持境界内にリクエスト単位のログが必要である
- データ経路または調達規則により、自社運用のインフラが望ましい
- クライアントを書き換えずにマルチプロバイダルーティングを行いたい
- SaaS ゲートウェイの制約(データ所在地、ネットワーク出口、変更管理)が要件に合わない
一つの試作だけが一つのキーと一つのモデルを使い、監査要件もない場合、自己ホストは標準選択として不適切です。その場合は、コントロールプレーンの必要性が生じるまで、プロバイダを直接呼び出すか薄いプロキシを使用してください。
参照アーキテクチャ
Clients (apps, agents, eval jobs)
|
| HTTPS + Bearer gateway key
v
Self-hosted AI gateway
- OpenAI-compatible API (/v1/chat/completions, /v1/responses, ...)
- Admin API for users, tokens, channels
- Usage logs, dashboard, pricing context
|
+--> Channel: OpenAI
+--> Channel: Anthropic / Claude (native Messages adaptation)
+--> Channel: Gemini
+--> Channel: Azure / Bedrock / others
|
v
Your datastore (SQLite / MySQL / PostgreSQL)
optional Redis for cache and rate limiting
クライアントは OpenAI SDK または生の HTTP を使い続けます。上流の多様性は設定であり、プロバイダごとに新しい SDK を導入することではありません。これは OpenAI 互換 API ゲートウェイ と同じ価値を持ちますが、稼働率とバックアップを自ら所有する必要があります。
本リポジトリ型ゲートウェイに通常含まれるもの
本プロジェクトは、自己ホスト可能な Go ゲートウェイ兼 AI 資産管理システムです。計画時に重要となる、リポジトリから確認できる機能は次のとおりです。
- チャットと関連サーフェス向けの OpenAI 互換リレーエンドポイント
- マルチプロバイダのチャネル設定
- スコープ付きアクセスのためのユーザーおよびトークン管理
- 利用ログと運用ダッシュボード
- サービスに組み込まれた Web 管理 UI
- 小規模デプロイ向け SQLite、および永続的なマルチユーザー本番環境向け MySQL または PostgreSQL
- 公開イメージ
calciumion/new-apiを利用する Docker ベースのデプロイ経路
コンプライアンス認証や、明記されていない SLA を創作してはいけません。関係者へ約束する前に、実際に動かすバージョンの UI と API で必要な機能を検証してください。
検証済みの最小 Docker 構成
本リポジトリには、PostgreSQL と Redis とともにゲートウェイを起動する実際の docker-compose.yml が含まれています。複数ユーザー向けステージングでは、これを出発点にすることを推奨します。プロジェクト README に記載された最短手順は次のとおりです。
docker pull calciumion/new-api:latest
# from a checkout that includes docker-compose.yml
docker compose up -d
# gateway listens on http://localhost:3000 by default
中核サービスの構成は次のようになります(リポジトリの compose ファイルから抜粋。Redis/Postgres サービス、ヘルスチェック、コメントを含む完全なファイルはそのまま使用してください)。
services:
new-api:
image: calciumion/new-api:latest
container_name: new-api
restart: always
command: --log-dir /app/logs
ports:
- "3000:3000"
volumes:
- ./data:/data
- ./logs:/app/logs
environment:
# Change passwords before any shared or production use.
- SQL_DSN=postgresql://root:123456@postgres:5432/new-api
- REDIS_CONN_STRING=redis://:123456@redis:6379
- TZ=Asia/Shanghai
- ERROR_LOG_ENABLED=true
- BATCH_UPDATE_ENABLED=true
- NODE_NAME=new-api-node-1
depends_on:
- redis
- postgres
この例を現実に即したものとして扱うための運用上の注意点です。
- compose のデフォルトパスワード(
123456)はローカル起動専用です。共有環境へ移す前に必ず変更してください。 - 規制対象環境では、ドキュメントで使用する可変の
:latestタグではなく、固定したイメージ digest を優先してください。 - 単一ノードの SQLite 実験については、README に
/dataボリュームをマウントし、SQL_DSNを指定せずにコンテナを動かす方法も記載されています。これは小規模構成向けであり、複数ライターを持つ本番環境向けではありません。 - TLS 終端は入口(nginx、Caddy、クラウドロードバランサー、Traefik)に配置してください。追加のアクセス制御なしで管理 UI のパスを公開インターネットへ露出してはいけません。
- プロバイダ API キーは初回ログイン後のチャネル設定またはシークレットマネージャーへ保存し、git には入れないでください。
エアギャップ環境のレジストリや独自オーケストレーションのために Docker Compose をそのまま使えない場合も、このスニペットは任意の疑似コードではなく、変換対象となる検証済み基準として扱ってください。上記のイメージ名、ポート、ボリューム、SQL_DSN 変数は、本リポジトリで公開されているデプロイドキュメントと一致します。
最初の 1 週間の設定チェックリスト
1. ID とキー
- 強力な認証を設定した管理者ユーザーを作成する
- サービスごとに、必要最小限のモデルスコープを持つトークンを発行する
- ステージングと本番のキーを分離する
- ローテーションの担当者を文書化する
2. チャネル
管理 UI のチャネル設定では、次を行います。
- 上流資格情報の境界ごとに一つのチャネルを作成する
- Azure またはリージョン固有エンドポイントには明示的なベース URL を設定する
- 資格情報を変更した後にヘルスチェックまたは手動スモークテストを実行する
- 相互に信頼できないテナント間で、制限のない単一の上流キーを共有しない
3. カタログと価格情報
- アプリケーションが依存する安定したモデル別名(
claude-sonnet、gemini-flash、gpt-...)を公開する - 別名を現在の上流 ID に対応付ける(例えば切り替え時点でベンダーが掲載する Claude Sonnet 5 / Opus 4.8 および Gemini 3.5 Flash クラスのモデル)
- デフォルト別名を変更したときは価格情報を見直す
4. 可観測性
- 課金対象ルートの利用ログを有効にする
- ログの保持期間とエクスポート経路を確認する
- CPU だけでなく、エラー率と支出速度にもアラートを設定する
5. バックアップ
- データベースバックアップ(PostgreSQL/MySQL の dump またはボリュームスナップショット)を自動化する
- 最初の実障害が起きる前に、空のホストでリストアをテストする
- バックアップ暗号化キーをゲートウェイコンテナの外に保管する
自己ホスト型コントロールプレーンのセキュリティモデル
設計時に想定すべき脅威
- プロバイダ予算を消費できるゲートウェイキーの窃取
- 公開インターネットへの管理 UI の露出
- 顧客の秘密を含むプロンプトログやツールログ
- オペレーターがチャネルを内部メタデータエンドポイントへ向けられる場合の SSRF 型のチャネルベース URL
- クラスタで
SESSION_SECRETがデフォルトのままの場合に起こる、複数ノード間のセッション固定
実際に効果のある制御
- エッジでの TLS と、非公開の管理アクセス(VPN、SSO、IP 許可リスト)
- アプリケーションごとの固有キーと、バッチキーに対するモデル許可リスト
- プロバイダの秘密情報をゲートウェイだけに保持する
- ツールまたは長いコンテキストを実行できるすべてのキーにクォータを設定する
- 利用ログのエクスポートにマスキングポリシーを適用する
- 複数ノード構成では
SESSION_SECRETを設定する(リポジトリ内の compose コメントを参照)
エージェントがツールを自動呼び出しできる場合は、OWASP LLM Applications Top 10 を確認してください。自己ホストにしても過度な代理権のリスクはなくなりません。制御を適用する場所が変わるだけです。
設定としてのルーティングポリシー
ルーティングポリシーは設定として記述します。
- 製品ごとのデフォルトモデル別名
- 一時的な上流エラーに対するバックアップ別名
- 規制対象または評価結果に敏感なフロー向けの固定別名
- キーが決してアクセスしてはいけないモデルの明示的な拒否
ストリーム途中の障害を単純に再試行しないよう、ルーティングには LLM API フェイルオーバー戦略 を組み合わせてください。ツールエージェントでは、プロバイダ横断のポータブルツール呼び出し のようにスキーマをポータブルに保ちます。
容量、データベース、Redis
| 規模 | データベース | 注意点 |
|---|---|---|
| 個人 / 小規模チーム | SQLite | 単純で、永続ボリュームをマウントする |
| 複数チームの本番環境 | MySQL ≥ 5.7.8 または PostgreSQL ≥ 9.6 | 並行性と運用ツールに優れる |
| 高負荷のレート制限 / キャッシュ経路 | Redis(任意) | プロセス内の制限では不足する場合に使用する |
CPU とメモリは、アイドル状態の管理 UI ではなく同時ストリーム数を基準に見積もってください。ストリーミング応答は接続を開いたままにするため、クライアントがストリーミングを使う場合は負荷テストに SSE 型トラフィックを含めます。
アップグレードと変更管理
- チャネルと課金に関する変更のリリースノートを読む。
- 本番に近いチャネル設定でステージングへデプロイする。
/v1/chat/completionsと、使用しているすべての/v1/responsesに対して curl スモークテストを実行する。- カナリーキーでログ取り込みとウォレット / クォータの動作を検証する。
- ロールバック用に既知の以前のイメージを保持してロールフォワードする。
- アップグレード後、上流の名称変更に対してモデル別名を再確認する。
データベースマイグレーション、プロバイダ資格情報のローテーション、ルーティングポリシーの変更を、同じ無人作業時間帯にまとめてはいけません。
デプロイ後に毎回行うスモークテスト
curl -sS https://gateway.example.com/v1/models \
-H "Authorization: Bearer $GATEWAY_API_KEY" | head
curl -sS https://gateway.example.com/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1-mini",
"messages": [{"role": "user", "content": "ping"}],
"max_tokens": 16
}'
対象チャネルに含まれる場合は、Claude の別名を一つ(例えば claude-sonnet → 現在の Claude ID)、Gemini の別名を一つ(gemini-flash → gemini-3.5-flash または後継モデル)追加してください。利用ログへの記録を確認するまで、デプロイが正常だと判断してはいけません。
自己ホストを維持しながらコストを制御する
自己ホストは無制限という意味ではありません。次を設定してください。
- キー単位およびグループ単位のクォータ
- バッチキーによるフラッグシップモデルの使用を防ぐモデル許可リスト
- ログのエクスポートまたはダッシュボード確認を利用した支出速度アラート
- 評価ジョブではデフォルトで安価なモデルを使用する
デフォルト別名を変更したときは、公開されている 価格情報 を確認してください。コストに関する質問へ答えられない自己ホスト型ゲートウェイは、共有の負債になります。
マネージドホスティングを選ぶべき状況
次の場合は、マネージドまたはハイブリッド構成を維持してください。
- tier-0 の依存サービスに対するオンコール体制がない
- バックアップとリストアの責務を果たせない
- 調達方針がベンダー運用のコントロールプレーンを優先する
- チームが必要としているのは単一プロバイダのシークレット中継だけである
どちらの場合でも、アプリケーションクライアントは OpenAI 互換のまま維持できます。ホスティング方式の変更によってクライアントを書き換えるべきではありません。
公式資料とプロジェクト資料
- プロジェクト README のデプロイ節(
docker pull calciumion/new-api:latest、docker-compose.yml) - OWASP LLM Applications Top 10
- OpenAI API リファレンス
- Docker ドキュメント
最終確認: 2026-07-15。実際にデプロイするバージョンに対して、イメージタグ、環境変数、UI パスを検証してください。
よくある質問
自己ホスト型 LLM ゲートウェイは、モデル自体を自己ホストすることと同じですか?
いいえ。多くの自己ホスト型ゲートウェイは、引き続きホスト型プロバイダ API を呼び出します。自己ホストするのは認証、ルーティング、ログからなるコントロールプレーンであり、必ずしもモデルの重みではありません。オープンウェイトモデルの自己ホストには、別途 GPU スタックが必要です。
SQLite から始めて、後から PostgreSQL へ移行できますか?
多くのデプロイでは可能ですが、障害対応中にロック競合を発見するのではなく、移行を事前に計画してください。小規模構成では SQLite を使用し、同時書き込み数やバックアップツールの要件が高まった時点で移行します。
最小限の安全な構成は何ですか?
エッジでの TLS、非公開の管理アクセス、アプリケーションごとの固有キー、ゲートウェイだけに保持するプロバイダの秘密情報、有効化された利用ログ、ツールまたは長いコンテキストを実行できるすべてのキーへのクォータです。
単一障害点になることを避けるにはどうすればよいですか?
稼働率が重要な場合は、ロードバランサーの背後で少なくとも二つのアプリインスタンスを動かし、外部データベースを使用し、リストアをテストし、チャネルのフェイルオーバーを文書化してください。ゲートウェイはプロバイダ障害の影響範囲を縮小すべきであり、より深刻な単一障害点を作るべきではありません。
新しいクライアントはどのエンドポイントを使用すべきですか?
幅広いクライアント対応のため、ゲートウェイの OpenAI 互換 /v1 ルートと /v1/chat/completions を優先してください。製品が意図的に /v1/responses に依存し、ゲートウェイのバージョンが必要なワークフローをサポートする場合に限って /v1/responses を採用します。
ステージングへの切り替え
リポジトリの compose ファイル(または同等のイメージと SQL_DSN)でステージングゲートウェイをデプロイし、一つの非クリティカルなサービスへスコープ付きキーを発行します。二つ目のプロバイダまたは本番トラフィックを受け入れる前に、chat completions、利用ログ、バックアップのリストアを検証してください。最初のカナリーが正常になった後は、チャネル設定、モデルカタログ、利用履歴を日々の運用ループとして使用します。