VPSでOllamaをセルフホストする方法と注意点
VPSでOllamaを安全に構築する手順を解説します。7Bモデルを動かすには8GBのRAMが必要で、CPU環境では4〜10 tokens/s程度の速度になります。APIのポート11434を外部に公開せず、127.0.0.1でのみ通信を許可する安全な設定方法を詳しく説明します。
構築内容
所有するサーバー上で動作する、単一の open-weight 言語モデルを構築します。HTTP API を介して回答を取得でき、必要に応じてブラウザ上のチャットページからも利用可能です。Ollama は、モデルのダウンロード、メモリへのロード、および http://127.0.0.1:11434 上でのリクエスト処理を担当します。インストールはコマンド一つで完了します。難しい作業は他の工程にあります。VPS の RAM 容量に適したモデルの選定、および認証なしの推論サーバーをインターネット全体に公開してしまうリスクの回避です。
まず、2つの注意点があります。CPU のみの VPS では、小型モデルでも動作が低速になります。また、API には認証機能が組み込まれていません。これらはトラブルの原因になりやすいため、以下で詳細に説明します。
数値で見るサイジングの実態
モデルのメモリ使用量は、ファイルサイズに実行時のオーバーヘッド(約1 GB)と、コンテキストウィンドウ用のメモリを加えたものです。Ollamaのデフォルトモデルは4-bit量子化(Q4)されており、パラメータ10億個につき約500 MBのRAMを消費します。計算は単純で、これがすべての基準となります。
llama3.2:3bのような3Bモデルは、ダウンロードサイズが約2 GBで、実行には約4 GBの空きRAMが必要です。mistral:7bやllama3.1:8bのような7Bまたは8Bモデルは、ディスク容量が約5 GBで、約8 GBのRAMを消費します。余裕を持たせるなら16 GB必要です。13Bまたは14Bモデルは、およそ16 GBを必要とします。30Bから70Bの範囲のモデルは、大容量RAMを搭載したマシン、あるいは現実的にはGPUが必要です。CPUのみのVPSでは、メモリ不足になるか、応答が遅すぎて実用には耐えません。
次に速度について説明します。これは多くの人が過小評価している要素です。CPUでの推論はクロック周波数ではなく、メモリ帯域幅に依存します。共有vCPUのVPSは帯域幅が限られています。速度は1秒間に1桁から2桁前半のトークン数(tokens per second)になると想定してください。7-8BのQ4モデルでは4〜10 tokens/s、3Bモデルでは10〜25 tokens/s程度です。GPUはこれらよりも約1桁高速です。これらはあくまで概算です。最も正確な方法は、自身の環境で測定することです。その方法は、以下の実行ステップで説明します。記事の数値ではなく、自身の eval rate を信頼してください。
結論として、CPUでの小規模な量子化モデルは、速度が許容できる範囲内であれば、下書き、要約、分類に非常に有用です。それ以上のサイズや速度が必要な場合は、GPUインスタンスを検討してください。
特定のモデルと特定の環境を比較するには、以下のリンクからメモリ使用量を推定してください。
Ollama のインストール
2つの方法があります。VPSなどのクリーンな環境では、公式スクリプトを使用するのが最も簡単です。
curl -fsSL https://ollama.com/install.sh | shこのスクリプトは、ollama という名前のシステムユーザーを作成します。バイナリは /usr/local/bin/ollama にインストールされます。また、起動時に実行され、127.0.0.1:11434 をバインドする ollama.service という systemd サービスを登録します。動作確認は以下のコマンドで行います。
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 のみにバインドします。-p 11434:11434 と記述すると、すべてのインターフェースで公開されます。これはセキュリティセクションで警告している間違いです。インストール方法は1つだけ選んでください。スクリプトとコンテナを同時に実行すると、ポートの競合が発生します。
初めてのモデルのプルと実行
ollama pull llama3.2:3b
ollama run llama3.2:3bpull がモデルのレイヤーをディスクにダウンロードします(このモデルの場合は約 2 GB です)。run がそれらをメモリにロードし、>>> プロンプトを表示します。質問を入力してください。重みがディスクから RAM にロードされる間、最初のトークンの生成には数秒かかる場合があります。その後、回答がストリーミングされます。/bye と入力するとチャットを終了できます。Ollama はバックグラウンドで実行を継続します。
ロードされている内容とメモリ使用量を確認するには、以下を参照してください:
ollama psPROCESSOR 列に正確な情報が表示されます。100% CPU は GPU が使用されていないことを意味します。処理が遅い原因はこれです。verbose flag を使用して実際の速度を測定してください:
ollama run --verbose llama3.2:3b "Write two sentences about Linux."最後に表示される eval rate の行は、このハードウェアにおける 1 秒あたりのトークン数です。計画を立てる際は、この数値を基準にしてください。
モデルの保存場所と必要なディスク容量
スクリプトによってインストールされ、serviceとして実行される場合、モデルは ollama ユーザーのホームディレクトリに保存されます:
sudo du -sh /usr/share/ollama/.ollama/models自身のユーザーとしてインタラクティブに実行する場合、モデルは ~/.ollama/models に保存されます。コンテナ内では、ollama という名前の volume に保存されます。量子化された weights は容量を急速に消費するため、この点は重要です。例えば、3B は約 2 GB、7-8B は約 5 GB、14B は約 9 GB です。4つのモデルを比較するために pull すると、気づかないうちに 20 GB を消費します。保持する予定のモデルに合わせてディスク容量を決定し、それ以外は ollama rm <model> で削除してください。
自身で管理するサービスとして実行する
install script によってすでに ollama.service が登録されているため、追加作業なしで起動時に自動再起動します。変更を推奨する設定は、モデルの保持時間と、構成によっては bind address です。Ollama の upgrade によって設定が上書きされないよう、これらは systemd の drop-in に記述します。
sudo systemctl edit ollama.serviceエディタに表示される [Service] ヘッダーの下に、以下を追加してください。
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"OLLAMA_KEEP_ALIVE は、最後の request からモデルがメモリに保持される時間です(デフォルトは 5 分)。常にクエリを実行するサーバーでは、毎回 weights を再読み込みしないよう、この値を増やしてください。リソースが限られた環境では、request 終了直後に RAM を解放するため、0 に設定します。systemctl edit が unit files を再読み込みするため、変更を適用するには restart を実行してください。
sudo systemctl restart ollama最も重要なセキュリティ上の注意点
デフォルトでは Ollama は 127.0.0.1:11434 にバインドされます。そのため、VPS 内のプロセスのみがアクセス可能です。このデフォルト設定は適切です。そのまま維持してください。
API には認証機能がありません。一切ありません。API key も、ログインも、rate limit も、allow-list も存在しません。port 11434 にアクセスできる者は誰でも、ダウンロード済みのモデルの実行、新しいモデルのダウンロード、モデルの削除が可能です。また、CPU や GPU を無制限にフルロード状態にすることもできます。Shodan のようなスキャナーは、公開されている Ollama インスタンスを大量にインデックス化します。公開されたインスタンスは、数時間以内に発見され、悪用されます。
したがって、絶対に避けるべき唯一のミスは以下の通りです。OLLAMA_HOST=0.0.0.0 を設定して、firewall で 11434 を開放しないでください。そうすると、認証なしの推論サーバーをインターネット全体に公開することになります。0.0.0.0 上で 11434 を直接公開する構成を、設定によって安全にすることは不可能です。Ollama には設定すべき認証機能自体が存在しないためです。
サーバー以外の場所からモデルにアクセスするための、安全な方法は 3 つあります。
- ローカルに留める。呼び出し元が同じ VPS 上の別のプログラム(cron スクリプト、bot、または ツールとモデルを橋渡しする MCP server)のみである場合は、bind を
127.0.0.1のままにし、そのプログラムからhttp://127.0.0.1:11434を呼び出してください。何も公開されず、追加の設定も不要です。 - プライベートトンネル経由でアクセスする。VPS を 自身でホストする WireGuard VPN に接続します。
OLLAMA_HOSTをトンネルのアドレス(例:10.8.0.1、0.0.0.0ではなく)に設定してください。これにより、VPN ピアのみが接続可能になります。パブリックインターネットからは 11434 は見えません。 - 認証機能を持つ reverse proxy を前段に置く。nginx、Traefik、または Caddy で TLS を終端し、パスワードまたはトークンを要求するように設定してから、
127.0.0.1:11434へプロキシします。Ollama は localhost バインドを維持し、パブリックポートで待機するのはプロキシのみとなります。これは、ローカルサービスの前段に nginx 用の Let's Encrypt 証明書を配置する のと同じ構成です。
reverse-proxy を使用する構成は、次に紹介する、実際のログイン機能が付いた chat UI と同じ仕組みです。
Open WebUIによるチャットUIの追加(TLS経由)
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に到達できます。他の解説で見られる bridge-network の構成(--add-host=host.docker.internal:host-gateway に OLLAMA_BASE_URL=http://host.docker.internal:11434 を使用)は、ここでは機能しません。その名前はDocker bridgeのゲートウェイに解決されます。ホストの 127.0.0.1 でバインドされたサービスには、bridge経由では到達できないため、Open WebUIはOllamaに接続できないというエラーを出します。
host networking を使用する場合のトレードオフとして、Open WebUIはホストの全インターフェースのポート 8080 で待機します。-p のマッピングは無視され、Dockerは警告を表示します。そのため、ホストとプロバイダーの両方のファイアウォールで 8080 を閉じ、TLSリバースプロキシのみを公開ポートとして使用してください。初回アクセス時にOpen WebUIは管理者アカウントの作成を求められます。このアカウントが認証層となるため、強力なパスワードを設定してください。
ノートPCからHTTPS経由でチャットを開くには、127.0.0.1:8080 の前にTLSリバースプロキシを配置します。すでにサーバー上で複数のDockerアプリをルーティングしている場合は、Traefik(複数アプリの自動TLS対応) が最適です。1つのlabelブロックで証明書を発行し、chat.example.com をOpen WebUIにルーティングできます。セキュリティセクションの原則は変わりません。プロキシが公開ポートとログインを管理し、Ollamaはlocalhostに留まり、Open WebUIの 8080 はファイアウォールで保護されたままとなります。
コードからOpenAI互換エンドポイントを使用する
Ollamaは/v1においてOpenAI chat APIのサブセットをサポートしています。そのため、base URLとダミーのkeyの2箇所を変更するだけで、ほとんどの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"}]}'これは、agentやeditorのツールにモデルを組み込む際にも適用されます。ローカル環境で開発を行う場合、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領域を追加してください。swapがあれば、物理メモリをわずかに超える負荷でも、クラッシュせずに低速ながら処理を継続できます。swapは即座のクラッシュを防ぎますが、4 GBのメモリで70Bモデルを実用的にするものではありません。
"Error: model requires more system memory" Ollamaがモデルの起動を拒否し、Error: model requires more system memory (X GiB) than is available (Y GiB) と表示されます。これは前述のクラッシュの回避パターンです。OOM killerによる強制終了を避けるため、Ollamaが事前にメモリ不足を計算して停止しました。エラーには必要なメモリ量が表示されます。空きメモリ(free -h で確認)の範囲内のモデルを選択するか、context lengthを短縮するか、より大容量のVPSへ移行してください。設定(flag)で解決することはできません。メモリ不足は物理的な制約です。
最初のトークン生成に時間がかかり、その後は正常。 初回実行時は5秒から30秒ほど何も表示されませんが、その後は正常にストリーミングされます。この遅延は、ディスクからRAMへ重みがロードされる際に発生します。ストレージの速度が遅いと、この時間はさらに長くなります。一度ロードされると、モデルは OLLAMA_KEEP_ALIVE の間メモリに保持されるため、2回目以降のプロンプトには即座に回答します。この待ち時間を減らしたい場合は、保持時間を増やしてください。また、ollama ps を使用すると、モデルが現在ロードされているか確認できます。
全体的に動作が遅い。 エラーは出ませんが、生成速度が毎秒10トークン以下になります。これはCPUによる推論が行われている状態です。ollama ps の結果が 100% CPU であれば、GPUが使用されていません。これはバグではなく、設定の問題でもありません。制限要因はメモリ帯域幅であり、設定ミスではないため、設定で解決することはできません。より小さいモデルを使用するか、速度を許容するか、GPUインスタンスへ移行してください。不具合だと判断する前に、--verbose で実際の生成速度を測定してください。
他のマシンから Connection refused となる。 ノートPCなどの外部マシンからアクセスすると curl: (7) Failed to connect to <ip> port 11434: Connection refused と表示されます。これは仕様です。Ollamaはデフォルトで localhost にのみバインドされます。0.0.0.0 を設定して解決しようとしないでください。それはセキュリティ上の重大なミスにつながります。代わりに、VPN経由または認証プロキシ経由でモデルにアクセスしてください。
11434 ポートをインターネットに公開している。 もし OLLAMA_HOST=0.0.0.0 を設定し、ファイアウォールを開放している場合、身に覚えのないモデルのプルや、未知のクライアントによるCPU使用率100%の状態が発生します。これは、攻撃者に利用されている状態です。これは稀なケースではなく、最も重大なミスです。直ちに 127.0.0.1 またはVPNのアドレスにバインドし直して、ファイアウォールで11434ポートを閉じてください。また、前段に認証機能を導入してください。ポートが開いていた間にそのアドレスへ到達できたものは、すべて第三者からクエリされたものと考えてください。
バックアップとアップグレード
失われる状態(state)はほとんどありません。モデルは再ダウンロード可能です。そのため、バックアップすべきものは Open WebUI の data volume(アカウント、チャット履歴、設定)と、作成した systemd drop-in のみです。使い捨ての container を使用して volume をバックアップしてください。
docker run --rm -v open-webui:/data -v "$PWD":/backup alpine \
tar czf /backup/open-webui.tgz -C /data .Ollama は install script を再実行することでアップグレードできます。Open WebUI は docker pull ghcr.io/open-webui/open-webui:main を実行した後、container を再作成してアップグレードします。長期的な固定(pin)は避けてください。モデルの品質と runtime は共に変化が早いため、前四半期の数値に頼らず、リリースノートを確認して自身の環境で再ベンチマークを行ってください。
FAQ
CPUのみのVPSでLLMを実行できますか?
はい、制限はありますが可能です。3Bから8B程度の小さな量子化モデルであれば、CPUでも動作します。ドラフト作成、要約、分類などの用途には十分実用的ですが、共有vCPUでは処理速度は1秒間に数〜十数トークン程度と低速です。13B以上のモデルは、動作が極端に遅くなるか、RAM不足で動作しません。高速な処理や大規模なモデルが必要な場合は、GPUインスタンスを使用してください。
各モデルに必要なRAM量は?
デフォルトの4-bit量子化モデルにおける目安は以下の通りです。重み付けにパラメータ10億個あたり約0.5 GB、その他にオーバーヘッドとして約1 GB、さらにコンテキスト用の領域が必要です。したがって、3Bモデルには約4 GB、7-8Bモデルには約8 GB、14Bモデルには約16 GBの空き容量が必要です。free -hで空きメモリを確認し、OSや他のプロセス用の領域を確保してください。
Ollama APIに認証はありますか?
ありません。Ollamaには組み込みの認証、APIキー、レート制限はありません。ポート11434にアクセスできるユーザーは、すべての操作権限を持ちます。そのため、Ollamaはデフォルトで 127.0.0.1 にバインドされており、0.0.0.0 でポート11434をインターネットに公開してはいけません。ローカル環境、プライベートVPN、またはログイン機能を持つリバースプロキシ経由でアクセスしてください。
Webチャットインターフェースを追加するには?
DockerでOpen WebUIを --network=host を使用して実行します。これにより、ホストのloopbackを共有し、http://127.0.0.1:11434 にあるネイティブのOllamaにアクセスできるようになります。次に、ノートPCからアクセスするために、ポート 8080 の前にTLSリバースプロキシを配置してください。ファイアウォールで 8080 を閉じて、プロキシのみを公開窓口にしてください。Open WebUIの管理アカウントでログインを行い、初回起動時にパスワードを設定します。
独自のアプリケーションから呼び出すには?
http://127.0.0.1:11434/v1 にあるOpenAI互換エンドポイントを使用してください。OpenAI SDKのベースURLにこのURLを指定し、APIキーには(無視されるため)任意の文字列を入力してください。また、model にプル済みのモデル名を指定します。既存のOpenAI用コードは、ベースURLとキーを変更するだけで、そのまま動作する場合がほとんどです。