Ollama APIにパスワードがない理由と対策
Ollama APIは認証なしで、port 11434に届く相手がモデル実行やpullを実行できます。VPSで起きる問題と、3つの対策を順番に解説します。
Ollama API にはパスワードがありません
Ollama API には認証がありません。実行しているサーバーには、ユーザー認証、パスワード、key の検証、allowlist のいずれもありません。port 11434 への TCP 接続を確立できるものはすべて、モデルの一覧表示、実行、新しいモデルのダウンロード、既存モデルの削除を行えます。
公式ドキュメントにも、次のように明記されています。「http://localhost:11434 を介して Ollama API にローカルからアクセスする場合、認証は必要ありません」。この文では、セキュリティモデル全体を ローカルから という条件が担っています。Ollama はデフォルトで 127.0.0.1 に bind するため、ラップトップでは loopback interface がアクセス制御になります。その listener を public address に移すと、代わりのアクセス制御がないため、アクセス制御はなくなります。
VPS (virtual private server) でこの点が重要になる理由はここにあります。デフォルト設定は安全です。多くの人が最初に行う変更は、2 台目のマシンからモデルを使えるよう listener を開くことです。しかし、この変更によって、すべての保護が一度に失われます。
開放された 11434 番ポートから分かること
すべてのエンドポイントにアクセスできます。読み取り専用モードも、専用の管理ポートもありません。以下は実際のリクエストで、localhost ではなくサーバーのアドレスを指定しています。
# List every model on the box
curl http://SERVER_IP:11434/api/tags
# See what is loaded into memory right now
curl http://SERVER_IP:11434/api/ps
# Run a prompt on your hardware
curl http://SERVER_IP:11434/api/generate -d '{"model":"llama3.2","prompt":"Why is the sky blue?"}'
# Write several gigabytes to your disk
curl http://SERVER_IP:11434/api/pull -d '{"model":"llama3.2"}'
# Remove a model
curl -X DELETE http://SERVER_IP:11434/api/delete -d '{"model":"llama3.2"}'運用上、4 つの問題が発生します。
- 他者のために CPU または GPU で推論を実行することになります。従量制限のある CPU プランでは、継続的な負荷によって、知らない相手に利用枠を消費されます。呼び出し元が自分だけでなくなると、VPS 上の AI ワークロードのコストを抑えることは難しくなります。
/api/pullによってディスクへ書き込まれます。モデルは 1 つあたり 2 から 40 gigabytes あります。pull のループでボリュームが満杯になり、Ollama だけでなく、サーバー上の他のすべてのサービスも停止します。- リクエストはプロセス内に到達し、ログに記録されます。デフォルトのログレベルでは、Ollama はメタデータのみを記録します。そのため、プロンプト本文ではなく、エンドポイント、ステータス、レイテンシ、クライアントアドレスが記録されます。それでも、誰がサーバーを何のために使用したかという記録が journal に残ります。これは自分で収集を選択した情報ではありません。
/api/deleteによってモデルが削除されます。復元するには、自分の帯域幅を使って再度ダウンロードする必要があります。
これらの問題に exploit は必要ありません。ドキュメント化された API が、設計どおりに動作しているだけです。
Ed25519 キーはアクセス制御ではありません
「Ollama API key」を検索すると、異なる2つのものが見つかります。どちらもサーバーのパスワードではありません。この2つを区別すると、混乱の大部分を解消できます。
1つ目は、ID キーペアです。 Ollama は初回起動時に Ed25519 キーペアを生成します。Linux では、インストールスクリプトが ollama という system user を作成し、その home directory を /usr/share/ollama に設定します。したがって、キーペアは次の場所に保存されます。
/usr/share/ollama/.ollama/id_ed25519
/usr/share/ollama/.ollama/id_ed25519.pubこのキーは外向きに使用されます。ollama signin が公開鍵を ollama.com アカウントに登録します。この鍵によって、registry へのモデルの push や、非公開モデルの pull が認証されます。つまり、この鍵は ollama.com に対してマシンを証明します。マシンに接続するクライアントには何も要求しません。この鍵を削除、ローテーション、または未作成のままにしても、API を呼び出せるユーザーは変わりません。
2つ目は OLLAMA_API_KEY です。 この変数には、https://ollama.com/settings/keys で作成したキーが格納されます。クライアントは、https://ollama.com/api のホステッド API を呼び出す際に、Authorization: Bearer $OLLAMA_API_KEY としてこのキーを送信します。これは Ollama のサービス用の認証情報であり、クライアントであるあなたが使用します。あなたの ollama serve がこのキーを読み取ることはありません。VPS で OLLAMA_API_KEY を設定しても、VPS にパスワードが設定されるわけではありません。
したがって、有効化する設定はありません。以下の3つの防御策は、いずれも同じ考え方で機能します。ポートに到達できない状態を維持し、認証を実行するものを前段に置きます。
現在サーバーが待ち受けているポートを確認する
sudo ss -tlnp | grep 11434安全な結果では、loopback アドレスが表示されます。
LISTEN 0 4096 127.0.0.1:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))公開状態の結果では、すべてのインターフェースが表示されます。
LISTEN 0 4096 0.0.0.0:11434 0.0.0.0:* users:(("ollama",pid=812,fd=3))0.0.0.0 は、このサーバー上のすべての IPv4 アドレスを意味します。公開アドレスも含まれます。*:11434 と [::]:11434 は、IPv6 を含めた場合の同じ指定です。
次に、外部から確認します。これはサーバーではなく、ラップトップで実行してください。
curl -m 5 http://YOUR_SERVER_IP:11434/api/versioncurl: (28) Connection timed out after 5001 milliseconds であれば問題ありません。curl: (7) Failed to connect ... Connection refused も同様です。version フィールドを含む JSON オブジェクトが返る場合、API 全体に誰でもアクセスできます。サーバー上で curl を実行しても、外部公開の確認にはなりません。loopback は常に応答するためです。
公開状態になる経路は、通常 2 つあります。1 つ目は、別のマシンからモデルへアクセスする必要があり、意図的に設定を変更する場合です。
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"この 1 行だけで、公開状態になります。2 つ目は Docker です。この場合、設定ファイルを編集する必要はありません。Docker については、以下の独立したセクションで説明します。
防御策 1: localhost で待ち受け、トンネル経由で接続する
まずこの方法を使ってください。新しいソフトウェアは不要で、漏えいする可能性のある認証情報も作成しません。ポートはパブリックインターフェース上に存在しないため、スキャンで検出されません。
デフォルトに依存せず、バインドアドレスを明示的に設定します。
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"これにより /etc/systemd/system/ollama.service.d/override.conf が書き込まれます。設定を適用して確認します。
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434ss は 127.0.0.1:11434 を示すはずです。それでも 0.0.0.0 を示す場合は、別の drop-in ファイルが優先されています。systemctl cat ollama.service を実行して、unit とすべての drop-in、およびそれぞれのパスを一覧表示し、古いファイルを削除します。
ラップトップからモデルを使用するには、SSH 経由でポートを転送します。
ssh -N -L 11434:127.0.0.1:11434 you@your-server-L 11434:127.0.0.1:11434 はラップトップ上のポート 11434 を開き、そこに到着したすべての通信を、サーバーから見える 127.0.0.1:11434 へ送ります。-N は SSH にリモートコマンドを実行させない指定です。そのため、プロセスはトンネルを開いたまま保持します。トンネルが動作している間、ラップトップで次のコマンドを実行できます。
curl -s http://localhost:11434/api/tags発生しやすい失敗は 2 つあります。bind [127.0.0.1]:11434: Address already in use は、ラップトップ上で Ollama 自体がそのポートを使用していることを示します。その場合は -L 11500:127.0.0.1:11434 で別のローカルポートを選び、クライアントの接続先を 11500 にします。正常に接続したトンネル経由で空の応答が返る場合は、SSH は動作しているものの、サーバー側で Ollama が待ち受けていません。SSH コマンドを変更する前に、サーバー上で ss を確認します。
複数のクライアントマシンを使用する場合は、ユーザーごとにトンネルを 1 本作るより、プライベートネットワークの方が適しています。マシンを WireGuard または Tailscale に接続し、Ollama を 0.0.0.0 ではなく、そのネットワーク上のアドレスで待ち受けるようにします。
[Service]
Environment="OLLAMA_HOST=10.8.0.1:11434"この場合、ポートは接続に暗号鍵が必要なインターフェース上にだけ存在します。ファイアウォール設定を誤った場合にも有効です。ルールが誤って全世界からのアクセスを許可しても、パブリックインターフェースが待ち受けていないポートを公開することはできません。
防御 2: bearer token を確認する reverse proxy
パブリックインターネット上のクライアントからモデルを呼び出す必要がある場合は、Ollama を loopback に限定し、その前段にプロキシを置きます。プロキシが TLS (transport layer security) を終端し、正しいヘッダーがないリクエストを拒否します。Ollama は引き続き 127.0.0.1 からの接続だけを受け付けるため、プロキシが唯一の接続経路になります。
最初に実際の token を生成します。手作業で作成しないでください。
openssl rand -base64 36token を確認する nginx のサイト設定は次のとおりです。
map $http_authorization $ollama_ok {
default 0;
"Bearer PASTE_YOUR_GENERATED_TOKEN_HERE" 1;
}
server {
listen 443 ssl;
server_name llm.example.com;
ssl_certificate /etc/letsencrypt/live/llm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;
location = /api/pull { return 403; }
location = /api/delete { return 403; }
location = /api/push { return 403; }
location / {
if ($ollama_ok = 0) { return 401; }
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host 127.0.0.1:11434;
proxy_buffering off;
proxy_read_timeout 600s;
}
}この設定では 5 行が実際の処理を担っており、それぞれが、設定しなければ発生する障害を防ぎます。
if を location ブロック内で使用するのは、通常 nginx では適切ではありません。ただし、本文が正確に return である形式は、予測どおりに動作する 2 つの形式の 1 つなので、この使用方法は安全です。
location = /api/pull は完全一致です。nginx は完全一致を location / プレフィックスより優先するため、この 3 つのエンドポイントは token を確認する前に拒否されます。有効な token があっても、推論を実行できるだけで、ディスクを使い果たすことはできません。
proxy_set_header Host 127.0.0.1:11434; が必要なのは、Ollama が受信した Host と Origin ヘッダーを調べるためです。プロキシの公開ホスト名をそのまま渡すと、Ollama 由来の 403 Forbidden が生成されることがあり、nginx の設定をデバッグしにくくなります。OLLAMA_ORIGINS は、特定の origin を許可する必要があるブラウザクライアント向けの、もう 1 つの設定です。
proxy_buffering off; が必要なのは、Ollama がレスポンスを token 単位でストリーミングするためです。buffering を有効にすると、nginx はストリームを保持し、生成の最後にまとめて配信します。そのため、生成中ずっとクライアントが停止したように見えます。
proxy_read_timeout 600s; が必要なのは、nginx のデフォルト値が 60 秒だからです。CPU 上での長い生成は簡単にこの時間を超え、クライアントは 504 Gateway Time-out を受け取り、/var/log/nginx/error.log には upstream timed out (110: Connection timed out) while reading response header from upstream が記録されます。リクエストは処理中でした。nginx が処理を打ち切っただけです。
設定を reload し、2 つの経路をテストします。
sudo nginx -t && sudo systemctl reload nginx
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
curl -s -H "Authorization: Bearer YOUR_TOKEN" https://llm.example.com/api/tags1 つ目は 401 を出力するはずです。2 つ目はモデル一覧を出力するはずです。1 つ目もモデル一覧を返す場合は、map ブロックのスコープが誤っています。これは http レベルに置く必要があるため、/etc/nginx/conf.d/ 配下のファイルまたは server ブロックの上に記述してください。server の内側には置かないでください。
Caddy でも 4 行の basic authentication で同じ処理を実行できます。bearer token よりもブラウザクライアントに適しています。
llm.example.com {
basic_auth {
apiuser PASTE_BCRYPT_HASH_HERE
}
reverse_proxy 127.0.0.1:11434
}caddy hash-password を実行すると、必要な bcrypt hash が生成されます。directive 名には注意が必要です。Caddy v2.8 より前は basicauth で、現在は basic_auth です。そのため、古いガイドからコピーした設定は読み込みに失敗し、Caddy は認識できなかった directive 名を示します。
どのプロキシを選んでも、これは全員で共有する 1 つの Secret です。これを保持するすべてのクライアントが同じアクセス権を持ちます。無効化するには設定を編集し、すべての呼び出し元を同時に更新する必要があります。
防御 3: クライアントごとにキーを発行するゲートウェイ
複数のユーザーやアプリケーションがモデルを呼び出すようになると、共有トークンでは対応できません。どのクライアントが負荷を発生させたのか特定できず、1 つだけ停止することもできません。プロキシがあった場所にゲートウェイを配置し、同じ OpenAI互換 API で通信します。ゲートウェイはクライアントごとに個別のキーを発行し、各キーの利用状況を記録します。通常は 自己ホスト型の LiteLLM ゲートウェイを使用します。アクセス制御に加えて、キーごとの予算とリクエストログも利用できます。
防御 1 のルールは変わりません。Ollama は 127.0.0.1 にバインドし、Ollama と通信するプロセスはゲートウェイだけにします。パブリックリスナーを持つサービスもゲートウェイだけにします。port 11434 が依然として外部公開されているホストにゲートウェイを配置しても、意味がありません。呼び出し元はゲートウェイを経由せずに接続できるためです。
ファイアウォールの落とし穴: 公開したコンテナポートは UFW を迂回する
ファイアウォールを正しく設定したはずのサーバーで、外部公開されたインスタンスが存在する理由はこれです。
UFW (uncomplicated firewall) は、カーネルの filter テーブルにある INPUT チェーンへルールを書き込みます。INPUT は、ホスト自身宛てのパケットを処理します。Docker の -p フラグは、nat テーブルの PREROUTING チェーンに宛先 NAT (network address translation) ルールを書き込みます。カーネルは、パケットの送信先を決定する前にこのルールを評価します。ルーティングの決定時点では、送信先がすでにコンテナのアドレスへ書き換えられています。そのため、パケットはローカルに配送されず転送され、INPUT ではなく FORWARD を通過します。UFW の INPUT ルールは参照されないため、パケットはファイアウォールを通らずに迂回します。
そのため、次の手順ではポート 11434 がインターネットに公開されたままになります。
sudo ufw default deny incoming
sudo ufw enable
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollamaそれでも sudo ufw status は、デフォルト拒否のファイアウォールが有効だと報告します。どちらの表示も同時に正しいため、誤った表示を信頼してしまいます。原因となったルールは次のコマンドで確認できます。
sudo iptables -t nat -L DOCKER -n修正方法は、publish フラグにアドレスを1つ追加することです。
docker rm -f ollama
docker run -d -v ollama:/root/.ollama -p 127.0.0.1:11434:11434 --name ollama ollama/ollama-p 11434:11434 は -p 0.0.0.0:11434:11434 の省略形です。127.0.0.1 を指定すると、マッピングのホスト側が loopback に限定されます。そのため、SSH トンネルとリバースプロキシからは引き続きアクセスできますが、インターネットからはアクセスできません。モデルはコンテナ内ではなく名前付き ollama volume に保存されているため、ここでコンテナを再作成しても安全です。
次のコマンドで、両方の表示が一致することを確認します。
docker port ollama
sudo ss -tlnp | grep 11434docker port ollama は 11434/tcp -> 127.0.0.1:11434 を出力するはずです。0.0.0.0:11434 が出力される場合、まだ外部公開されています。この仕組みを一度理解すれば、今後公開するすべてのコンテナに適用できます。Docker の公開ポートが UFW を迂回する理由では、DOCKER-USER チェーンと、Docker の再起動後も残るルールについて説明しています。ホスト自体のポリシーをまだ構築中であれば、新しい VPS に必要な UFW ルールで、この構成の基盤を確認できます。Rocky または AlmaLinux には設定対象の UFW がないため、代わりに firewalld で記述する同じ基盤ポリシーから始めてください。
実行中のプロセスの実行ユーザー
Linux のインストールスクリプトは専用アカウントを作成し、そのアカウントでサービスを実行します。
useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama/etc/systemd/system/ollama.service の unit は、User=ollama と Group=ollama を設定します。これは変更しないでください。ターミナルで手動実行した簡単な ollama serve は、ログインしているユーザーとして実行されます。そのユーザーが root の場合、認証されていない API が root としてファイルを書き込みます。実行ユーザーを確認します。
ps -o user= -C ollama結果は ollama になるはずです。それ以外の場合は、手動で起動したプロセスが unit と並行して実行されているか、unit の代わりに実行されています。後から追加するすべてのデーモンにも同じ考え方が当てはまり、最小権限ユーザーでサービスを実行することで適切に運用できます。
Ollama API エンドポイントが安全か確認する方法
どの構成を選んだ場合でも、別のマシンから次のテストを実行すれば確認できます。
curl -m 5 http://YOUR_SERVER_IP:11434/api/version
curl -m 5 http://YOUR_SERVER_IP:11434/api/tagsどちらもタイムアウトするか、接続を拒否する必要があります。プロキシを構築した場合は、プロキシのホスト名に対して同じ2つのパスへアクセスし、認証情報なしでは 401 を返し、認証情報ありでは正しい JSON を返す必要があります。
次に、アクセスログを1回確認します。ポートが公開されていた間に、誰かがそのポートを見つけたかどうかを確認できます。
journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1Ollama はリクエストごとに1行を記録し、クライアントアドレスも含めます。
[GIN] 2026/08/12 - 14:01:10 | 200 | 103.965898ms | 127.0.0.1 | POST "/api/generate"Ollama が loopback にバインドされると、すべての行に 127.0.0.1 が1回表示されます。接続元になり得るアドレスがそれだけだからです。この列にパブリックアドレスが表示されている場合は、外部からのリクエストです。タイムスタンプから発生時刻を確認できます。このコマンドが何も出力しない状態が、求める結果です。Ollama のモデル側の運用に慣れていない場合は、VPS で Ollama を実行する方法で、インストール、モデルサイズ、実際にロードできるモデルを決めるメモリ制限を説明しています。
FAQ
Ollama に API key またはパスワードはありますか?
いいえ。実行しているサーバーには、どのような認証もありません。公式ドキュメントにも、API へのアクセスに認証は必要ないと記載されています。「Ollama API key」と呼ばれるものは、どちらも別の用途です。/usr/share/ollama/.ollama/ にある Ed25519 の鍵ペアは、モデルを push したり非公開モデルを pull したりするために、ollama.com に対してマシンを証明します。OLLAMA_API_KEY は、クライアントが https://ollama.com/api のホステッド API に送信する認証情報です。使用している ollama serve はどちらも読み取らないため、アクセス制御はネットワークまたは前段のプロキシで行う必要があります。
ファイアウォールがある場合、OLLAMA_HOST=0.0.0.0 は安全ですか?
そのホスト上で、ほかの何もファイアウォールルールを書き換えない場合に限り安全です。0.0.0.0 は、リスナーがパブリックインターフェイス上に実際に存在し、ファイアウォールだけで到達不能にできると信頼していることを意味します。Docker がポートを公開すると、その信頼は崩れます。Docker が nat テーブルに追加する DNAT ルールは、パケットが UFW の存在する INPUT チェーンに到達する前に評価されるため、パケットは転送され、UFW はそれを認識できません。127.0.0.1 またはプライベートトンネルのアドレスに bind すれば、リスナーはパブリックインターフェイスから除外されます。そのため、ファイアウォール設定を誤っても公開されるものがありません。
Ollama のポートがインターネットに公開されているかどうかを確認するにはどうすればよいですか?
サーバー上で sudo ss -tlnp | grep 11434 を実行し、別のマシンから curl -m 5 http://YOUR_SERVER_IP:11434/api/version を実行します。ss が 127.0.0.1:11434 を表示し、リモートからの curl がタイムアウトする状態が、期待する結果です。ss が 0.0.0.0:11434 または *:11434 を表示し、リモートからの curl が JSON を返す場合、API 全体に到達できます。サーバー自体で curl を実行してテストしてはいけません。bind アドレスに関係なく、loopback が応答するためです。
ポートを 11434 から適当な番号に変更するだけではだめですか?
だめです。理由を明確にしておく必要があります。別のポートへの変更で遅くなるのは、単一のポートをスキャンする場合だけです。スキャナーはポート範囲全体を調べ、到着したポートに関係なく、/api/tags への 1 回のリクエストでサービスを特定します。ポートを変更すると、すべてのクライアントのデフォルト設定も壊れ、後で自分の構成を把握しにくくなります。ポートを移動するのではなく、loopback に bind してください。これによりリスナー自体がなくなります。
公開した Ollama に誰かがアクセスしました。何を確認すればよいですか?
まず 127.0.0.1 に bind してサービスを再起動してください。調査を始める前に公開状態を止めます。次に journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1 を実行し、どの外部アドレスが、いつ、どのエンドポイントを呼び出したかを確認します。ollama list を、本来存在するはずのモデルと比較してください。/api/pull には認証がなく、pull していないモデルはディスク使用量であると同時に、アクセスの証拠でもあります。df -h で空き容量を確認します。Ollama はデフォルトのログレベルではプロンプト本文を記録しません。そのため、誰がどのモデルにリクエストしたかは記録できますが、何が生成されたかは記録できません。