NordBastion のホッキョクグマのマスコットが、暗い北欧の保管庫の中で彫刻が施された石のベンチに腰掛け、膝の上にノートパソコンを乗せている。傍らのサーバーラックの上には、六角形のガラス容器に封じられた光るシアン色のニューラルラティスがあり、閉じたルーン文字の扉の奥で、容器からシアン色のトークンの短い流れがスクリーンへと注ぎ込んでいる。
ハウツー · AI エージェント·読了17分 · 実践30分

VPS で LLM をセルフホスト。
GPU なし。API キーなし。プロンプトは施設の外に出ない。

GPU なしローカル LLM への6ステップ——箱を買う前にトークン/秒を予測する計算式、4/8/16/32 GB に収まるモデル、Ollama が標準搭載しない認証、そして正直に「向かない仕事」の一覧。Debian 12 で検証済み。

6つのステップ
  1. 01

    サイズ

    コア数ではなく帯域幅

  2. 02

    インストール

    Ollama

  3. 03

    測定

    あなた自身のトークン/秒

  4. 04

    保護

    TLS + トークン

  5. 05

    接続

    ベース URL 1つ

  6. 06

    制限する

    コンテキスト、RAM、ディスク

始める前に · 計算

たった一つの割り算が、この箱にできることを教えてくれる。箱を買う前に、それをやること。

言語モデルをローカルで動かすことについて書かれた文章のほとんどはグラフィックカードの話であり、手元にあるのが仮想マシンだけなら役に立たない。役に立つ考え方は、GPU をめぐる議論が示唆するよりずっとシンプルで、一文に収まる——1つのトークンを生成するために、高密度モデルはその重みをすべてメモリから読み出さなければならない。一部ではなく、全部を、トークン1つにつき1回。

この一つの事実だけで、性能に関する問いはすべて片が付く。生成速度を決めるのは借りたコア数ではなく、マシンが RAM からモデルをどれだけ速くストリームできるかだ。つまり、一円も使う前に、封筒の裏で計算できる上限がある。

tokens per second  ≈  memory bandwidth (GB/s)  ÷  model size (GB)

量子化された 8B モデルは約5 GB を占める。現実的に20 GB/s 前後をストリームできる仮想化ホストでは、上限は1秒あたり約4トークンで、実際に観測される数字はおそらくその半分から3分の2ほどになる。おおむね1秒に3語。これは失望すべきことではなく、この仕事についての事実として受け止めるとよい——チャット画面には遅いが、ドキュメントを分類して JSON を1行返す仕事には十分すぎるほどだ。

コア数は今も重要だ。ただし、多くの人が思っている理由とは違う。 スレッド数を増やすのは、メモリ経路が飽和するまでは効果がある。このクラスのマシンでは、それはたいてい4〜8スレッドあたりという早い段階で起きる。その先では、余分なコアは遊んでいるだけで、すべてが RAM を待っている状態になる。だから16コアの箱がテキスト生成において4コアの箱の4倍速いということにはならず、速度を期待してコア数にお金を払うことが、間違ったティアを買ってしまう一番よくある原因になる。

読むのは速く、書くのは遅い。 すべてのリクエストには2つの段階があり、振る舞いはまったく異なる。プロンプトの処理——プレフィル——は入力全体を一度に扱う計算律速の行列演算であり、生成よりも何倍も速く終わる。答えを生み出す方は、これまで説明してきたメモリ律速の部分で、トークンを1つずつ生成する。だから、2,000語の文書を渡して3文で返してもらうのは無理のない仕事だが、2,000語のエッセイを書かせるのはそうではない。この非対称性を踏まえてプロンプトを設計すれば、CPU の箱はトークンレートから想像するよりずっと快適に感じられる。

ティア メモリ 余裕をもって使える最大のモデル オーダー 用途
Sentinel · $3.904 GB3B(Q4、約2 GB)1秒に1文分類、タグ付け、ルーティング、エンベディング
Garrison · $7.908 GB8B(Q4、約5 GB)1秒に数語デフォルト。要約、JSON 抽出、RAG の回答
Ravelin · $16.9016 GB14B(Q4、約9 GB)上記のおよそ半分より高度な推論、長いコンテキスト、バッチパイプライン
Bulwark · $32.9032 GB32B(Q4、約20 GB)1秒に1語未満速度より品質。非同期の作業限定
Citadel · $62.9064 GB70B(Q4、約40 GB)1回の答えに数分収まる。対話向きではない。夜間ジョブ向け

モデルサイズはいつもの Q4_K_M 量子化によるもので、ほとんど気づかれない程度の品質と引き換えに、メモリを半分以下に抑える。速度列は上の割り算から導いたオーダー(目安)であり、ベンチマークではない——ステップ03の狙いは、この表を含め、どんな表も信じるのではなく、自分自身のマシンを計測することにある。

始める前に · 収まるか

CPU に本当に向いていること。そして、向いていないことも率直に。

このセクションは、熱っぽく書くより正直に書くほうがずっと価値がある。セルフホストしたモデルを見限る一番早い方法は、それが最も苦手な仕事にだけ使わせて、この発想自体が馬鹿げていたと結論づけることだからだ。

余裕をもって収まる。 出力が短く、価値が文章そのものではなく判断にある仕事すべて。メッセージをいくつかの区分のどれかに分類する。サポートチケットが緊急かどうかを判定する。請求書から5つの項目を JSON として抽出する。スレッドを3文に要約する。ドキュメントにタグを付ける。商品説明を書き直す。短い文字列を翻訳する。2つのレコードが同一人物を指しているかを検出する。段落がどこかへ送られる前に名前を伏せる。そのどれもが長い入力を消費して短い出力を生む——これはまさに、CPU が得意とする非対称性だ。

収まる。ただし辛抱がいる。 人が待っていない仕事。夜間バッチ、キューワーカー、その日のドキュメントを毎晩まとめて処理する作業、定期レポート。答えを誰も待っていないなら、チャット画面では耐えられないトークンレートもまったく問題にならなくなる——午前3時に6分かかるジョブは、ただ実行されたジョブにすぎない。

収まらない。 人が実際に使いたいと思える対話型アシスタント——この速度ではカーソルが這うように進み、アシスタントがない方がましな体験になる。長文生成——「2,000語書いて」——では出力全体が遅い部分になる。大きなリポジトリを何度も読み込むコーディングエージェントは、コンテキストも要求される品質も、小さなモデルが持ちこたえられる範囲を超える。10万トークンのコンテキストを必要とする何か——キャッシュだけでマシンの容量を超えてしまう。そして画像や動画のモデルは、まったく別の分野であり、これは本当に GPU を必要とする。

自分のワークロードがその最後のグループに属するなら、まっとうな答えはより大きな CPU の箱を買うことではなく、ハイブリッド構成にすることだ。呼び出しの大半はローカルモデルに任せ、最先端の推論が必要な一握りだけをホスト型 API に回す——これはまさに、AI エージェントを24時間365日動かすガイドがランタイム側について描いている形そのものだ。あのガイドは意図的にモデル自体を対象外にしていた。このガイドが、その欠けていた半分にあたる。

ステップ01 · サイズ

コア数ではなく、モデルに合わせて買う。そして余裕を残しておく。

仕事から逆算する。モデルにやらせたいことを決め、それをこなせる最小サイズを選び、そのサイズが Q4_K_M でどれだけ場所を取るかを調べ、そこにオーバーヘッドを足す。

RAM needed  =  model file  +  KV cache  +  ~2 GB for the system

  3B  Q4_K_M  ≈  2.0 GB        KV cache at 8k context   ≈  0.5–1 GB
  8B  Q4_K_M  ≈  4.9 GB        KV cache at 32k context  ≈  2–4 GB
 14B  Q4_K_M  ≈  9.0 GB
 32B  Q4_K_M  ≈ 20.0 GB
 70B  Q4_K_M  ≈ 40.0 GB

KV キャッシュは、みんなが忘れがちなオーバーヘッドだ。 会話の中にすでにあるトークンはすべてメモリに保持され、モデルが再計算しなくて済むようになっている。この保存領域は、許可するコンテキストの長さに応じて大きくなる。コンテキストを2倍にすれば、これもおよそ2倍になる。4k コンテキストでは収まっていたモデルが、32k では収まらなくなることがあり、しかもそれは最初のリクエストではなく10回目のリクエストで失敗するので、計算違いというより謎の不具合のように見えてしまう。

ここに緩やかな性能劣化というものはない。 合計が RAM を超えると、カーネルは行儀よく遅くなったりはしない。トークン1つごとにモデルの重みをディスクとの間でページングし始める。4秒で終わるはずの生成が4分になり、ロードアベレージは十の桁まで上がり、箱の上の他のすべて——データベース、Web サーバー、あなたの SSH セッション——も道連れになる。メモリに収めることは最適化ではない。必須条件だ。

パネルでは、注文 → VPS → 計算が示したティア、イメージは Debian 12。アカウント開設にメールアドレスは不要、身分証明書もどの段階でも求められず、請求は Monero、Bitcoin、Lightning、その他対応している資産のいずれかで決済する——これは普通の Web サーバーよりもここでは重要な意味を持つ。理由は匿名 VPS ホスティングの柱ガイドで説明されており、下のプライバシーの章ではそれをプロンプトに具体的に当てはめている。

ステップ02 · インストール

コマンド1つ、サービス1つ。ループバックに束縛し、そのままにしておく。

まずマシンを固める——鍵のみの SSH、頼んでいないものは何も通さないファイアウォール、無人でのセキュリティアップグレード。最初の1時間のチェックリストはおよそ1時間で終わり、この箱はまもなく、あなたが尋ねるすべての質問を抱えることになる。

次にランナーをインストールする。Ollama は、モデルレジストリと REST API と systemd ユニットをまとった llama.cpp であり、1行のインストーラーがこの3つすべてをセットアップする。

apt update && apt install -y curl
curl -fsSL https://ollama.com/install.sh | sh

systemctl status ollama --no-pager
ss -ltnp | grep 11434
# → 127.0.0.1:11434 — loopback only. Leave it that way.

最後の一行は二度読む価値がある。デフォルトのままではサービスはループバックインターフェースでしか待ち受けておらず、これはまさに正しい状態だ。この直後の10分間で最もよくある間違いは、別のマシンから届かないからといって OLLAMA_HOST を 0.0.0.0 に設定してしまうことだ。正しく届かせる方法はステップ04にある——ポート 11434 がインターネットに直接さらされてよい場合は存在しない。

後から気づくより、今のうちに設定しておく価値がある2つの項目がある。モデルはデフォルトで /usr/share/ollama 以下に保存され、サイズが大きいので、余裕のある場所を指すようにする。そして、デフォルトでは最後のリクエストから5分間モデルを RAM に常駐させ続ける。これは、ほかの作業も行っている箱にとっては気前が良すぎる設定だ。

systemctl edit ollama
[Service]
Environment="OLLAMA_MODELS=/var/lib/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=30m"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
systemctl daemon-reload && systemctl restart ollama

並列リクエストと複数モデルの同時ロードは、どちらもメモリ使用量を掛け算で増やす。モデル1つ分ちょうどのサイズで組んだマシンには、2つ目のコピーを収める余分な1ギガバイトもない。キューを直列化するのは、このハードウェアの制約ではなく、破綻しない唯一の構成である。

ステップ03 · 測定

自分自身の数字を手に入れる。他人のベンチマークは、あなたのマシンについて何も語らない。

モデルを pull する。最初の計測には、現行の 8B クラスの instructモデルならどれでもよい——サイズが近いので、計測結果はモデルではなくハードウェアについて語ってくれる。

ollama pull llama3.1:8b        # ~4.9 GB at Q4_K_M
ollama list
ollama ps                      # nothing resident yet

次に、タイミング表示をオンにして1回生成を実行する。重要な数値は eval rate——プロンプトを読み終えたあとに1秒あたり生成されるトークン数だ。

ollama run llama3.1:8b --verbose "Reply with exactly one sentence about the Baltic Sea."
total duration:        14.2s
load duration:          3.1s
prompt eval count:        24 token(s)
prompt eval rate:      92.11 tokens/s      ← reading: fast
eval count:               38 token(s)
eval rate:              3.42 tokens/s      ← writing: the real ceiling

2行、2つの異なる世界。読み込みは1秒あたり90トークン前後、書き込みは3.5トークンほどだった。この比率こそ、計算の章で見た非対称性を、自分自身のマシンで測った値であり、今日集める中で最も役に立つ一つの事実だ。意味するところはこうだ——この箱には長い入力を渡し、短い出力を求めよ。

同じ計測を API 経由で行う方法。2つか3つのモデルサイズを比較するスクリプトを組みたいなら、実際にはこちらが欲しいはずだ。

apt install -y jq

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model":  "llama3.1:8b",
  "prompt": "List three Nordic capitals.",
  "stream": false
}' | jq '{
  tokens: .eval_count,
  seconds: (.eval_duration / 1000000000),
  rate: (.eval_count / (.eval_duration / 1000000000))
}'

一段下のサイズと一段上のサイズを測ったら、そこで止める。 3B と 14B を pull し、同じプロンプトをそれぞれに通し、3つの速度を書き留める。これでこのマシンでのトレードオフのコストが正確にわかる——たいていは各方向でほぼ倍という数字になる——ので、印象ではなく仕事ごとに選べるようになる。そのうえで、使わないモデルは削除する。どれも数ギガバイトあるからだ。

どのモデルでも、初回実行には一つ注意点がある。出力の中の load duration は、重みをディスクから RAM に読み込むのにかかった時間だ。これが発生するのはモデルがまだ常駐していないときだけであり、それを制御しているのが OLLAMA_KEEP_ALIVE だ。速度を比較するときはこれを含めないこと。そして驚く必要もない——NVMe なら数秒で、しかも1回きりだ。

ステップ04 · 保護

Ollama に認証はない。まったくない。弱い認証があるのではなく、ない。

ここは、まずいことが起きるのを止めるためのくだりなので、遠慮なく言い切る。Ollama の API にはパスワードもトークンもユーザーモデルも権限システムもない。ポート 11434 に TCP 接続を開けるものなら何でも、あなたの CPU 上でテキストを生成し、pull 済みのモデルを列挙し、新しいモデルを pull し、使っているモデルを削除できる。オンにする設定はない。オンにする仕組みそのものが存在しないからだ。

ポート 11434 は常時スキャンされている。理由は単純で、開放されたモデルランナーは他人にとってのタダの計算資源だからだ。症状はアラートではない。2週間ほどマシンが遅く感じられ、心当たりのない帯域幅グラフが残るだけだ。サービスはループバックに留め、前段に呼び出し元を確認する仕組みを置くこと。

このマシンの外に、モデルを必要とするものが何もないなら、ここで止まってよい——もう終わっている。ループバックとファイアウォールだけで完結した答えになり、同じ VPS 上で動くエージェント、自動化スタック、Web アプリは、以降の作業なしに 127.0.0.1 経由でモデルに届く。続けるのは、別のマシン上の何かが呼び出す必要がある場合だけだ。

プロキシと、トークン。 長いランダムなトークンを生成し、A レコードをこの箱に向け、証明書と入り口の両方を Caddy に任せる。

openssl rand -hex 32      # → the bearer token, store it in a password manager
apt install -y caddy

/etc/caddy/Caddyfile

llm.example.com {
    @unauthorised not header Authorization "Bearer PASTE_THE_HEX_TOKEN_HERE"
    respond @unauthorised "unauthorised" 401

    reverse_proxy 127.0.0.1:11434 {
        # Generation is slow by nature — do not let the proxy give up first.
        transport http {
            read_timeout 10m
        }
    }
}
systemctl reload caddy
ufw allow 80,443/tcp
ufw status                # 11434 must appear nowhere

Basic 認証ではなくベアラートークンを選ぶことには、ちょっとした美しさがある。Ollama は OpenAI 互換 API を公開しており、OpenAI クライアントはどれもキーをまさにそのヘッダーとして送るので、いま生成したトークンが、アプリケーションがすでに運び方を知っている API キーそのものになる。カスタムヘッダーは一切不要で、アクセスのローテーションは Caddyfile の1行と、呼び出し側の環境変数1つで済む。

サーバーではない別のマシンから確認する。最初の呼び出しは拒否され、2回目は応答するはずだ。

curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
# → 401

curl -s https://llm.example.com/api/tags -H "Authorization: Bearer THE_TOKEN" | jq '.models[].name'
# → the list of models you pulled

モデルを呼び出すのがあなた自身ではなくエージェントになるなら、公開範囲の問題はリモート MCP サーバーをホストするガイドでより詳しく扱う価値がある——TLS、トークン、どこから何に届くべきかという同じ考え方を、トークンではなくツールを渡すサービスに当てはめたものだ。

ステップ05 · 接続

ベース URL 1つで、すでに何もかもがそれで話せる。変えるのは文字列1つだけ。

Ollama は自身の API に加えて、/v1 で OpenAI 互換のインターフェースを提供している。連携の話はこれで全部だ——OpenAI 向けに作られたもの、公式 SDK、フレームワークのラッパー、自動化ノードは、ベース URL とキーを変えるだけで動く。それ以外は何も変わらない。

curl -s https://llm.example.com/v1/chat/completions \
  -H "Authorization: Bearer THE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3.1:8b",
    "messages": [{"role":"user","content":"Reply with the word OK."}]
  }' | jq -r '.choices[0].message.content'

Python から見ると、ホスト型のセットアップと違うのは冒頭の2行だけだ。

from openai import OpenAI

client = OpenAI(
    base_url="https://llm.example.com/v1",
    api_key="THE_TOKEN",
)

r = client.chat.completions.create(
    model="llama3.1:8b",
    messages=[{"role": "user", "content": "Classify: 'the invoice is overdue'"}],
)
print(r.choices[0].message.content)

JSON を求めれば、JSON が返ってくる。 自動化にとって最も役立つ機能は制約付き出力だ。Ollama はモデルの振る舞いに期待するのではなく、答えを妥当な JSON に強制できる。これにより、小さなモデルは信頼できない語り手から頼れるパーサーへと変わる——無人で動き続けるワークフローと、40件に1件壊れるワークフローの違いはここにある。

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model":  "llama3.1:8b",
  "prompt": "Extract the total and the currency: Invoice 4021, 1 249,90 EUR due 30 days.",
  "format": "json",
  "stream": false
}' | jq -r .response
# → {"total": 1249.90, "currency": "EUR"}

自動化スタックでも同じことが言える。n8n には専用の Ollama ノードがあり、その OpenAI ノードはカスタムのベース URL を受け付けるので、既存のワークフローは認証情報を1つ編集するだけでローカル推論に移行できる。n8n セルフホスティングガイドが自動化エンジン自体を扱っている。できるなら、この2つは別々の箱で動かすこと。アイドル時でも700 MB を使うエンジンと、5ギガバイトを欲しがるモデルは、8ギガバイトのマシンの上では相性の悪い同居人だからだ。

そしてエンベディングのエンドポイント——この箱が本領を発揮する場所だ。 エンベディングモデルは生成モデルよりも2桁小さく、チャンクごとに1回のパスを行うだけで何も生成しないので、CPU は瞬時と感じられる速さで処理する。

ollama pull nomic-embed-text      # ~275 MB

curl -s http://127.0.0.1:11434/api/embed -d '{
  "model": "nomic-embed-text",
  "input": ["the first chunk of a document", "the second chunk"]
}' | jq '.embeddings | length'
ステップ06 · 制限する

制限のないモデルランナーは、手元にあるものをすべて使い切る。境界を与えること。

コンテキストに上限を設ける。 コンテキスト長はメモリ使用量を左右する主要なつまみであり、デフォルト値は小さな箱が望むより気前がよい。グローバル設定は、現実にありうる最長のプロンプトが実際に必要とする長さにする——分類や抽出のほとんどの作業は4,000トークン以内で快適にこなせる——そして、それ以上必要になる稀な呼び出しでは、リクエストごとに引き上げる。

Environment="OLLAMA_CONTEXT_LENGTH=4096"
curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "…a long document…",
  "options": { "num_ctx": 16384 },
  "stream": false
}'

モデルをどれだけメモリに常駐させ続けるか決める。 常駐しているモデルは瞬時に呼び出せるが、その代わりに数ギガバイトを人質に取る。推論専用のマシンなら、ずっとロードしたままにしておく。共有マシンなら、しばらくしたら解放させる。この値はリクエストごとにも指定できるので、夜間バッチはその実行の間だけモデルを固定し、終わったら解放することもできる。

OLLAMA_KEEP_ALIVE=-1     # resident until the service restarts
OLLAMA_KEEP_ALIVE=30m    # a sensible default on a shared box
OLLAMA_KEEP_ALIVE=0      # unload immediately after each request

ollama ps                # what is resident right now, and how much it holds

キューを直列化する。 1つのモデルに対する同時2リクエストは、2倍速くはならない。同じ飽和したメモリ経路を奪い合い、それぞれが遅くなる。しかも Ollama が2つ目のコピーをロードしてさばこうとすれば、箱の RAM が尽きる。このクラスのハードウェアでは、前段にキューを置いた「一度に1リクエスト」が、最速かつ唯一の安全な構成だ——だからこそ、ステップ02で OLLAMA_NUM_PARALLEL と OLLAMA_MAX_LOADED_MODELS を1に固定した。

ディスクを見張る。 4つのモデルを比較すれば、4つのモデルが手元に残る。1つ5ギガバイトともなれば、誰も文句を言わないままディスクが静かに埋まっていく。後回しのタスクにせず、比較そのものに片付けを組み込むこと。

ollama list
du -sh /var/lib/ollama/models
ollama rm mistral:7b qwen2.5:14b

最後に、再現できないものだけをバックアップする。モデルの重みは再現できる——pull すればまた手に入る。リポジトリに値するのは、設定、Caddyfile、トークン、3週間かけて磨いたプロンプト、そしてもし作っているなら検索の裏にあるベクトルインデックスだ。暗号化バックアップのガイドが仕組みを扱っている。この箱についての含めるべきリストは短く、書き留めておく価値がある。

良い部分 · 検索

CPU が反論を打ち負かす場所。エンベディングは遅くない。

ここまでの話はすべて生成についてであり、CPU が苦手とする部分だ。検索は、たいていの実用的なシステムのもう半分であり、この構図をまるごと反転させる——だからこそ、このページで最も安いティアでも、そこでは一度もトークンを生成しなくても、本当に価値のあることができる。

エンベディングモデルは、テキストの一部をベクトルに変換する。サイズはギガバイトではなく数百メガバイト単位で測られ、チャンクごとにちょうど1回の順伝播を行うだけで、メモリ帯域幅に縛られるトークンごとのループも存在しない。8B モデルが1秒に3語しか書けない同じ箱の上で、エンベディングモデルはドキュメントライブラリを、ファイルコピーのような速さで処理していく。

その形。 ドキュメントを数百語程度のチャンクに分割する。各チャンクを一度エンベディングし、ベクトルを保存する。質問時には質問自体をエンベディングし、最も近いチャンクを数個見つけ、それを質問と一緒にモデルへ渡す。保存先に特別なものは要らない——ベクトル拡張を備えた SQLite データベースだけで、単一の VPS 上で数万チャンクをまかなえるし、pgvector を使った PostgreSQL ならそれをはるかに超える規模でも対応できる。専用のベクトルデータベースは後になって欲しくなるぶんには結構だが、初日から必要な依存関係ではない。

これが速度よりも重要な理由。 それぞれの半分が何に触れるかを見てほしい。生成のステップが目にするのは、1つの質問といくつかの段落だ。エンベディングのステップが目にするのは<em>あなたが持つすべてのドキュメント</em>——アーカイブ全体、すべての契約書、すべてのメモ、すべてのメッセージが、チャンクごとにモデルを通過していく。そのステップをホスト型エンドポイントに対して実行すれば、インデックス化のためにコーパス全体が第三者に送信されたことになる。自分のマシン上で実行すれば、何一つ動かない。

これは、最先端モデルの品質を手放したくない人にとって本当に良いハイブリッド構成になる。ローカルでインデックス化し、ローカルで検索し、答えが優れていなければならないときだけ、質問と検索で得た3つのチャンクをホスト型モデルに送る。コーパスは手元に留まり、その薄い一部だけが、必要なときに限って外へ出る。

このサイトの2つの隣人が、そのパターンを具体的に示している。セルフホストした SearXNG は、検索レイヤーにコーパスではなくオープンウェブ向けのプライベートなフロントエンドを与える。セルフホストしたドキュメントストアはそこにコーパスを与える。この両方に加えてモデルも、ホスト型サービスの1シート分より月額が安いティアに収まる。

モデルの下にあるレイヤー

機微なのはプロンプトの方だ。答えではなく、問いの方。

モデルのプライバシーというと、多くの人はリスクが出力側にあるかのように考える。だが違う。出力はありふれたテキストであり、似たような答えを他の千人も得ている。正体を明かすのは入力の方であり、1年分の入力は組織の姿をかなり完全に描き出す肖像になる。

リクエストログに実際に何が入っているかを考えてみてほしい。要約させるために貼り付けた契約書。分類してほしいと頼んだ、顧客本人が含まれる顧客からのメール。医療の手紙、給与の数字、下書き中だった退職願、公開されていないリポジトリのコード。そしてその周りのメタデータ——どんな質問を、どんな順番で、何時に、どのアドレスから、何か月にわたって。「これが我が社の戦略です」と署名した文書を書く人はいない——だが質問の連なりこそがその文書であり、それをあなた自身が、1回の呼び出しごとに正直に組み立てている。

第1層——エンドポイントが保持するもの。 まともなプロバイダーはまともなポリシーを公開しており、良心的なところは業務用 API のトラフィックで本当に学習しない。だがそれは「保持しない」という約束とは別物だ。リクエストは不正利用監視のため一定期間保存されるのが通例で、定められた条件下でスタッフが閲覧でき、法的手続きのもとで開示されうる——これは大規模プラットフォームの運用として正しいやり方であると同時に、見知らぬ相手にメールで送りたくない文章を置く場所としては正しくない。自分のマシン上のモデルには、自分でログを書かない限りそのような記録は存在しない。

第2層——ログが結びつく身元。 保持されること自体は露出の半分にすぎない。もう半分は、それが結びつく鍵——アカウント、会社名、請求先住所、カードだ。その結びつきこそが「誰かが競合の買収について尋ねた」を「この会社が、あの火曜日に尋ねた」に変える。モデルを式から取り除けば保持は消える。マシンから身元を取り除けば結びつきが消える。メールアドレスも身分証明書もなしに開設し、北欧の法域にあり、Monero で決済する VPS は、この同じ動きのもう半分にあたる。

第3層——自分で書くログ。 セルフホストはリスクを消すのではなく移すだけであり、それがどこに着地するかは冷静に見ておく価値がある。あなたのアプリケーションはおそらく自分のプロンプトをログに残している。リバースプロキシはすべてのリクエスト行をログに残している。2か月前のデバッグセッションが journal に詳細な出力を残していたりする。モデル自体は呼び出しの間に何も保持しないが、その周りの仕組みはすべてを保持しうる——だから何を記録するかを意図的に決め、保持期間を設定し、そのログを、他人には許さなかったはずの基準で扱うこと。

とはいえ、これだけでローカルモデルがそれ自体でプライバシーを保証してくれるわけではない。むしろ、その保証を自分自身の手で与えられる唯一の構成になる、ということだ。テキストは自分が借りたハードウェアの上に留まり、自分が選んだ法域のもとにあり、自分が発行したトークンの背後にあり、それ以外の何にも報告する義務を負わない。

フィールドノート · 6つの落とし穴

がっかりされる6つの理由。そのうち5つは避けられる。

落とし穴01 · メモリ

遅くなるのではなく、箱が固まった

モデルとそのコンテキストキャッシュの合計が RAM を超え、カーネルがトークンごとに重みをページングし始めた。メモリに収めるか、サイズを一段落とすか——中間の設定はない。

落とし穴02 · 露出

誰かがあなたの CPU を使っていた

クライアントを動かすために OLLAMA_HOST を 0.0.0.0 に設定してしまった。この API にはおよそ認証というものが一切なく、11434 はスキャンされている。ループバックと、トークンを確認するプロキシを組み合わせること。

落とし穴03 · 期待

動くことは動く。ただしファックスのようにゆっくり打つ

対話型アシスタント向けに 32B モデルが選ばれた。サイズは用途に合わせる——対話型は小さいモデルを求め、品質を求めるなら非同期にする。

落とし穴04 · コンテキスト

最初のリクエストは問題なく、10回目は這うように遅かった

会話が長くなればキャッシュも大きくなり、ターンごとに履歴全体が読み直される。コンテキストには上限を設け、際限なく追記し続けるのではなく、新しい会話を始めること。

落とし穴05 · 常駐

5ギガバイトが消え、何も動いていない

モデルは最後の呼び出しのあとも常駐し続ける仕様になっている。OLLAMA_KEEP_ALIVE をこの箱に合わせて設定し、他を疑う前に ollama ps を確認すること。

落とし穴06 · ディスク

一度比較しただけのモデルでディスクが埋まった

1つ5ギガバイトの候補が4つ、どれも削除されていない。ollama rm を比較作業の一部にし、ディスクのアラートが鳴ったらモデルディレクトリを確認すること。

FAQ · ローカルモデル

質問、回答済み。

CPU 専用モデルが、想定している仕事に適したツールかどうかを見極める10の質問。

本当に GPU なしで LLM を動かせる?

できる。ただし速度について正直な注意点が一つある。量子化されたモデルは普通のサーバー用 CPU で問題なく動く——重みは RAM に載り、演算量も十分に手が届く範囲で、このプロセスのどこにもグラフィックカードは必要ない。GPU が買ってくれるのはメモリ帯域幅であり、生成速度を決めるのはその帯域幅だ。だから CPU 専用の箱は、モデルにもよるが1秒あたり数語から数十語程度で、正確かつ完全に答える。これはチャット画面には遅いが、多くの人が実際に自動化したい仕事——メッセージの分類、ドキュメントからの構造化 JSON の抽出、ページの要約、検索用のテキストのエンベディング、段落の書き直し——にはまったく問題ない。問うべきは「できるか」ではなく、「どの速度でできて、その速度がこの仕事にとって重要かどうか」だ。

トークン/秒はどれくらい見込める?

誰かのベンチマーク——私たちのものも含めて——を信じるのではなく、自分で計算すること。高密度モデルは1トークンを生成するためにその重みをすべてメモリから読み出すので、上限はおおよそメモリ帯域幅をモデルサイズで割ったものになる。約2 GB に量子化された 3B モデルは、実効20 GB/s のマシンでは上限がおよそ1秒10トークン。4.4 GB の 7B はおよそ4.5。20 GB の 32B は1未満。実際の数字はこの上限より低いところに落ち着く——目安として50〜70パーセント——そしてホスト、同居する他のワークロード、スレッド数によって変わる。プロンプト処理はまったく別の話だ。こちらは計算律速で、何倍も速く終わる。だからこそ、長いドキュメントの要約は快適なのに、大きなモデルとのチャットはそうではない。

8 GB でどのモデルから始めればいい?

Q4_K_M の 8B クラス instructモデルで、4.5〜5 GB あたりに収まり、OS とコンテキストキャッシュの余地を残す。このサイズが今のところの最適解だ——指示に確実に従い、求めればちゃんと妥当な JSON を作り、要約・分類・書き直しをこなせるだけの実力があり、なおかつ応答性を保てるだけ小さい。それより下、3B モデルは分類・タグ付け・ルーティングに本当に使え、速度もおよそ2倍だ。それより上、14B は複数段階の推論で明らかに優れる一方、速度はおよそ半分になる。これはバッチ作業には割の良い取引だが、対話型の用途にはあまり向かない。まず 8B から始めて計測し、その結果が示す方向へ動くこと。

モデルには実際どれだけ RAM が必要?

量子化済みファイルのサイズに、コンテキストキャッシュ、そしてシステム用の余裕を足したもの——その合計が収まらなければならない。失敗の形が「遅くなる」ではなく「破綻する」だからだ。モデルが収まらないと、カーネルはモデルの重みをディスクにスワップし始め、本来4秒で終わる生成が4分かかるようになり、ロードアベレージは十の桁まで上がっていく。Q4_K_M での実用的な目安として、3B モデルは約2 GB、8B は約5 GB、14B は約9 GB、32B は約20 GB、70B は約40 GB。Debian とそのサービス用に2ギガバイト、許容するコンテキストの長さに応じて KV キャッシュ用にさらに1〜4ギガバイトを足す。そのうえで、答えぴったりのティアではなく、その一段上のティアを買うこと。

Ollama と llama.cpp、どっちを使う?

Ollama はまさに llama.cpp であり、それにモデルレジストリと REST API と systemd サービスをまとわせたものだ。特別な理由がない限り Ollama を使う——インストールコマンド1つ、GGUF ファイルを探し回る代わりの ollama pull、OpenAI 互換のエンドポイント、スレッド数とメモリのまともなデフォルト。Ollama が公開していないフラグが欲しいとき、再現性のために特定のビルドを固定したいとき、あるいは1つのモデルを1つの設定でずっと動かし続けたいだけでデーモンに何かを管理させたくないときは、llama.cpp を直接使う。どちらも同じ重みを同じ速度で動かす——違いは完全に運用面にある。

セルフホストしたモデルは大手のホスト型モデルと同じくらい使える?

同じではない。そうではないふりをすると午後を無駄にする。API の向こうにある最先端モデルは、仮想マシンに収まるどんなモデルよりも大きく、難しい推論、長いコンテキスト、コードでは勝る。小さなローカルモデルが本当に競争力を持つのは、実務の巨大な中間層だ——メールが6つのカテゴリのどれに属するかを判定する、請求書から5項目を抽出する、サポートスレッドを要約する、説明文を書き直す、ドキュメントにタグを付ける、2つのレコードが同一人物かを判断する。この種の仕事では、8B と最先端モデルの差はわずかで、コストの差は決定的で、プライバシーの差は絶対的だ。生産的な姿勢は「API を置き換える」ことではなく、「そもそも外に出す必要のなかった90パーセントを送るのをやめる」ことにある。

Ollama に認証機能はある?

ない——まったく何もない。これがこのガイドで最も重要な運用上の事実だ。パスワードもトークンもユーザーモデルもない。ポート 11434 に TCP 接続を開けるものなら何でも、テキストを生成し、モデルを一覧表示し、新しいモデルを pull し、既存のモデルを削除できる。このポートは日常的にスキャンされており、無防備なインスタンスは見つかり次第、見知らぬ相手にタダの計算資源として使われる——最初は謎のロードアベレージとして、後には帯域幅の請求として表面化する。Ollama は 127.0.0.1 に束縛し、前段にリバースプロキシを置き、そこで TLS を終端し、プロキシ側でベアラートークンかクライアント証明書を要求すること。箱の外に必要とするものが何もないなら、そもそも公開しない。

n8n や自分のエージェントランタイムからローカルモデルを使える?

できる。たいていは1つの項目を変えるだけで済む。Ollama は /v1 で OpenAI 互換 API を提供しているので、ベース URL を設定できるクライアント——OpenAI の各種 SDK、LangChain、n8n の OpenAI ノード、たいていのエージェントフレームワーク——は、https://your-host/v1 を指定し、キーとして空でない文字列を送るだけで話せるようになる。n8n には専用の Ollama ノードもある。実際にうまくいくパターンはハイブリッド型だ。大量で退屈な呼び出しの大半をローカルモデルに回し、本当に最先端の推論が必要な一握りのステップだけをホスト型 API に取っておく。ローカル側が妥当な JSON を返さない場合のフォールバックも添えて。

エンベディングは CPU でもやる価値がある?

このページ全体の中で、最もコストパフォーマンスが良いのがこれだ。エンベディングモデルは小さく——ギガバイトどころか数十〜数百メガバイト——チャンクごとに1回の順伝播を行うだけでトークンごとの生成もないため、CPU は気持ちよく処理できる。つまり、RAG システムの検索側全体——ドキュメントのインデックス化、クエリのエンベディング、最も近いチャンクの検索——は最安のティアで快適に動く。しかもそこは、あなたが持つすべてのドキュメントに触れる側でもある。生成のステップはホスト型 API に任せると決めたとしても、エンベディングのステップだけを自分のマシンに移すことで、コーパスを他人の手から遠ざけておける。

API の方が速くて安いのに、なぜモデルをセルフホストするのか?

理由は3つ、重要度の低いものから順に。コストには形がある——API は安いが、それはある地点までの話で、月に5万件のメッセージを分類するワークフローの請求額は伸び続けるのに、$7.90 の VPS はそうならない。可用性——レート制限もなく、組み込んだモデルが廃止されることもなく、他人のステータスページで起きる障害もない。そして決め手になるもの——あなたのプロンプトこそ、あなたが生み出すテキストの中で最も多くを語る。答えではなく、問いの方。何を、誰について、何日に、どんな順番で尋ねたか。ホスト型エンドポイントはそのすべてを、課金上の身元と結びつけて見ている。身分証明書なしで借りたマシン上で、北欧の法域で、Monero で支払って動くモデルは、同じテキストを見ても誰にも報告しない。

サーバーを取得する

あなただけに答えるモデル用の Nordic VPS。KYC 不要、暗号通貨払い。

Garrison(4 vCPU、8 GB、240 GB NVMe、$7.90/月)は、コンテキストキャッシュとシステムの余地を残しつつ 8B モデルを動かせる——たいていの人がまず選ぶべきティアだ。Ravelin はメモリを2倍にして 14B と長いコンテキストに対応する。登録時にメールアドレスは不要、身分証明書も不要、トークン単位の請求もない。

最終レビュー · 2026-08-24 · 出典 · Ollama のドキュメントと API リファレンス、llama.cpp のドキュメント、Caddy リバースプロキシのドキュメント、参照した量子化ビルドの公開モデルカード · 頻度 · 年次