午前2時、Slackが爆発 — すべては一つの疑問から始まった
その日は金曜日で、チーム全員が社員のAIチャット活用を支援する社内システムの導入を終えたばかりだった。ステージング環境では問題なく動いていた。本番に上げて3時間後、問題が発生し始めた。コンテナが何度もクラッシュし、MongoDBに接続できず、そして最も深刻なこと——ユーザーの会話データがいかなるフィルターも通さずにOpenAIのサーバーへと送られていた。CTOから午前2時17分にメッセージが来た:「今すぐ直せ。」
あのとき初めて、企業にとってAIチャットゲートウェイをセルフホストすることがいかに重要かを痛感した。コストだけの問題ではない——データの管理権、監査ログ、そして特定のプロバイダーに縛られずに複数のAIモデルを統合できる柔軟性が重要なのだ。それ以来、どのチームにAIツールを提案する前でも、必ず一つ聞くようにしている:「あなたの会話データは、誰のサーバーを通っているのか?」
LibreChatは、その後に選んだ解決策だ。Open WebUI(Ollamaのローカルモデルに特化)と異なり、LibreChatはOpenAI、Claude、Gemini、Ollamaを一つのインターフェースで動かすよう設計されている。さらに重要なのは、認証・権限管理・会話管理のシステムが、デモ用ではなく実際に会社全体で使えるレベルで実装されている点だ。
LibreChatとは何か、なぜ他と違うのか
LibreChatは、自分のサーバーで完全に動作するオープンソースのAIチャットインターフェースだ。主なスタック構成は以下の通り:
- Frontend:React + TypeScript、ChatGPTに近い使用感
- Backend:Node.js + Express
- Database:MongoDBで会話履歴とユーザーアカウントを管理
- ファイルストレージ:設定に応じてローカル、S3、Azure Blobに対応
最大の特徴はプリセットシステムだ。各AIエンドポイント(モデル+システムプロンプト+パラメータ)の設定をあらかじめ作っておけば、ユーザーはプリセットを選んで使うだけでいい。チームメンバーそれぞれが異なるシステムプロンプトを設定したり、バラバラなモデルを使ったりする混乱がなくなる——チーム全体で同じベースラインを共有でき、管理がずっと楽になる。
環境の準備
最小要件
- サーバー:2 vCPU、4GB RAM(本番環境は4 vCPU / 8GB推奨)
- Docker Engine 24以上、Docker Compose v2
- ドメイン+SSL——LibreChatは本番モードでHTTPでは動作しない
# 開始前にバージョンを確認する
docker --version # Docker version 24.x.x
docker compose version # Docker Compose version v2.x.x
リポジトリのクローン
git clone https://github.com/danny-avila/LibreChat.git
cd LibreChat
Docker ComposeでLibreChatをデプロイする
ステップ1 — .env設定ファイルの作成
LibreChatは2つのメイン設定ファイルを使用する:環境変数用の.envと、AIエンドポイント用のlibrechat.yamlだ。
# サンプルファイルをコピーする
cp .env.example .env
.envファイルを開き、重要な値を設定する。これは最も見落とされがちなステップであり、後々のほとんどのエラーの原因にもなる:
# MongoDB URI — 付属のMongoDBコンテナを使う場合はそのままでよい
MONGO_URI=mongodb://mongodb:27017/LibreChat
# シークレットキー — 必ずランダムに生成すること、デフォルト値は使用禁止
CREDS_KEY=f34be427ebb29de8d88c107a71546019685ed8b241d927a3ad354e35188a4a # 64 hex chars
CREDS_IV=e2341419ec3dd3d19b13a1a87fafcbfb # 32 hex chars
JWT_SECRET=16f8c0ef4a5d6b3e1f7a9c2d4e6b8f0a2c4e6b8f0a2c4e6b8f0a2c4 # 64 hex chars
JWT_REFRESH_SECRET=eaa5191f2914e082135951f8e6d6fe35ba2e21239aa7b82a3c # 64 hex chars
# ユーザー登録を許可する — アカウントを作り終えたらfalseに設定すること
ALLOW_REGISTRATION=true
# 自分のドメイン
DOMAIN_CLIENT=https://chat.yourdomain.com
DOMAIN_SERVER=https://chat.yourdomain.com
キーの生成にはopensslを使うこと——手入力では必ずパターンが生まれてしまう:
# opensslでランダムなキーを生成する
openssl rand -hex 32 # CREDS_KEY、JWT_SECRET、JWT_REFRESH_SECRET用
openssl rand -hex 16 # CREDS_IV用
ステップ2 — AIエンドポイントの設定(librechat.yaml)
これが最も重要な部分だ——すべてのAIプロバイダーを宣言する場所。サンプルファイルをコピーする:
cp librechat.example.yaml librechat.yaml
librechat.yamlファイルを必要に応じて編集する:
version: 1.1.5
cache: true
endpoints:
openAI:
apiKey: "${OPENAI_API_KEY}"
models:
default: ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo"]
fetch: false
titleConvo: true
titleModel: "gpt-4o-mini"
anthropic:
apiKey: "${ANTHROPIC_API_KEY}"
models:
default: ["claude-opus-4-8", "claude-sonnet-4-6", "claude-haiku-4-5"]
fetch: false
google:
apiKey: "${GOOGLE_API_KEY}"
models:
default: ["gemini-2.0-flash", "gemini-1.5-pro"]
fetch: false
# 必要に応じてローカルのOllamaに接続する
custom:
- name: "Ollama Local"
apiKey: "ollama"
baseURL: "http://host.docker.internal:11434/v1/"
models:
default: ["llama3.1:8b", "qwen2.5:7b"]
fetch: true
titleConvo: false
API keyを.envに追加する:
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=AIza...
ステップ3 — 起動
# すべてのサービスを起動する
docker compose up -d
# ログを監視する — 初回起動時は必須
docker compose logs -f librechat
初回起動時はイメージのpullとMongoDBの初期化に2〜3分かかる。ステータスを確認:
docker compose ps
# 期待される結果:
# NAME STATUS
# LibreChat-LibreChat-1 running (healthy)
# LibreChat-mongodb-1 running (healthy)
ステップ4 — NginxによるリバースProxy設定
LibreChatはポート3080で動作する。SSLを付けて外部に公開するにはNginxが必要だ:
server {
listen 443 ssl http2;
server_name chat.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/chat.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 300s; # 重要: AIのレスポンスに時間がかかる場合がある
proxy_send_timeout 300s;
}
}
proxy_read_timeout 300sには注意が必要だ——デフォルトの60秒のままにしていたため、応答が遅いモデルでタイムアウトが発生し、AIがまだ生成中なのにユーザーにエラーが表示された経験がある。
企業環境向けセキュリティ設定
セットアップ完了後にユーザー登録を無効化する
チームに必要なアカウントを作り終えたら、すぐに公開登録を無効にする。登録ボットにスキャンされ、自分のAPIキーを気づかないうちに使われているサーバーが多い:
# .envファイル内で設定
ALLOW_REGISTRATION=false
# 設定を反映させるためにリスタートする
docker compose restart LibreChat-LibreChat-1
レート制限 — APIキーの枯渇を防ぐ
# .envでメッセージ数を制限する
LIMIT_CONCURRENT_MESSAGES=1
LIMIT_MESSAGE_IP=100 # 15分ごとに100メッセージ/IP
LIMIT_MESSAGE_USER=50 # 15分ごとに50メッセージ/ユーザー
メール認証の有効化(オプション)
# .envでSMTPを設定する
EMAIL_SERVICE=gmail
[email protected]
EMAIL_PASSWORD=app-specific-password
[email protected]
# 登録時にメール認証を要求する
EMAIL_VERIFICATION=true
よくあるエラーの対処法
起動直後にMongoDBのconnection refusedが発生する
このエラーはLibreChatコンテナがMongoDBの初期化完了前に起動するために発生する——healthcheck付きのdepends_onがあっても、まれにレースコンディションが起きる。手早い解決策:
docker compose restart LibreChat-LibreChat-1
「Invalid CREDS_KEY length」エラーでコンテナがクラッシュする
キーの長さが正しくない。CREDS_KEYは正確に64文字の16進数、CREDS_IVは正確に32文字の16進数でなければならない:
# 長さを確認する
echo -n "$CREDS_KEY" | wc -c # 64が出力されるはず
echo -n "$CREDS_IV" | wc -c # 32が出力されるはず
ストリーミングレスポンスが途中で切れる
まずリバースプロキシのタイムアウト設定を確認する。Cloudflareを使っている場合は、chatドメインに対してバイパスするか「Disable Response Buffering」を有効にする必要がある——Cloudflareはデフォルトでレスポンスをバッファリングし、ストリームを切断してしまう。
データのバックアップ
# 手動でMongoDBをバックアップする
docker exec LibreChat-mongodb-1 mongodump \
--db LibreChat \
--out /data/backup/$(date +%Y%m%d) \
--gzip
# バックアップをコンテナの外にコピーする
docker cp LibreChat-mongodb-1:/data/backup ./backup
# 毎朝3時に自動バックアップするcronジョブ
0 3 * * * docker exec LibreChat-mongodb-1 mongodump --db LibreChat --out /data/backup/$(date +\%Y\%m\%d) --gzip
あの深夜2時の夜から8ヶ月後
LibreChatはあれから今日まで25人のチームで安定稼働し続けている——ダウンタイムも、目立ったインシデントもない。アップデートもシンプルだ:
git pull
docker compose pull && docker compose up -d
一番気に入っているのは、会話履歴が自分のMongoDBに保存されることだ——機密データがどこへ行くか分からないという不安がなくなった。さらにプリセットシステムのおかげで、部署ごとに専用のシステムプロンプトとユースケースに合わせたモデルが設定済みのプリセットを用意でき、新メンバーのオンボーディングも10分で完了する。
初期セットアップに正しく設定するまで1〜2時間かかるが、その後のメンテナンスはほぼゼロだ。もしあなたのチームが社内業務でAIを使っていて、その会話データがどこへ行っているか把握していないなら——これが具体的な答えだ。

