OllamaをVPSで安全にホストする方法
7Bモデルには約8 GBのRAMが必要で、CPUでは毎秒4〜10 tokensです。OllamaをVPSで動かし、127.0.0.1:11434/v1から呼び出す構成と、port 11434を閉じる理由を解説します。
構築するもの
所有するサーバー上で動作する単一のオープンウェイト言語モデルです。HTTP API 経由で応答し、必要であればブラウザーでチャットページも利用できます。Ollama はモデルをダウンロードしてメモリに読み込み、http://127.0.0.1:11434 でリクエストを処理するコンポーネントです。インストールは 1 つのコマンドで完了します。難しい点は別の部分にあります。VPS の RAM に実際に収まるモデルを選ぶことと、認証のない推論サーバーを誤ってインターネット全体に公開しないことです。
最初に、重要な注意点を 2 つ示します。CPU のみの VPS では、小型モデルでも処理速度が遅くなります。また、API には組み込みの認証機能がありません。どちらも問題が発生しやすい部分であるため、以下で詳しく説明します。
数値で確認するサイズの現実
モデルのメモリ使用量は、おおむねファイルサイズに、ランタイムのオーバーヘッドとして約 1 GBを加え、さらにコンテキストウィンドウ分を加えた値です。Ollama のデフォルトモデルは 4-bit 量子化(Q4 と表示)されており、パラメータ 1 billion 個あたり約 0.5 GBの RAMを使用します。計算は単純で、適合するかどうかはこの計算で決まります。最後の項は自分で設定します。Ollama の小さいデフォルト値より num_ctx を大きくすると長いプロンプトを扱えますが、RAM 上の KV キャッシュが増加します。そのため、モデルが適合するか判断する前にコンテキスト長を決めてください。
llama3.2:3bのような 3B モデルは、ダウンロードサイズが約 2 GBで、実行には空き RAMが約 4 GB必要です。mistral:7bや llama3.1:8bのような 7B または 8B モデルは、ディスク上で約 5 GBを使用し、RAMは約 8 GB、余裕を持たせるなら 16 GB必要です。13B または 14B モデルには、おおむね 16 GBが必要です。30Bから70Bの範囲のモデルには大容量 RAMのマシン、現実的には GPUが必要です。CPU VPSでは、適合しないか、適合しても実用にならないほど遅く応答します。
次に速度です。ここは過小評価されがちです。CPU推論はクロック速度ではなくメモリ帯域幅に制約され、共有 vCPU VPSの帯域幅は限られています。1桁台から低い2桁台の tokens per secondを見込んでください。7-8B の Q4 モデルは 1 秒あたり 4から 10 tokens、3B モデルは 1 秒あたり 10から 25 tokens程度になる場合があります。GPUは、おおむね1桁高い速度で動作します。ここで示した値は意図的に概算です。実際には、以下の実行手順で示す方法で自分のマシンを測定してください。どの記事の数字も、この記事の数字も信用せず、eval rateを信頼してください。
実用上の結論は明確です。CPU上の小型量子化モデルは、速度を許容できるなら、下書き、要約、分類に実際に役立ちます。より大きなモデルや高速な処理が必要なら、GPUインスタンスの費用を見込んでください。特定の1つのモデルについて、この計算を最初から最後まで確認したい場合は、VPSで Nemotron 3.5 Lightningを実行するで、取得する tag、実際に必要な RAM、CPUのみで処理が追いつくかを説明しています。
特定のモデルを特定のマシンで実行できるか比較するには、ここでメモリ使用量を見積もります。
Ollama のインストール
方法は2つあります。ベア VPS では、公式スクリプトが最も簡単です。
curl -fsSL https://ollama.com/install.sh | shこのコマンドにより、ollama という名前の system user が作成され、バイナリが /usr/local/bin/ollama にインストールされます。また、起動時に開始し、127.0.0.1:11434 に bind する ollama.service という名前の systemd service が登録されます。起動していることを確認します。
systemctl status ollama
ollama --versionすでに Docker を使用している場合は、コンテナを使用します。
docker run -d --name ollama \
-p 127.0.0.1:11434:11434 \
-v ollama:/root/.ollama \
--restart always \
ollama/ollamaポートマッピングの 127.0.0.1: プレフィックスに注意してください。これにより、ポートは localhost にのみ bind されます。-p 11434:11434 と記述すると、すべてのインターフェースで公開されます。これは、セキュリティセクションで警告している誤りです。インストール方法は1つだけ選択してください。スクリプトとコンテナを同時に実行しないでください。2つのプロセスがポートを奪い合うことになります。
最初のモデルを取得して実行する
ollama pull llama3.2:3b
ollama run llama3.2:3bpull はモデルのレイヤーをディスクにダウンロードします(このモデルでは約 2 GB)。run はレイヤーをメモリに読み込み、>>> プロンプトを表示します。質問を入力してください。重みをディスクから RAM に読み込む間、最初のトークンが表示されるまで数秒かかる場合があります。その後、回答がストリーミング表示されます。チャットを終了するには /bye と入力してください。Ollama はバックグラウンドで実行を続けます。
読み込まれている内容と、その構成を確認します。
ollama psPROCESSOR 列が実際の処理内容を示します。100% CPU は GPU を使用していないことを意味し、速度が遅い原因はここにあります。verbose フラグを使用して実際の速度を測定します。
ollama run --verbose llama3.2:3b "Write two sentences about Linux."最後に表示される eval rate 行が、このハードウェアでの 1 秒あたりのトークン数です。この値を基準に計画してください。
モデルの保存場所と必要なディスク容量
スクリプトでインストールし、サービスとして実行する場合、モデルは ollama ユーザーのホームディレクトリに保存されます。
sudo du -sh /usr/share/ollama/.ollama/models自分のユーザーで対話的に実行する場合、モデルは ~/.ollama/models に保存されます。コンテナでは、ollama という名前付きボリュームに保存されます。この違いは重要です。量子化済みの重みでも容量はすぐに増えるためです。3B モデルは約 2 GB、7-8B モデルは約 5 GB、14B モデルは約 9 GB を使用します。比較のために 4 つのモデルを取得すると、気付かないうちに 20 GB を消費します。保持するモデルに必要な容量を見積もってディスクを用意し、不要なモデルは ollama rm <model> で削除してください。同じ VPS で、写真ライブラリを保持する PhotoPrism または Immich など、別の大容量データを使用するサービスも実行している場合は、その使用量を空き容量から先に差し引いてください。残った容量を、実際にモデルへ割り当てられる容量として扱います。
制御するサービスとして実行する
インストールスクリプトはすでに ollama.service を登録しているため、追加の作業なしでブート時に再起動します。変更する価値がある設定は、モデルをメモリに常駐させる時間と、一部の構成での bind アドレスです。どちらも systemd の drop-in に記述するため、Ollama のアップグレードで上書きされません。
sudo systemctl edit ollama.serviceエディターに表示された [Service] ヘッダーの下に、次を追加します。
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"OLLAMA_KEEP_ALIVE は、最後のリクエスト後にモデルをメモリに保持する時間です(デフォルトは 5 分)。1 日を通して問い合わせるサーバーでは、毎回 weights を再読み込みしないよう値を大きくします。メモリに余裕がないサーバーでは 0 に設定すると、リクエストの完了直後に RAM を解放します。モデルを一定時間ではなく無期限に常駐させる場合は、Ollama のモデルを常時ロードしておくで、リクエスト単位の keep_alive フィールドと、最初の時間がかかるリクエストではなく再起動後に weights を再びウォームアップする方法を説明しています。systemctl edit は unit ファイルを再読み込みするため、変更を適用するには再起動します。
sudo systemctl restart ollama最も重要なセキュリティ上の注意点
デフォルトでは Ollama は 127.0.0.1:11434 にバインドするため、VPS 自身上のプロセスだけが接続できます。このデフォルト設定が正しいため、変更しないでください。
API に認証機能はありません。まったくありません。API key、ログイン、レート制限、allow-list のいずれもありません。11434 番ポートに接続できる者は、pull 済みのモデルを実行し、新しいモデルを pull し、モデルを削除し、CPU または GPU を無期限に最大負荷で占有できます。Shodan などのスキャナーは公開された Ollama インスタンスを数千単位でインデックス化しており、外部公開されたインスタンスは数時間以内に発見され、悪用されます。
そのため、絶対に避けるべき唯一の誤りは、OLLAMA_HOST=0.0.0.0 を設定して firewall で 11434 を開くことです。これにより、認証のない推論サーバーがインターネット全体に公開されます。Ollama には設定できる認証機能自体が存在しないため、raw な 11434-on-0.0.0.0 を安全にする設定はありません。これはこのサービス固有のルールであり、ポートを公開してはいけないという一般的な禁止事項ではありません。リモートデスクトップ用に自分でホストする RustDesk relay は、機能を提供するために公開トラフィックを受け入れる必要があります。その代わり、独自の key-based authentication と、文書化された短いポート一覧を備えています。Ollama には、そのどちらもありません。
このホスト以外からモデルに接続する安全な方法は3つあります。
- ローカルに限定します。同じ VPS 上の別のプログラム、cron script、bot、または ツールとモデルを接続する MCP server だけが呼び出し元なら、バインドを
127.0.0.1のままにして、そのプログラムからhttp://127.0.0.1:11434を呼び出します。何も公開されず、追加設定も必要ありません。 - private tunnel 経由で接続します。VPS を自分でホストする WireGuard VPN に接続し、
OLLAMA_HOSTを tunnel address に設定します(0.0.0.0ではなく、たとえば10.8.0.1)。接続できるのは VPN peer だけです。パブリックインターネットからは、11434 で何も待ち受けていないように見えます。 - 認証機能を持つ reverse proxy を前段に置きます。nginx、Traefik、または Caddy で TLS を終端し、password または token を要求してから
127.0.0.1:11434へ proxy します。Ollama は localhost bind のままにし、公開ポートで待ち受けるのは proxy だけにします。これは、任意のローカルサービスの前段に Let's Encrypt certificate を nginx に設定する構成と同じです。
reverse-proxy 方式は、次に設定する chat UI が実際のログイン機能付きで提供する構成です。
TLS の背後に Open WebUI でチャット UI を追加する
Open WebUI はセルフホスト型のチャットインターフェースです。Docker で実行し、ローカルの Ollama を参照させます。
docker run -d \
--name open-webui \
--network=host \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-v open-webui:/app/backend/data \
--restart always \
ghcr.io/open-webui/open-webui:mainLinux VPS では、--network=host フラグが重要です。これはコンテナをホストのネットワーク名前空間に配置します。そのため、コンテナ内の 127.0.0.1 はホスト自身のループバックとなり、Ollama がほかのインターフェースで待ち受けなくても、コンテナは 127.0.0.1:11434 で Ollama に接続できます。別の場所で紹介するブリッジネットワークの構成である --add-host=host.docker.internal:host-gateway と OLLAMA_BASE_URL=http://host.docker.internal:11434 は、ここでは機能しません。その名前は Docker ブリッジのゲートウェイに解決されます。また、ホスト上で 127.0.0.1 にバインドされたサービスにはブリッジ経由で到達できません。そのため、Open WebUI は Ollama に接続できないという状態のままになります。
ホストネットワークの代わりに、Open WebUI はホストのすべてのインターフェースでポート 8080 を待ち受けます。-p のマッピングは破棄され、そのことを示す警告が Docker によって出力されます。そのため、ホスト側とプロバイダー側のファイアウォールの両方で 8080 を閉じ、TLS リバースプロキシだけを公開経路にします。初回アクセス時、Open WebUI は管理者アカウントの作成を求めます。このアカウントが認証層になるため、強力なパスワードを設定してください。
ノート PC から HTTPS 経由でチャットを開くには、127.0.0.1:8080 の前段に TLS リバースプロキシを配置します。すでにこのホスト上で複数の Docker アプリをルーティングしている場合は、複数のアプリで TLS を自動化する Traefik が最も適しています。1 つのラベルブロックで証明書を発行し、chat.example.com を Open WebUI にルーティングできます。同じラベル単位のアプリケーションルーティングを、このホスト上のほかのブラウザフロントエンドでも使用できます。ステータスダッシュボードでも、Jellyfin ライブラリを 90 年代のレンタル店として表示する Halcyon のような娯楽向けのアプリでも同様です。それぞれ固有のホスト名とログインを設定します。セキュリティセクションの原則も変わりません。公開ポートとログインはプロキシが管理し、Ollama は localhost に置いたままにします。Open WebUI 自身の 8080 もファイアウォールで保護します。
コードからOpenAI互換エンドポイントを使用する
Ollamaは/v1でOpenAI chat APIのサブセットを提供しています。そのため、base URLと使い捨てのkeyを変更するだけで、ほとんどのOpenAIクライアントライブラリを使用できます。
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")
resp = client.chat.completions.create(
model="llama3.2:3b",
messages=[{"role": "user", "content": "Name three Linux distributions."}],
)
print(resp.choices[0].message.content)api_keyはクライアントライブラリで必要ですが、Ollamaでは無視されます。そのため、任意の文字列を指定できます。modelには、すでにpull済みの名前を指定する必要があります。存在しない名前を指定するとmodel "x" not found, try pulling it firstが返されます。単純なcurl呼び出しも同じ考え方です。
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"llama3.2:3b","messages":[{"role":"user","content":"Hello"}]}'エージェントやエディターのツールにモデルを組み込む場合も、この方法を使用します。すでにこのマシン上で開発している場合は、ローカルモデルをスクリプトやプラグインのバックエンドとして利用できます。tmux内でVPS上で実行するClaude Codeと併用すれば、低コストでプライベートな下書き処理を有料APIから切り離し、負荷の高い推論はホスト型モデルに任せられます。
障害のパターンと、実際に表示される正確な文字列
生成の途中でプロセスが「Killed」になる。 大きなモデルを起動すると、ターミナルに Killed と表示されるか、サーバーログに llama runner process has terminated: signal: killed が記録されます。モデルがサーバーの搭載 RAM を超えるメモリを必要としたため、Linux の OOM killer がプロセスを停止しました。sudo dmesg | grep -i oom で原因を確認できます。Out of memory: Killed process ... (ollama) のような行が表示されます。対策は、より小さいモデルまたはより強く量子化したモデルを使うことです。13B の代わりに llama3.2:3b を使う方法もあります。swap を追加すれば、物理 RAM をわずかに超える負荷でも、プロセスが停止せず低速で処理を完了できる場合があります。swap は即時クラッシュを低速な応答に変えるだけです。4 GB で 70B モデルを実用的に動かせるようにはなりません。ターミナルを監視していない限り、この停止は気付かれないままです。別の場所から問い合わせるサーバーでは、ollama.service に通知を送る OnFailure= unit を割り当て、プッシュ通知用に運用する ntfy サーバーへ投稿すると、次のリクエストまで待たずに停止した瞬間を把握できます。
「Error: model requires more system memory」と表示される。 Ollama はモデルの起動を拒否し、Error: model requires more system memory (X GiB) than is available (Y GiB) を表示します。これは前述のクラッシュを穏当な形で処理したものです。Ollama が必要なメモリを計算し、OOM killer に停止される前に処理を中止しています。必要なメモリと利用可能なメモリの2つの値も表示されます。必要量が空き RAM を下回るモデルを選んでください。空き RAM は free -h で確認できます。コンテキスト長を短くするか、より大きな VPS に移行する方法もあります。モデルを収めるための特別な flag はありません。必要なメモリは実際に必要です。
最初のトークンだけ非常に遅く、その後は正常です。 コールド状態のモデルは 5~30 秒間何も出力せず、その後は通常どおりストリーミングします。これは、初回に重みをディスクから RAM に読み込んでいるためです。ストレージが遅いと、さらに時間がかかります。読み込みが完了すると、モデルは OLLAMA_KEEP_ALIVE の期間メモリ上に常駐するため、2 回目のプロンプトには即座に応答します。初回の読み込みが呼び出し経路上のどこかで設定されたタイムアウトを超えると、応答が遅くなるのではなくエラーになります。その場合は、context deadline exceeded を報告した層の特定方法 により、クライアント、プロキシ、読み込み処理のどれが待機を打ち切ったのかを確認できます。間隔が気になる場合は、その値を大きくしてください。モデルが現在読み込まれているかどうかは ollama ps で確認できます。
全体的に遅い。 エラーは表示されず、1秒あたり10トークン以下しか生成されません。これは CPU 推論が本来の動作をしている状態です。ollama ps により 100% CPU が表示される場合、GPU はありません。これはバグではなく、設定でも解決できません。制限要因は設定ミスではなくメモリ帯域幅だからです。小さいモデルを使うか、その速度を受け入れるか、GPU インスタンスへ移行してください。問題があると判断する前に、--verbose で実際の生成速度を測定します。速度ではなく回答の長さが待ち時間の原因なら、num_predict で応答を制限すると、冗長なモデルが読む予定のないトークンを数分かけて生成することを防げます。
別のマシンから Connection refused になる。 ラップトップから curl: (7) Failed to connect to <ip> port 11434: Connection refused が返されます。これは想定どおりの動作です。Ollama は localhost のみに bind します。0.0.0.0 に bind して「修正」してはいけません。これは前述した、まさに避けるべき公開設定です。VPN 経由、または認証プロキシ経由でモデルへ接続してください。
11434 をインターネットに公開してしまった。 OLLAMA_HOST=0.0.0.0 を設定して firewall を開放した後、開始していないモデルの pull が実行されていたり、不明なクライアントによって CPU 使用率が100%に張り付いていたりする場合、すでに発見され、利用されています。これは稀なケースではなく、最も重大な設定ミスです。127.0.0.1 または VPN アドレスに bind し直し、firewall で11434を閉じ、手前に認証を配置してください。公開中にそのアドレスから到達できたものは、第三者に問い合わせられた可能性があると考えてください。
バックアップとアップグレード
失う可能性のある状態はほとんどありません。モデルは再ダウンロードできるため、バックアップする価値があるのは Open WebUI のデータボリューム、アカウント、チャット履歴、設定、および作成した systemd の drop-in だけです。使い捨てのコンテナでボリュームをバックアップします。
docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
tar czf /backup/open-webui.tgz -C /data .Ollama はインストールスクリプトを再実行してアップグレードします。Open WebUI は docker pull ghcr.io/open-webui/open-webui:main を実行してからコンテナを再作成し、アップグレードします。長期的にバージョンを固定しないでください。モデルの品質とランタイムはどちらも速いペースで変化するため、リリースノートを確認し、前四半期の数値をそのまま信頼せず、自分のサーバーで再ベンチマークしてください。
FAQ
CPU 専用の VPS で本当に LLM を実行できますか?
はい。ただし制限があります。3B から 8B 程度の小さな量子化モデルは CPU で動作し、文書の下書き、要約、分類に実用的に使えます。ただし速度は遅く、共有 vCPU では毎秒 1 桁から低い 2 桁程度のトークン数です。13B 以上のモデルは非常に遅いか、RAM に収まりません。十分な速度や大きなモデルが必要な場合は、GPU インスタンスを使用してください。
各モデルにはどの程度の RAM が必要ですか?
デフォルトの 4-bit 量子化モデルでは、重みに対してパラメーター 10 億個あたり約 0.5 GB の RAM が必要です。これに約 1 GB のオーバーヘッドと、コンテキスト用の追加領域が少し必要です。そのため、3B モデルには約 4 GB、7-8B モデルには約 8 GB、14B モデルには約 16 GB の空き容量が必要です。free -h で余裕を確認し、オペレーティングシステムやサーバー上の他の処理に必要な領域も確保してください。
Ollama API は認証されていますか?
いいえ。Ollama には組み込みの認証、API key、rate limit がありません。port 11434 に到達できるユーザーは、Ollama を完全に操作できます。そのため、デフォルトでは 127.0.0.1 に bind され、0.0.0.0 上の 11434 をインターネットに公開してはいけません。ローカルから、private VPN 経由で、または login 機能を追加した reverse proxy 経由でアクセスしてください。
Web chat interface を追加するにはどうすればよいですか?
--network=host を指定して Docker で Open WebUI を実行します。これにより host の loopback を共有し、http://127.0.0.1:11434 の native Ollama に接続できます。その後、port 8080 の前段に TLS reverse proxy を配置し、ラップトップからアクセスできるようにします。firewall では 8080 を閉じ、proxy だけを外部公開してください。login には Open WebUI 自身の admin account を使用し、初回起動時に password を設定します。
自分のアプリケーションから呼び出すにはどうすればよいですか?
http://127.0.0.1:11434/v1 の OpenAI-compatible endpoint を使用してください。任意の OpenAI SDK の base URL をこの URL に設定し、API key には任意の文字列を渡します。API key は無視されます。model には pull 済みのモデル名を設定してください。既存の OpenAI code は、通常、base URL と key を変更するだけでそのまま動作します。