[{"content":"2026年9月15日に、文章を生成しないAIモデルが出ました。TypeSafe AIの「Jev」です。返すのは型のついた値と、確率と、信頼度。人間が読むためではなく、ソフトウェアがそのまま使うための出力です。\nこのサイトは「自分のサーバーで動かした記録」を書いています。なので、最初に確認したのはこれを自前で動かせるのかでした。\n確認できた範囲では、動かせません。 そして、その理由の書かれ方が少し特殊でした。\n確認できたこと Jevのウェイトは公開されていない。 ライセンスはproprietary（専有）で、アーキテクチャも技術論文も公開されていないとされている セルフホストの選択肢について、公式サイト・Cloudflareのドキュメント・Wikipedia・技術メディアの4か所を見ても、記載が1つもなかった 提供はホスト型APIのみ。エンドポイントは api.typesafe.ai/v1/systemone 価格は入力100万トークンあたり$0.042。出力トークンは課金されない（2つの情報源で一致） コンテキスト長については、情報源が食い違っている（後述） 応答時間は70〜500ミリ秒とされている 私はJevを実際には叩いていません。 この記事は公開情報の確認と、自前で同じことをやる場合の計算です。そこは最後にはっきり書きます。\nJevが何を返すのか（最小限） 大規模言語モデルと違い、Jevは自然言語のテキストを返しません。用意されているのは3種類の問い方です。\nプリミティブ 何をするか 返ってくるもの Choice 選択肢から1つ選ぶ（最大255個） 選択肢・確率・信頼度 Score 順序のある段階で評価する スコア・段階別の確率・信頼度 Noul はい／いいえを判定する 0〜1の確率 信頼度は確率分布の形から出しており、高信頼度は自動処理へ、中程度はレビューへ、低信頼度は人間へという振り分けが想定されています。\n「判断だけを返す」というのは、つまりこういうことです。文章を読ませて要約させるのではなく、「この問い合わせは対応が必要か」に0〜1で答えさせる。 用途がはっきり分かれています。\n自前サーバーで動かせるのか 4か所を確認しました。\n確認先 セルフホストに関する記載 TypeSafe AI 公式サイト 記載なし（early accessの案内、コンソール、ドキュメントへのリンクのみ） Cloudflare AI のモデルドキュメント 記載なし（typesafe/jev として第三者製モデルを提供） Wikipedia ライセンスはproprietary。「アーキテクチャ、ウェイト、技術論文のいずれも公開していない」 MarkTechPost 「TypeSafe has not published weights, a parameter count, or a self-hosting option」 注意して書きます。「できない」と断定できるのは、公式が明示的に禁じている場合です。 ここで確認できたのは、そのための情報が公開されていないということです。ウェイトが無ければ動かしようがないので、実務上は「できない」と同じですが、書き方は分けておきます。\nつまりJevを使うということは、判断を外部のAPIに投げるということです。自前サーバーの話とは、前提が逆になります。\n情報が食い違っている点：コンテキスト長 ここは正直に書きます。2つの情報源で、記載が食い違っています。\nCloudflare AI のドキュメント：コンテキストウィンドウ 32,000トークン MarkTechPost：「Context length and model size remain undisclosed（コンテキスト長とモデルサイズは非公開のまま）」 TypeSafe自身が公開していない数字を、提供事業者であるCloudflareが自社ドキュメントに書いている、という形です。どちらが正しいのかは、私には判断できませんでした。\nCloudflare経由で使う場合は32,000で考えてよさそうですが、TypeSafeのAPIを直接叩く場合に同じとは限りません。 長い入力を投げる設計にするなら、ここは自分で確かめてください。\n同じことを自前の小型モデルでやれるか 「判断だけ返してほしい」なら、自前の小型モデルでもできそうに見えます。実測した範囲では、厳しいです。\nさくらのVPS 2Gプラン（GPUなし・CPUのみ）で測った数字です。\n実測値 Ollama本体の常駐メモリ 36MB 0.5Bモデルの生成速度 15.36 tok/s 0.5Bのロード時間 3.18秒 1Bモデルの生成速度 0.07 tok/s（実用外） 必要メモリ モデルファイル × 約2.4 速度の問題より、性質の問題のほうが大きいと考えています。\n0.5Bクラスに判断させると、出力が安定しません。 実際、日本語で答えさせたときに「東京」が簡体字の「东京」になりました。文章としては読めますが、これを機械が受け取る前提の構造化データにするには、後段で整形と検証が要ります。 Jevが返すのは最初から型のついた値と確率なので、そこが要りません。\n加えて、Ollamaは既定で5分アイドルするとモデルをメモリから降ろします。 つまり、たまにしか呼ばない判断処理だと、毎回ロード時間を払い直すことになります。詳しくはOllamaの使い方に書きました。Jevの応答は70〜500ミリ秒とされているので、この用途では桁が違います。\n費用はどこで逆転するか ここからは計算値です。 実測ではありません。\nJevの価格は入力100万トークンあたり$0.042、出力は無課金。仮に1件の判断で入力500トークンを使うとすると、\n500トークン ÷ 1,000,000 × $0.042 = $0.000021 / 件 一方、自前で動かす側は固定費です。さくらのVPS 2Gプランは月額1,706円（2026年9月時点の公式価格・税込）。1ドル150円と仮定すると約$11.37。\n$11.37 ÷ $0.000021 ≒ 約54万件 / 月 月に54万件、1日あたり18,000件の判断を回して、ようやく費用が並びます。 そこまで行かないなら、Jevを呼ぶほうが安いという計算になります。\nただし前提が1つあります。上の計算は、この用途のためにVPSを新しく借りる場合の話です。 私のように、すでに別の用途でVPSを借りていて空きメモリがある場合、Ollamaを追加で動かす費用はゼロです。その場合、比較の土台が変わります。 プランの積み上げはAI用途のVPSは何GB必要かに書きました。\nそれでも自前を選ぶ理由があるとすれば 費用と速度では、判断タスクに関して自前の小型モデルに勝ち目が見えませんでした。それでも自前を選ぶ理由があるとすれば、費用ではありません。\nデータを外に出せない。 要件として決まっている場合、比較の問題ではなくなります 外部サービスの終了や仕様変更に縛られたくない。 ウェイトが手元にあるかどうかの差です 「自前AI」という名前のサイトですが、自前が常に正しいとは書きません。 測って、計算して、負けているところは負けていると書きます。判断だけを返すAPIが$0.042/100万トークンで使えるなら、判断タスクを自前の0.5Bで回す理由は、上の2つ以外に見つかりませんでした。\nこの記事が書けなかったこと 私はJevを実際に使っていません。 公式サイト、Cloudflareのドキュメント、Wikipedia、技術メディアの記載を確認しただけです。精度も速度も自分では測っていません コンテキスト長はどちらが正しいか判断できませんでした（Cloudflareは32,000、TypeSafeは非公開） 一般公開の時期を確認できませんでした。 2026年9月22日時点で、公式サイトには early access の案内が出ています モデルサイズもアーキテクチャも公開されていないので、なぜ速くて安いのかは説明できません 1ドル150円という前提で計算しています。 為替で結論の分岐点は動きます 0.5Bで判断タスクをやらせる実験はしていません。 生成速度と日本語品質の実測から「厳しい」と書きましたが、判定精度そのものは測っていません 出典 Jev (AI model) - Wikipedia（ライセンス、ウェイト非公開、公開日／2026年9月22日確認） TypeSafe AI 公式サイト（early accessの案内、入力価格／2026年9月22日確認） Jev (typesafe) · Cloudflare AI docs（モデルID、コンテキストウィンドウ、入出力仕様／2026年9月22日確認） TypeSafe AI Releases Jev - MarkTechPost（プリミティブの仕様、価格、セルフホストに関する記載／2026年9月22日確認） 実測値は当サイトの測定による（さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / GPUなし / Ollama 0.33.3） 関連記事 GPUなしでローカルLLMは使えるのか — 自前で動かす場合に載るモデルの決め方 Ollamaの使い方 — 5分でアンロードされる話とロード時間 VPSにローカルLLMを構築する — 自前側の構築手順 ","permalink":"https://jimae-ai.com/jev-self-host/","summary":"\u003cp\u003e2026年9月15日に、\u003cstrong\u003e文章を生成しないAIモデル\u003c/strong\u003eが出ました。TypeSafe AIの「Jev」です。返すのは型のついた値と、確率と、信頼度。人間が読むためではなく、\u003cstrong\u003eソフトウェアがそのまま使うための出力\u003c/strong\u003eです。\u003c/p\u003e\n\u003cp\u003eこのサイトは「自分のサーバーで動かした記録」を書いています。なので、最初に確認したのは\u003cstrong\u003eこれを自前で動かせるのか\u003c/strong\u003eでした。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e確認できた範囲では、動かせません。\u003c/strong\u003e そして、その理由の書かれ方が少し特殊でした。\u003c/p\u003e\n\u003ch2 id=\"確認できたこと\"\u003e確認できたこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eJevのウェイトは公開されていない。\u003c/strong\u003e ライセンスはproprietary（専有）で、\u003cstrong\u003eアーキテクチャも技術論文も公開されていない\u003c/strong\u003eとされている\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eセルフホストの選択肢について、公式サイト・Cloudflareのドキュメント・Wikipedia・技術メディアの4か所を見ても、記載が1つもなかった\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e提供はホスト型APIのみ。エンドポイントは \u003ccode\u003eapi.typesafe.ai/v1/systemone\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e価格は入力100万トークンあたり$0.042。出力トークンは課金されない\u003c/strong\u003e（2つの情報源で一致）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eコンテキスト長については、情報源が食い違っている\u003c/strong\u003e（後述）\u003c/li\u003e\n\u003cli\u003e応答時間は70〜500ミリ秒とされている\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e私はJevを実際には叩いていません。\u003c/strong\u003e この記事は公開情報の確認と、自前で同じことをやる場合の計算です。そこは最後にはっきり書きます。\u003c/p\u003e\n\u003ch2 id=\"jevが何を返すのか最小限\"\u003eJevが何を返すのか（最小限）\u003c/h2\u003e\n\u003cp\u003e大規模言語モデルと違い、Jevは自然言語のテキストを返しません。用意されているのは3種類の問い方です。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eプリミティブ\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e何をするか\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e返ってくるもの\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eChoice\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e選択肢から1つ選ぶ（最大255個）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e選択肢・確率・信頼度\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eScore\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e順序のある段階で評価する\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eスコア・段階別の確率・信頼度\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eNoul\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eはい／いいえを判定する\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e0〜1の確率\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e信頼度は確率分布の形から出しており、\u003cstrong\u003e高信頼度は自動処理へ、中程度はレビューへ、低信頼度は人間へ\u003c/strong\u003eという振り分けが想定されています。\u003c/p\u003e\n\u003cp\u003e「判断だけを返す」というのは、つまりこういうことです。\u003cstrong\u003e文章を読ませて要約させるのではなく、「この問い合わせは対応が必要か」に0〜1で答えさせる。\u003c/strong\u003e 用途がはっきり分かれています。\u003c/p\u003e\n\u003ch2 id=\"自前サーバーで動かせるのか\"\u003e自前サーバーで動かせるのか\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e4か所を確認しました。\u003c/strong\u003e\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e確認先\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eセルフホストに関する記載\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eTypeSafe AI 公式サイト\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e記載なし\u003c/strong\u003e（early accessの案内、コンソール、ドキュメントへのリンクのみ）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eCloudflare AI のモデルドキュメント\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e記載なし\u003c/strong\u003e（\u003ccode\u003etypesafe/jev\u003c/code\u003e として第三者製モデルを提供）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eWikipedia\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eライセンスは\u003cstrong\u003eproprietary\u003c/strong\u003e。「アーキテクチャ、ウェイト、技術論文のいずれも公開していない」\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eMarkTechPost\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e「TypeSafe has not published weights, a parameter count, or a self-hosting option」\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e注意して書きます。「できない」と断定できるのは、公式が明示的に禁じている場合です。\u003c/strong\u003e ここで確認できたのは、\u003cstrong\u003eそのための情報が公開されていない\u003c/strong\u003eということです。ウェイトが無ければ動かしようがないので、実務上は「できない」と同じですが、書き方は分けておきます。\u003c/p\u003e\n\u003cp\u003eつまり\u003cstrong\u003eJevを使うということは、判断を外部のAPIに投げるということ\u003c/strong\u003eです。自前サーバーの話とは、前提が逆になります。\u003c/p\u003e\n\u003ch2 id=\"情報が食い違っている点コンテキスト長\"\u003e情報が食い違っている点：コンテキスト長\u003c/h2\u003e\n\u003cp\u003eここは正直に書きます。\u003cstrong\u003e2つの情報源で、記載が食い違っています。\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCloudflare AI のドキュメント\u003c/strong\u003e：コンテキストウィンドウ \u003cstrong\u003e32,000トークン\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMarkTechPost\u003c/strong\u003e：「Context length and model size remain undisclosed（コンテキスト長とモデルサイズは非公開のまま）」\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTypeSafe自身が公開していない数字を、提供事業者であるCloudflareが自社ドキュメントに書いている\u003c/strong\u003e、という形です。どちらが正しいのかは、\u003cstrong\u003e私には判断できませんでした。\u003c/strong\u003e\u003c/p\u003e","title":"Jevは自前サーバーで動かせるのか｜公式の記載を確認して、自前の0.5Bと費用を比べた"},{"content":"Ollamaのコマンドは、覚えることがほとんどありません。pull して run するだけです。\n詰まるのはコマンドではなく、その裏側です。 pullが何分かかるのか。1回目の応答だけ異常に遅いのはなぜか。使い終わったメモリはいつ返ってくるのか。このあたりは、動かしてみるまで分かりません。\nさくらのVPS 2Gプラン（Ubuntu 24.04・GPUなし・CPUのみ）で測った数字と、公式ドキュメントの記載を突き合わせました。\n確認できたこと pull は 0.5Bで38.6秒、1Bで2分4秒、3Bで2分56秒。ディスクはそれぞれ +380MB / +1,260MB / +1,840MB 増えた 1回目の応答が遅いのはモデルのロード時間。0.5Bで3.18秒、1Bでは43.6秒かかった モデルは既定で5分間メモリに保持され、そのあとアンロードされる（公式ドキュメントの記載） つまり5分以上間を空けると、あのロード時間がもう一度発生する ollama ps の Processor 列を見れば、CPUで動いているかGPUで動いているかが分かる（公式の記載。100% CPU のように出る） Ollama本体は常駐36MB。ディスクは2.1GB。モデルを3つ入れた時点で合計3.4GBだった 実測値は「実測」、公式ドキュメントの記載は「公式」と書き分けます。\n基本のコマンドと、実際にかかった時間 コマンド 何をするか このサーバーでの実測 ollama pull \u0026lt;model\u0026gt; モデルを取得する 0.5B: 38.6秒 / 1B: 2分4秒 / 3B: 2分56秒 ollama run \u0026lt;model\u0026gt; \u0026quot;...\u0026quot; 1回だけ実行する 初回はロード時間が乗る（後述） ollama list 入っているモデルを見る 即時 ollama ps いま動いているモデルを見る 即時。Processor列が重要 ollama rm \u0026lt;model\u0026gt; モデルを消す 未測定 ollama serve サーバーとして起動する systemdに任せている 覚えるのはこれで足りました。 以下は、この表に書ききれない裏側です。\npull：待ち時間はモデルのサイズにほぼ比例する 3つのモデルを入れたときの実測です。\nモデル 所要時間 ディスクの実増 qwen2.5:0.5b 38.6秒 +380MB llama3.2:1b 2分4秒 +1,260MB qwen2.5:3b 2分56秒 +1,840MB ディスクは、Ollama本体の2.1GBが先に乗っています。 3つ入れた時点で合計3.4GBでした。\nollama list に出るサイズと df で見た増加がずれることがありますが、これはOllamaが10進のMB、du や df が2進のMiBで表示しているためです。同じ値です。\nrun：1回目だけ遅いのはロード時間 ここが、いちばん誤解されやすい場所です。\nモデル ロード時間 生成速度 qwen2.5:0.5b 3.18秒 15.36 tok/s llama3.2:1b 43.6秒 0.07 tok/s 0.5Bなら3秒で、体感としては「少し待つ」程度です。1Bでは43.6秒かかりました。このロード時間は、生成が始まる前に発生します。 プロンプトを投げて40秒間なにも起きないので、固まったように見えます。\n1Bのほうは生成そのものも 0.07 tok/s まで落ちていて、9トークンの返事に合計3分かかりました。なぜここで崖が来るのかは2GBのVPSでローカルLLMは動くのかに書いています。\nメモリは5分で返る。そしてまたロードし直す 公式ドキュメントに、はっきり書かれています。\nHow do I keep a model loaded in memory or make it unload immediately? By default models are kept in memory for 5 minutes before being unloaded.\n既定では5分です。 そして keep_alive で変えられます。公式の記載では、負の数（-1 や \u0026quot;-1m\u0026quot;）を渡すとメモリに保持し続け、0 を渡すと応答を返した直後にアンロードします。\nこの5分という数字は、上のロード時間と組み合わせると意味が変わります。\n5分以内に続けて使うなら、ロード時間は最初の1回だけ 5分以上空けると、43.6秒をもう一度払う つまり、たまにしか呼ばない使い方がいちばん割に合いません。 1日に数回、思い出したように呼ぶ用途だと、毎回ロード待ちが発生します。逆に、まとめて処理を回すなら最初の1回で済みます。\nメモリを常に空けておきたいなら keep_alive: 0、応答を速くしたいなら負の数、という選び方になります。私が使っているのは既定の5分のままです。 同居しているサービスがあるので、使っていないメモリは返してほしいためです。\n公式には、空のリクエストを送ってモデルを先に読み込ませておく方法も書かれています（プリロード）。応答時間を短くしたい場合の手です。\nollama ps で、CPUで動いているのかが分かる 公式ドキュメントの該当項目は「モデルがGPUに載ったかどうかを確かめる方法」です。\nHow can I tell if my model was loaded onto the GPU? ollama ps command to see what models are currently loaded into memory.\n出力の Processor 列に、100% GPU / 100% CPU / 48%/52% CPU/GPU のような値が出ます。\nGPUのないサーバーなら 100% CPU になります。 ここを確認しておくと、「GPUがあるつもりだったのに使われていなかった」という取り違えを避けられます。GPUなしの環境で何がどこまで動くかはGPUなしでローカルLLMは使えるのかにまとめました。\nモデルはどこに置かれるか 公式ドキュメントの記載です。\nOS 保存場所 Linux /usr/share/ollama/.ollama/models macOS ~/.ollama/models Windows C:\\Users\\%username%\\.ollama\\models Linuxの保存先が ollama ユーザーのホーム配下にある点は、覚えておく価値があります。ディスクの使用量を調べるときに、ここを見ずに ~/.ollama を探すと何も出てきません。\nモデルを消したとき、ディスクは戻るのか 測っていません。\nollama rm を実行していないので、pullで増えた分と同じだけ戻るのかを確認していません。「戻るはずです」とは書きません。\nただし、この種の「消したのに戻らない」は実際に踏んでいます。 同じサーバーでDockerを掃除したとき、docker system prune で消えたのは13GBのうち79.75MBだけでした。イメージには一切触らず、ボリュームも容量の99.1%が既定のprune では残ります。詳細はdocker system prune では13GBが1バイトも消えなかったに書きました。\nディスクの回収は、コマンドを打った結果を df で確かめるまで信用しないほうがいいというのが、そこから得た教訓です。Ollamaでも同じ姿勢で確認することをすすめます。\n使えるモデルの一覧はどこで見るか ollama list で見えるのはすでに入れたモデルだけです。これから入れられるモデルの一覧は、Ollamaの公式ライブラリにあります。\n見るべきなのはダウンロードサイズです。GPUのない環境では、必要メモリがそこからほぼ決まります。\n必要メモリの目安 ≒ モデルファイルのサイズ × 2.4 この2.4倍は実測から出した値です（0.5Bのファイル380MBに対し、メモリのピークが実測930MB）。公式ライブラリのサイズから逆算した早見表はGPUなしでローカルLLMは使えるのかにあります。\nライセンスもモデルごとに違います。 同じQwen2.5でも、公式ライブラリには「3Bと72B以外はApache 2.0、3Bと72BはQwenライセンス」と書かれています。商用で使うなら、サイズ単位で確認してください。\nこの記事が書けなかったこと ollama rm の実測をしていません。 ディスクが戻るかどうかを確認していません keep_alive を変えたときの挙動を測っていません。 公式の記載を引用しただけです プリロードも試していません すべてGPUなし・CPUのみの数字です。 GPUがある環境では、ロード時間も生成速度も別物になります Ollama 0.33.3 の時点の話です 出典 Ollama Docs FAQ（keep_alive と5分の既定値、モデルの保存場所、ollama ps の Processor 列、プリロード／2026年9月17日確認） Ollama公式ライブラリ（モデルのサイズとライセンス記載） 実測値は当サイトの測定による（さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / GPUなし / Ollama 0.33.3） 関連記事 VPSにローカルLLMを構築する — インストールと、認証がないことへの備え GPUなしでローカルLLMは使えるのか — 載るモデルの決め方と早見表 2GBのVPSでローカルLLMは動くのか — ロード時間と生成速度の全記録 ","permalink":"https://jimae-ai.com/ollama-commands/","summary":"\u003cp\u003eOllamaのコマンドは、覚えることがほとんどありません。\u003ccode\u003epull\u003c/code\u003e して \u003ccode\u003erun\u003c/code\u003e するだけです。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e詰まるのはコマンドではなく、その裏側です。\u003c/strong\u003e pullが何分かかるのか。1回目の応答だけ異常に遅いのはなぜか。使い終わったメモリはいつ返ってくるのか。\u003cstrong\u003eこのあたりは、動かしてみるまで分かりません。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eさくらのVPS 2Gプラン（Ubuntu 24.04・GPUなし・CPUのみ）で測った数字と、公式ドキュメントの記載を突き合わせました。\u003c/p\u003e\n\u003ch2 id=\"確認できたこと\"\u003e確認できたこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003epull\u003c/code\u003e は 0.5Bで38.6秒、1Bで2分4秒、3Bで2分56秒\u003c/strong\u003e。ディスクはそれぞれ +380MB / +1,260MB / +1,840MB 増えた\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e1回目の応答が遅いのはモデルのロード時間\u003c/strong\u003e。0.5Bで3.18秒、1Bでは43.6秒かかった\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eモデルは既定で5分間メモリに保持され、そのあとアンロードされる\u003c/strong\u003e（公式ドキュメントの記載）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eつまり5分以上間を空けると、あのロード時間がもう一度発生する\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003eollama ps\u003c/code\u003e の Processor 列を見れば、CPUで動いているかGPUで動いているかが分かる\u003c/strong\u003e（公式の記載。\u003ccode\u003e100% CPU\u003c/code\u003e のように出る）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOllama本体は常駐36MB。ディスクは2.1GB\u003c/strong\u003e。モデルを3つ入れた時点で合計3.4GBだった\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e実測値は「実測」、公式ドキュメントの記載は「公式」と書き分けます。\u003c/p\u003e\n\u003ch2 id=\"基本のコマンドと実際にかかった時間\"\u003e基本のコマンドと、実際にかかった時間\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eコマンド\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e何をするか\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eこのサーバーでの実測\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama pull \u0026lt;model\u0026gt;\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eモデルを取得する\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e0.5B: \u003cstrong\u003e38.6秒\u003c/strong\u003e / 1B: \u003cstrong\u003e2分4秒\u003c/strong\u003e / 3B: \u003cstrong\u003e2分56秒\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama run \u0026lt;model\u0026gt; \u0026quot;...\u0026quot;\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1回だけ実行する\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e初回はロード時間が乗る（後述）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama list\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e入っているモデルを見る\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e即時\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama ps\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eいま動いているモデルを見る\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e即時。\u003cstrong\u003eProcessor列が重要\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama rm \u0026lt;model\u0026gt;\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eモデルを消す\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e未測定\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003eollama serve\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eサーバーとして起動する\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003esystemdに任せている\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e覚えるのはこれで足りました。\u003c/strong\u003e 以下は、この表に書ききれない裏側です。\u003c/p\u003e","title":"Ollamaの使い方｜コマンドが実際に何秒かかって何MB増えるのかを実測した"},{"content":" 本記事はプロモーションを含みます。 記事内の一部のリンクは広告リンクです。リンクの有無で内容を変えていません。 掲載している数値はすべて自分のサーバーで実際に測った値か、公式ドキュメントの記載です。\nローカルLLMの構築記事を探すと、出てくるのは自分のPC（WindowsやMac、自作機）か、自社サーバー（ハードウェアを買う話）のどちらかです。\nVPSに立てる話が、ほとんど見つかりません。\n私は、さくらのVPS 2Gプラン（GPUなし・CPUのみ）にOllamaを入れて動かしています。その過程で、PCに入れるのとは違う問題に2つぶつかりました。 どちらも、PCなら起きないか、起きても実害が出ないものです。\n確認できたこと 公式のインストールスクリプトは、1.34GBを一発勝負で落とす構造。実測で89分かけて55.6%で切れた。途中から再開できない wget -c で落としてから展開すれば2分1秒で終わった 公式のアップグレード手順も、同じスクリプトの再実行。つまり更新のたびに同じ賭けをする Ollamaに認証はない。 公式ドキュメントには「公開のしかた」は書いてあるが、公開したあと誰が叩けるのかは書かれていない systemdでメモリ枠を切ると、モデルが暴れても同居しているサービスが巻き添えにならない PCに入れるのとVPSに入れるのは、前提が3つ違う 自分のPC VPS GPU 載っていることがある 基本的にない 稼働 使うときだけ 24時間動き続ける ネットワーク 家庭内LANの内側 グローバルIPで直結 3つ目が、この記事のいちばん重要な点です。 自分のPCで OLLAMA_HOST を広げても、届くのは家の中だけです。VPSで同じことをすると、インターネット全体から届きます。\nGPUがないことの影響（どのモデルまで載るか）はGPUなしでローカルLLMは使えるのかに分けて書きました。この記事は構築の手順と、立てたあとの安全に絞ります。\n公式の「3行」は、1.34GBの一発勝負 Ollamaの公式インストール手順はこれです。\ncurl -fsSL https://ollama.com/install.sh | sh これを実行したら、89分かけて55.6%で切れました。\ncurl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1) tar: Unexpected EOF in archive tar: Error is not recoverable: exiting now やり直しです。 このスクリプトは curl | zstd -d | tar -x と直結していて、ダウンロードしながら展開しています。 そのため途中で切れても再開できません。\n配布物は 1,433,825,108バイト（1.34GB）。これを一発で落とし切る必要があります。\n原因は特定できていません。 失敗の直後に同じURLへ curl を投げたら 10.8 MB/s 出ました。配布元が常に遅いわけではありません。あの時間帯だけ経路が細かった可能性が高いですが、確証はありません。\nただし対処は原因に関係なく有効です。 1.34GBを一発勝負で落とす構造そのものが弱い。\nそしてこれは、インストール時だけの問題ではありません。 公式ドキュメントのアップグレード手順は、同じスクリプトの再実行です。\nHow can I upgrade Ollama? （中略）curl -fsSL https://ollama.com/install.sh | sh\nつまり更新のたびに、同じ賭けをすることになります。 自分のPCなら失敗しても「もう一度やる」で済みますが、VPSは稼働中のサーバーです。 深夜に90分かけて失敗する運用を、繰り返す理由はありません。\n手順：落としてから展開する 同じ配布物がGitHubのリリースにあります。こちらを wget -c で落とします。\nwget -c --tries=0 --waitretry=15 --timeout=60 \\ https://github.com/ollama/ollama/releases/download/v0.33.3/ollama-linux-amd64.tar.zst 2026-09-07 20:55:24 (11.3 MB/s) - saved [1433825108/1433825108] 2分1秒で完了しました。 89分の失敗のあと、同じ回線で、です。\nwget -c を使う理由は2つあります。\n-c は途中から再開できる。 切れても最初からになりません wgetはHTTP/1.1しか使わない。 さきほどの HTTP/2 PROTOCOL_ERROR は起きません 落としたら、壊れていないか確認してから展開します。\nzstd -t ollama-linux-amd64.tar.zst sudo install -o0 -g0 -m755 -d /usr/local/bin /usr/local/lib/ollama sudo tar --zstd -xf ollama-linux-amd64.tar.zst -C /usr/local 展開は10.9秒でした。\nOllamaに認証はない。公式も書いていない ここがVPSでいちばん危険な場所です。\n公式ドキュメントのFAQには、ネットワークに公開する方法が書かれています。\nHow can I expose Ollama on my network? Ollama binds 127.0.0.1 port 11434 by default. Change the bind address with the OLLAMA_HOST environment variable.\n書いてあるのは、ここまでです。\n私が2026年9月13日に確認した範囲では、このFAQに「公開したAPIを誰が叩けるのか」「認証をどうするのか」という記載はありません。 プロキシの節ではnginxでポート11434へ転送する例が示されていますが、そこにも認証の話は出てきません。\nつまり、OLLAMA_HOST=0.0.0.0:11434 としてVPSで起動した時点で、そのAPIは世界中の誰でも叩ける状態になります。 ポートスキャンで見つかれば、他人のサーバーでモデルを回されます。CPUだけのVPSなら、それだけでサービスが止まります。\nだから既定値のまま縛ります。\nEnvironment=\u0026#34;OLLAMA_HOST=127.0.0.1:11434\u0026#34; 既定値も 127.0.0.1 なので、書かなくても同じ動きです。それでも明示して書き残します。 「意図してローカルに縛った」と分かる状態にしておかないと、あとから設定を触る人（半年後の自分を含む）が、軽い気持ちで 0.0.0.0 にします。\n外から使いたい場合の選択肢は、私が確認した範囲では次のとおりです。\n方法 認証 備考 SSHポートフォワード SSHの鍵 追加のソフトが要らない。いちばん簡単 nginxのリバースプロキシ＋Basic認証 Basic認証 公式FAQにプロキシの例はあるが、認証の例はない VPNの内側に置く VPN 構成が増える 私が使っているのはSSHポートフォワードだけです。 下2つは構成として妥当だと考えていますが、このサーバーでは試していません。 試していないものを「おすすめ」とは書きません。\nsystemdのunitと、メモリ枠を切る理由 配布物にサービス定義は含まれていないので、自分で書きます。\nsudo useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama sudo tee /etc/systemd/system/ollama.service \u0026gt; /dev/null \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/local/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment=\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0026#34; Environment=\u0026#34;OLLAMA_HOST=127.0.0.1:11434\u0026#34; MemoryMax=1200M MemorySwapMax=1024M [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload \u0026amp;\u0026amp; sudo systemctl enable --now ollama MemoryMax と MemorySwapMax が、VPSならではの部分です。\nVPSには、たいてい他のものが同居しています。私のサーバーでは、静的サイトと業務アプリが動いています。枠を切らずにモデルを載せて失敗すると、巻き添えで全部が止まります。\n実際、枠を超えたときに何が起きるかは測りました。1Bのモデルを載せたとき、枠に5万回以上当たり、生成速度は0.07 tokens/秒まで落ちました（実測の全記録）。このとき枠を切っていなければ、同じ状態がサーバー全体で起きていたはずです。\n枠があると、壊れるのはOllamaだけで済みます。 Restart=always を書いてあるので、落ちても3秒後に戻ります。\n数字は自分の環境に合わせてください。私の環境ではOSのメンテナンス用に最低300MBを空けています。目安は、空きメモリから他のサービス用の余裕を引いた残りです。\nどのモデルを載せるか 構築が終わったら、載せるモデルを決めます。GPUがない環境では、上限はほぼ計算で決まります。\n載せられるモデルファイル ≒ 空きメモリ ÷ 2.4 この2.4倍は実測から出した値です。そして、この計算を外れた瞬間に速度は崖から落ちます（0.5Bで15.36 tok/s、1Bで0.07 tok/s）。モデル別の早見表はGPUなしでローカルLLMは使えるのかにまとめました。\n費用：VPSとクラウドAPI、どちらが安いか 正直に書きます。用途が小さいなら、APIのほうが安いです。\nさくらのVPS 2Gプランは月額1,706円（2026年9月時点の公式価格・税込）。これは使っても使わなくても固定で出ていきます。 一方、クラウドのAPIは従量課金です。月に数百回しか呼ばないなら、APIのほうが安く済みます。\nVPSが有利になるのは、次のどれかに当てはまるときです。\nデータを外に出せない。 費用の比較ではなく、要件として決まっている場合 常時・大量に呼ぶ。 固定費を上回るだけの回数を回す場合 すでにVPSを借りていて、余っている。 私の場合はこれです。業務システムを載せているサーバーの空きメモリで動かしているので、Ollamaのために増やした費用はゼロです 3つ目は見落とされがちですが、実際にはいちばん現実的だと思います。 Ollama本体の常駐メモリは36MBで、使っていないときのコストはほぼゼロだからです。\nプラン別の積み上げはAI用途のVPSは何GB必要かに書きました。価格・仕様は変わるので、申し込む前に公式の最新情報を確認してください。\nさくらのVPS公式：https://vps.sakura.ad.jp/\n（上記は広告リンクです。この記事の手順と結論は、提携の有無とは無関係です。 上に書いたとおり、用途によってはAPIのほうが安いとも書いています。）\nこの記事が書けなかったこと nginx＋Basic認証とVPNは、このサーバーでは試していません。 構成として妥当だと考えているだけです Ollamaが実際に攻撃を受けた事例は確認していません。 「認証がない」ことと「公式に記載がない」ことを確認しただけで、被害の統計は持っていません バージョンは0.33.3の時点の話です。 配布方法もドキュメントも変わります MemoryMax の最適値は測っていません。 1,200MBは私の環境で他のサービスを守れる値として決めたもので、最適化した結果ではありません GPUありのVPSは扱っていません 出典 Ollama Docs FAQ（OLLAMA_HOST の既定値と変更方法、アップグレード手順、プロキシの例／2026年9月13日確認） Ollama GitHub Releases（配布物の入手先） 実測値は当サイトの測定による（さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / GPUなし / Ollama 0.33.3） 関連記事 GPUなしでローカルLLMは使えるのか — 載るモデルの決め方と早見表 2GBのVPSでローカルLLMは動くのか — 0.5B・1B・3Bの実測の全記録 AI用途のVPSは何GB必要か — プランの積み上げと、余裕の取り方 ","permalink":"https://jimae-ai.com/local-llm-vps-setup/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e本記事はプロモーションを含みます。\u003c/strong\u003e 記事内の一部のリンクは広告リンクです。\u003cstrong\u003eリンクの有無で内容を変えていません。\u003c/strong\u003e 掲載している数値はすべて自分のサーバーで実際に測った値か、公式ドキュメントの記載です。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eローカルLLMの構築記事を探すと、出てくるのは\u003cstrong\u003e自分のPC\u003c/strong\u003e（WindowsやMac、自作機）か、\u003cstrong\u003e自社サーバー\u003c/strong\u003e（ハードウェアを買う話）のどちらかです。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eVPSに立てる話が、ほとんど見つかりません。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e私は、さくらのVPS 2Gプラン（GPUなし・CPUのみ）にOllamaを入れて動かしています。その過程で、\u003cstrong\u003ePCに入れるのとは違う問題に2つぶつかりました。\u003c/strong\u003e どちらも、PCなら起きないか、起きても実害が出ないものです。\u003c/p\u003e\n\u003ch2 id=\"確認できたこと\"\u003e確認できたこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e公式のインストールスクリプトは、1.34GBを一発勝負で落とす構造\u003c/strong\u003e。実測で\u003cstrong\u003e89分かけて55.6%で切れた\u003c/strong\u003e。途中から再開できない\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003ewget -c\u003c/code\u003e で落としてから展開すれば2分1秒\u003c/strong\u003eで終わった\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e公式のアップグレード手順も、同じスクリプトの再実行\u003c/strong\u003e。つまり更新のたびに同じ賭けをする\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOllamaに認証はない。\u003c/strong\u003e 公式ドキュメントには「公開のしかた」は書いてあるが、\u003cstrong\u003e公開したあと誰が叩けるのかは書かれていない\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003esystemdでメモリ枠を切る\u003c/strong\u003eと、モデルが暴れても同居しているサービスが巻き添えにならない\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"pcに入れるのとvpsに入れるのは前提が3つ違う\"\u003ePCに入れるのとVPSに入れるのは、前提が3つ違う\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e自分のPC\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eVPS\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eGPU\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e載っていることがある\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e基本的にない\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e稼働\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e使うときだけ\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e24時間動き続ける\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eネットワーク\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e家庭内LANの内側\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eグローバルIPで直結\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e3つ目が、この記事のいちばん重要な点です。\u003c/strong\u003e 自分のPCで \u003ccode\u003eOLLAMA_HOST\u003c/code\u003e を広げても、届くのは家の中だけです。VPSで同じことをすると、\u003cstrong\u003eインターネット全体から届きます。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eGPUがないことの影響（どのモデルまで載るか）は\u003ca href=\"/local-llm-cpu-only/\"\u003eGPUなしでローカルLLMは使えるのか\u003c/a\u003eに分けて書きました。この記事は\u003cstrong\u003e構築の手順と、立てたあとの安全\u003c/strong\u003eに絞ります。\u003c/p\u003e\n\u003ch2 id=\"公式の3行は134gbの一発勝負\"\u003e公式の「3行」は、1.34GBの一発勝負\u003c/h2\u003e\n\u003cp\u003eOllamaの公式インストール手順はこれです。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ecurl -fsSL https://ollama.com/install.sh \u003cspan class=\"p\"\u003e|\u003c/span\u003e sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eこれを実行したら、89分かけて55.6%で切れました。\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ecurl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003etar: Unexpected EOF in archive\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003etar: Error is not recoverable: exiting now\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eやり直しです。\u003c/strong\u003e このスクリプトは \u003ccode\u003ecurl | zstd -d | tar -x\u003c/code\u003e と直結していて、\u003cstrong\u003eダウンロードしながら展開しています。\u003c/strong\u003e そのため途中で切れても再開できません。\u003c/p\u003e","title":"VPSにローカルLLMを構築する｜公式の「3行」が89分で失敗した話と、認証がないことへの備え"},{"content":"「GPUがないパソコンやサーバーでローカルLLMは動くのか」。動きます。ただし、載せられるモデルの大きさは、ほぼ計算で決まります。\n載せられるモデルファイル ≒ 空きメモリ ÷ 2.4 この2.4という倍率は、GPUなしのVPSで実際に測って出した値です。そしてこの計算を外れた瞬間、速度は段階的にではなく崖のように落ちます。\n確認できたこと 必要メモリの目安はモデルファイルの約2.4倍。0.5Bのモデル（380MB）で実測930MBだった 0.5Bは15.36 tokens/秒で動き、1Bでは0.07 tokens/秒に落ちた。219分の1。段階的ではなく崖 Ollamaの公式ドキュメントには、必要メモリの記載がない。2026年9月13日に確認した 重いのはツールではなくモデル。Ollama本体の常駐メモリは36MBで、Dockerの49MBより軽い 先に埋まるのはメモリではなくディスクのことがある。Ollama本体だけで2.1GB 商用利用の可否はモデルごとに違う。同じQwen2.5でもサイズによってライセンスが分かれている この記事の数字には実測値と計算値が混ざっています。 どちらなのかは、その都度書きます。\n載るモデルは「空きメモリ ÷ 2.4」で決まる 出発点は、GPUのないVPSで測った1本の実測値です。\nモデルファイル 380MB → 実際のメモリピーク 930MB（2.4倍） さくらのVPS 2Gプラン、Ubuntu 24.04、GPUなし・CPUのみ。qwen2.5:0.5b を載せたときの値です。測定の詳細は2GBのVPSでローカルLLMは動くのかに書きました。\nこの倍率で逆算すると、載せられるモデルの上限が出ます。\n載せられるモデルファイル ≒ 空きメモリ ÷ 2.4 同じ実測から、1Bのモデルが動かない理由も説明がつきます。 1Bのファイルは1,260MB。2.4倍すると約3,000MBが必要になります。そのときの枠は1,200MBでした。入るはずがありません。そして実際に入りませんでした。\n倍率が1本のモデルからしか出ていない点は、そのまま弱点です。 0.5B以外では検証していません。\nなお、この2.4倍はcgroupの memory.current から取った値で、モデルファイルのページキャッシュを含みます。 「アプリが確保した量」より大きめに出る数字です。余裕を見る方向に効くので、目安としては安全側ですが、そういう数字だという前提で読んでください。\n公式のファイルサイズから逆算した早見表 ここから先は計算値です。 各モデルのファイルサイズは2026年9月13日にOllama公式ライブラリで確認した値、必要メモリはそれを2.4倍したものです。\nモデル 公式のファイルサイズ 必要メモリの目安（×2.4） gemma3:270m 292MB 約700MB qwen2.5:0.5b 398MB 約960MB（実測930MB） gemma3:1b 815MB 約1,960MB qwen2.5:1.5b 986MB 約2,370MB llama3.2:1b 1.3GB 約3,120MB qwen2.5:3b 1.9GB 約4,560MB llama3.2:3b 2.0GB 約4,800MB gemma3:4b 3.3GB 約7,920MB 実測と一致しているのは2行目だけです。 他は倍率からの計算で、私は確かめていません。\n空きメモリ別に並べ替えると、こうなります。\n空きメモリ 載る見込みのモデル 検証状況 1.4GB前後 gemma3:270m / qwen2.5:0.5b 0.5Bのみ実測済み 3GB前後 gemma3:1b / qwen2.5:1.5b 未検証 5GB前後 llama3.2:1b / qwen2.5:3b 未検証 8GB前後 gemma3:4b 未検証 「空きメモリ」は搭載メモリではありません。 OSと、すでに動いているものが使っている分を引いた残りです。2GBのVPSでも、OSのデーモンだけで50〜100MBを持っていきます（43時間の計測で確認しました）。\n速度は段階的に落ちない。崖から落ちる ここが、この計算を守るべきいちばんの理由です。\nモデル ファイル メモリピーク 生成速度 結果 qwen2.5:0.5b 397MB 930MB 15.36 tok/s 動く llama3.2:1b 1.3GB 1,201MB（上限） 0.07 tok/s 実用不可 qwen2.5:3b 1.9GB — — 落ちた 0.5Bから1Bに上げただけで、219分の1になりました。9トークンの返事に3分かかっています。\n「少し重くなる」ではありません。枠を超えた瞬間、メモリとスワップの間でページを出し入れし続ける状態になり、実用の範囲から一気に外れます。そのときのI/O待ちは最大86%でした。\nつまり、目安を少し超えるくらいなら大丈夫、という読み方はできません。 超えたら使えません。\nOllamaの公式ドキュメントに、必要メモリの記載はない ローカルLLMの解説記事を10本ほど見ると、ほぼすべてがVRAMの容量別にモデルを振り分けています。8GB VRAMならこれ、16GBならこれ、という形です。\nなぜCPUの話が出てこないのか。公式に書いていないからです。\n2026年9月13日に確認した範囲では、Ollamaの公式ドキュメント（FAQ）に必要RAMの節はありません。 メモリに関連する記載としてあるのは、次のようなものです。\nollama ps が、モデルをどこで動かしているかを 100% GPU / 100% CPU またはその中間として表示する 必要RAMは OLLAMA_NUM_PARALLEL × OLLAMA_CONTEXT_LENGTH に応じてスケールする 「100% CPU」という表示が公式に用意されていること自体が、CPUだけでの動作が想定内であることを示しています。一方で、では何GB要るのかは、公式には書かれていません。\nGitHubのREADMEについては、断定を避けます。 以前は必要RAMの記載があったと記憶していますが、2026年9月13日時点のREADMEからは該当箇所を確認できませんでした。「削除された」と書けるだけの確証がないため、ここでは「現時点では見つからなかった」とだけ書きます。\n書かれていない数字を埋めるために、解説記事はGPUベンダー側の表を持ってくることになります。その表は、GPUがない環境には使えません。\n「動く」ことと「使える」ことは違う 0.5Bは15 tokens/秒で動きました。ただし、出力はこうでした。\n日本の首都は东京です。 「東京」が簡体字の「东京」になっています。 中国語圏で作られた小型モデルなので、日本語の中に簡体字が混ざります。\n同じ質問に対して、1Bのほうは正しく「東京」と返しました。品質は上がっています。速度が実用外なだけです。\nCPUだけの環境では、この「品質は足りているが遅すぎる」と「速いが品質が足りない」の間に挟まれます。 メモリを増やす以外に、この挟み撃ちから抜ける方法はありません。\n用途で言い換えると、こうなります。\n分類・抽出・短い要約なら0.5Bクラスでも実用範囲 日本語の文章を生成させるなら0.5Bでは足りない 重いのはツールではなくモデル 「AIツールはメモリを食う」という言い方をよく見ますが、実測すると逆です。\n常駐メモリ Ollama本体 36MB Docker（dockerd + containerd） 約49MB n8n 402MB Dify（16コンテナ） 2,076MB Ollamaのデーモンは、Dockerより軽い。 モデルを止めればメモリはすぐ戻ります。使っていないときのコストはほぼゼロです。\n重いのはモデルです。ツールを選び直しても解決しません。\n先に埋まるのはディスクのことがある メモリばかり見ていると足をすくわれます。\nOllama本体だけでディスク2.1GB。 CPUしかない環境でも、GPU用のライブラリを含めて配布されるためです ここにモデルが積み上がります。3つ入れた時点で3.4GBでした 2GBのVPSでディスクが20GBというような構成では、メモリの上限より先にディスクが問題になることがあります。 特にDockerを同居させている場合は、消したつもりで消えていない領域が積み上がります。\n商用利用：ライセンスはモデルごとに違う 同じシリーズでもサイズによって分かれます。 Ollama公式ライブラリの記載（2026年9月13日確認）です。\nモデル ライセンスの記載 Qwen2.5 3Bと72B以外はApache 2.0。3Bと72BはQwenライセンス Gemma 3 Gemma Terms of Use Llama 3.2 ライセンス名を確認できませんでした Qwen2.5の原文はこうです。\nall models except the 3B and 72B are released under the Apache 2.0 license, while the 3B and 72B models are under the Qwen license.\n「オープンソースだから自由に使える」とは限りません。 商用で使うなら、使うモデルのライセンス原文を読んでください。ここに書いたのは、あくまでOllamaのライブラリページに書かれていた内容です。\nLlama 3.2については、Ollamaのライブラリページからライセンス名を確認できませんでした。 推測で埋めません。\nこの記事が書けなかったこと 2.4倍という倍率は、モデル1本（qwen2.5:0.5b）の実測から出したものです。 他のモデルでは検証していません 早見表の「未検証」の行は、計算値です。 3GB・5GB・8GBの環境では測っていません GPUがある環境とは比較していません。 この記事の数字はすべてCPU推論のものです 量子化の違いは扱っていません。 Ollamaの既定の量子化のままで測った値です Ollamaの必要メモリについて、「公式が意図的に書いていない」とは書けません。 確認できたのは「見つからなかった」ことだけです 出典 Ollama公式ライブラリ qwen2.5 / gemma3 / llama3.2（モデルのファイルサイズとライセンス記載、2026年9月13日確認） Ollama Docs FAQ（ollama ps の表示、RAMのスケール、2026年9月13日確認） 実測値は当サイトの測定による（さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / GPUなし） 関連記事 2GBのVPSでローカルLLMは動くのか｜0.5B・1B・3Bを実測したら1Bで崖だった — この記事の2.4倍の根拠になった測定の全記録 AI用途のVPSは何GB必要か｜n8nとDifyを実測して積み上げた — メモリを増やす側から考えるときはこちら 43時間、1分ごとにVPSを測り続けた — 「空きメモリ」がどれだけOS側に取られるか ","permalink":"https://jimae-ai.com/local-llm-cpu-only/","summary":"\u003cp\u003e「GPUがないパソコンやサーバーでローカルLLMは動くのか」。\u003cstrong\u003e動きます。ただし、載せられるモデルの大きさは、ほぼ計算で決まります。\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e載せられるモデルファイル ≒ 空きメモリ ÷ 2.4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eこの2.4という倍率は、GPUなしのVPSで実際に測って出した値です。そして\u003cstrong\u003eこの計算を外れた瞬間、速度は段階的にではなく崖のように落ちます。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"確認できたこと\"\u003e確認できたこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e必要メモリの目安はモデルファイルの約2.4倍\u003c/strong\u003e。0.5Bのモデル（380MB）で実測930MBだった\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e0.5Bは15.36 tokens/秒で動き、1Bでは0.07 tokens/秒\u003c/strong\u003eに落ちた。219分の1。段階的ではなく崖\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOllamaの公式ドキュメントには、必要メモリの記載がない\u003c/strong\u003e。2026年9月13日に確認した\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e重いのはツールではなくモデル\u003c/strong\u003e。Ollama本体の常駐メモリは36MBで、Dockerの49MBより軽い\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e先に埋まるのはメモリではなくディスク\u003c/strong\u003eのことがある。Ollama本体だけで2.1GB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e商用利用の可否はモデルごとに違う\u003c/strong\u003e。同じQwen2.5でもサイズによってライセンスが分かれている\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eこの記事の数字には\u003cstrong\u003e実測値と計算値が混ざっています。\u003c/strong\u003e どちらなのかは、その都度書きます。\u003c/p\u003e\n\u003ch2 id=\"載るモデルは空きメモリ--24で決まる\"\u003e載るモデルは「空きメモリ ÷ 2.4」で決まる\u003c/h2\u003e\n\u003cp\u003e出発点は、GPUのないVPSで測った1本の実測値です。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eモデルファイル 380MB → 実際のメモリピーク 930MB（2.4倍）\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eさくらのVPS 2Gプラン、Ubuntu 24.04、GPUなし・CPUのみ。\u003ccode\u003eqwen2.5:0.5b\u003c/code\u003e を載せたときの値です。測定の詳細は\u003ca href=\"/ollama-2gb-vps-local-llm/\"\u003e2GBのVPSでローカルLLMは動くのか\u003c/a\u003eに書きました。\u003c/p\u003e\n\u003cp\u003eこの倍率で逆算すると、載せられるモデルの上限が出ます。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e載せられるモデルファイル ≒ 空きメモリ ÷ 2.4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e同じ実測から、1Bのモデルが動かない理由も説明がつきます。\u003c/strong\u003e 1Bのファイルは1,260MB。2.4倍すると約3,000MBが必要になります。そのときの枠は1,200MBでした。入るはずがありません。そして実際に入りませんでした。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e倍率が1本のモデルからしか出ていない点は、そのまま弱点です。\u003c/strong\u003e 0.5B以外では検証していません。\u003c/p\u003e\n\u003cp\u003eなお、この2.4倍はcgroupの \u003ccode\u003ememory.current\u003c/code\u003e から取った値で、\u003cstrong\u003eモデルファイルのページキャッシュを含みます。\u003c/strong\u003e 「アプリが確保した量」より大きめに出る数字です。余裕を見る方向に効くので、目安としては安全側ですが、そういう数字だという前提で読んでください。\u003c/p\u003e\n\u003ch2 id=\"公式のファイルサイズから逆算した早見表\"\u003e公式のファイルサイズから逆算した早見表\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eここから先は計算値です。\u003c/strong\u003e 各モデルのファイルサイズは2026年9月13日にOllama公式ライブラリで確認した値、必要メモリはそれを2.4倍したものです。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eモデル\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e公式のファイルサイズ\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e必要メモリの目安（×2.4）\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003egemma3:270m\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e292MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約700MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eqwen2.5:0.5b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e398MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約960MB（\u003cstrong\u003e実測930MB\u003c/strong\u003e）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003egemma3:1b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e815MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約1,960MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eqwen2.5:1.5b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e986MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約2,370MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003ellama3.2:1b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1.3GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約3,120MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eqwen2.5:3b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1.9GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約4,560MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003ellama3.2:3b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e2.0GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約4,800MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003egemma3:4b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e3.3GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約7,920MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e実測と一致しているのは2行目だけです。\u003c/strong\u003e 他は倍率からの計算で、私は確かめていません。\u003c/p\u003e","title":"GPUなしでローカルLLMは使えるのか｜載るモデルは「空きメモリ÷2.4」で決まる"},{"content":"当サイトへのご連絡は、下記のフォームからお願いします。\nお問い合わせフォーム → お問い合わせフォームを開く\nお受けできる内容 記事の内容に関するご質問 記事の誤りのご指摘 取材・執筆のご依頼 掲載しているサービスの提供元の方からのご連絡 記事の誤りのご指摘は、特に歓迎します。 当サイトは実際に測定した数字を掲載していますが、環境の違いや私の見落としで、誤った内容になっている可能性があります。お気づきの点があればお知らせください。確認のうえ、該当記事に訂正を追記します。\nお返事について いただいた内容は必ず確認しますが、すべてにお返事できるとは限りません。 あらかじめご了承ください。\n技術的なご質問について、記事に書いていない環境での動作は、私も確認できていないことがあります。その場合は「分からない」とお答えします。\n個人情報の取り扱い フォームから送信いただいた情報は、お問い合わせへの返信のみに使用します。 詳細はプライバシーポリシーをご覧ください。\n","permalink":"https://jimae-ai.com/contact/","summary":"\u003cp\u003e当サイトへのご連絡は、下記のフォームからお願いします。\u003c/p\u003e\n\u003ch2 id=\"お問い合わせフォーム\"\u003eお問い合わせフォーム\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e→ \u003ca href=\"https://docs.google.com/forms/d/e/1FAIpQLSftw82II4awxrU1rFpAv8q6FrYVK3u2Ygs3aMwzi5wpQQB0sA/viewform\"\u003eお問い合わせフォームを開く\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"お受けできる内容\"\u003eお受けできる内容\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e記事の内容に関するご質問\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e記事の誤りのご指摘\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e取材・執筆のご依頼\u003c/li\u003e\n\u003cli\u003e掲載しているサービスの提供元の方からのご連絡\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e記事の誤りのご指摘は、特に歓迎します。\u003c/strong\u003e 当サイトは実際に測定した数字を掲載していますが、環境の違いや私の見落としで、誤った内容になっている可能性があります。お気づきの点があればお知らせください。\u003cstrong\u003e確認のうえ、該当記事に訂正を追記します。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"お返事について\"\u003eお返事について\u003c/h2\u003e\n\u003cp\u003eいただいた内容は必ず確認しますが、\u003cstrong\u003eすべてにお返事できるとは限りません。\u003c/strong\u003e あらかじめご了承ください。\u003c/p\u003e\n\u003cp\u003e技術的なご質問について、記事に書いていない環境での動作は、私も確認できていないことがあります。\u003cstrong\u003eその場合は「分からない」とお答えします。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"個人情報の取り扱い\"\u003e個人情報の取り扱い\u003c/h2\u003e\n\u003cp\u003eフォームから送信いただいた情報は、\u003cstrong\u003eお問い合わせへの返信のみに使用します。\u003c/strong\u003e 詳細は\u003ca href=\"/privacy/\"\u003eプライバシーポリシー\u003c/a\u003eをご覧ください。\u003c/p\u003e","title":"お問い合わせ"},{"content":"当サイト「自前AI」（https://jimae-ai.com/）における、個人情報の取り扱いについて定めます。\n個人情報の取得と利用目的 当サイトが利用者から個人情報を取得するのは、お問い合わせフォームを利用された場合のみです。\n取得する項目は、お名前・メールアドレス・お問い合わせ内容です。利用目的は、お問い合わせへの返信に限ります。 それ以外の目的には使用せず、第三者に提供することもありません。\nお問い合わせフォームにはGoogleフォームを利用しています。送信された内容はGoogle社のサービス上に保存されます。詳細はGoogleプライバシーポリシーをご確認ください。\nアクセス解析について 当サイトは、Googleアナリティクスをはじめとする第三者のアクセス解析ツールを設置していません。（2026年9月8日時点）\nただし、サイトを配信しているWebサーバーは、通常のアクセスログとしてIPアドレス・アクセス日時・閲覧ページ・ブラウザの種類などを記録しています。これらはサーバーの運用と障害対応のために使用するもので、個人を特定する目的では利用しません。\nなお、当サイトはGoogle Search Consoleに登録しています。これは検索結果での表示状況を確認するためのもので、利用者の端末に情報を保存するものではありません。\n将来アクセス解析ツールを導入する場合は、導入前にこのページを更新します。\n広告・アフィリエイトについて 当サイトは、A8.netをはじめとするアフィリエイトプログラムに参加しています。\n記事内に広告リンクを掲載する場合、その記事に広告を含む旨を明記します。 表記のない記事には広告リンクを掲載していません。\nアフィリエイトプログラムでは、成果を計測するためにCookieを利用することがあります。Cookieに個人を特定する情報は含まれません。ブラウザの設定でCookieを無効にすることができます。\n免責事項 当サイトに掲載する情報は、掲載時点で確認したものです。サービスの仕様・料金・提供状況は変更されることがあります。 実際にご利用の際は、必ず各提供元の公式情報をご確認ください。\n当サイトには、実際に検証した内容と、公式ドキュメントを引用した内容が含まれます。どちらであるかは記事内で区別して記載しています。 検証していない事柄については、その旨を明記しています。\n当サイトの情報を利用したことにより生じた損害について、当サイトは責任を負いかねます。 サーバーの設定変更やソフトウェアの導入は、利用者ご自身の責任において実施してください。\n当サイトからリンクした外部サイトの内容については、当サイトは責任を負いません。\n著作権について 当サイトに掲載している文章・画像・測定データの著作権は、当サイトの運営者に帰属します。引用の範囲を超えた転載はご遠慮ください。\n引用される場合は、出典として当サイトのURLを明記してください。\n記事内で引用している各社の商標・ロゴ・公式ドキュメントの著作権は、それぞれの権利者に帰属します。\nお問い合わせ 本ポリシーに関するご質問は、お問い合わせからご連絡ください。\n改定について 本ポリシーは、必要に応じて変更することがあります。変更した場合は、このページに反映します。\n制定日：2026年9月8日\n","permalink":"https://jimae-ai.com/privacy/","summary":"\u003cp\u003e当サイト「自前AI」（https://jimae-ai.com/）における、個人情報の取り扱いについて定めます。\u003c/p\u003e\n\u003ch2 id=\"個人情報の取得と利用目的\"\u003e個人情報の取得と利用目的\u003c/h2\u003e\n\u003cp\u003e当サイトが利用者から個人情報を取得するのは、\u003cstrong\u003eお問い合わせフォームを利用された場合のみ\u003c/strong\u003eです。\u003c/p\u003e\n\u003cp\u003e取得する項目は、お名前・メールアドレス・お問い合わせ内容です。利用目的は、\u003cstrong\u003eお問い合わせへの返信に限ります。\u003c/strong\u003e それ以外の目的には使用せず、第三者に提供することもありません。\u003c/p\u003e\n\u003cp\u003eお問い合わせフォームにはGoogleフォームを利用しています。送信された内容はGoogle社のサービス上に保存されます。詳細は\u003ca href=\"https://policies.google.com/privacy?hl=ja\"\u003eGoogleプライバシーポリシー\u003c/a\u003eをご確認ください。\u003c/p\u003e\n\u003ch2 id=\"アクセス解析について\"\u003eアクセス解析について\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e当サイトは、Googleアナリティクスをはじめとする第三者のアクセス解析ツールを設置していません。\u003c/strong\u003e（2026年9月8日時点）\u003c/p\u003e\n\u003cp\u003eただし、サイトを配信しているWebサーバーは、通常のアクセスログとしてIPアドレス・アクセス日時・閲覧ページ・ブラウザの種類などを記録しています。これらはサーバーの運用と障害対応のために使用するもので、\u003cstrong\u003e個人を特定する目的では利用しません。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eなお、当サイトはGoogle Search Consoleに登録しています。これは検索結果での表示状況を確認するためのもので、\u003cstrong\u003e利用者の端末に情報を保存するものではありません。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e将来アクセス解析ツールを導入する場合は、\u003cstrong\u003e導入前にこのページを更新します。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"広告アフィリエイトについて\"\u003e広告・アフィリエイトについて\u003c/h2\u003e\n\u003cp\u003e当サイトは、A8.netをはじめとするアフィリエイトプログラムに参加しています。\u003c/p\u003e\n\u003cp\u003e記事内に広告リンクを掲載する場合、\u003cstrong\u003eその記事に広告を含む旨を明記します。\u003c/strong\u003e 表記のない記事には広告リンクを掲載していません。\u003c/p\u003e\n\u003cp\u003eアフィリエイトプログラムでは、成果を計測するためにCookieを利用することがあります。Cookieに個人を特定する情報は含まれません。\u003cstrong\u003eブラウザの設定でCookieを無効にすることができます。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"免責事項\"\u003e免責事項\u003c/h2\u003e\n\u003cp\u003e当サイトに掲載する情報は、掲載時点で確認したものです。\u003cstrong\u003eサービスの仕様・料金・提供状況は変更されることがあります。\u003c/strong\u003e 実際にご利用の際は、必ず各提供元の公式情報をご確認ください。\u003c/p\u003e\n\u003cp\u003e当サイトには、実際に検証した内容と、公式ドキュメントを引用した内容が含まれます。\u003cstrong\u003eどちらであるかは記事内で区別して記載しています。\u003c/strong\u003e 検証していない事柄については、その旨を明記しています。\u003c/p\u003e\n\u003cp\u003e当サイトの情報を利用したことにより生じた損害について、\u003cstrong\u003e当サイトは責任を負いかねます。\u003c/strong\u003e サーバーの設定変更やソフトウェアの導入は、利用者ご自身の責任において実施してください。\u003c/p\u003e\n\u003cp\u003e当サイトからリンクした外部サイトの内容については、当サイトは責任を負いません。\u003c/p\u003e\n\u003ch2 id=\"著作権について\"\u003e著作権について\u003c/h2\u003e\n\u003cp\u003e当サイトに掲載している文章・画像・測定データの著作権は、当サイトの運営者に帰属します。引用の範囲を超えた転載はご遠慮ください。\u003c/p\u003e\n\u003cp\u003e引用される場合は、\u003cstrong\u003e出典として当サイトのURLを明記してください。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e記事内で引用している各社の商標・ロゴ・公式ドキュメントの著作権は、それぞれの権利者に帰属します。\u003c/p\u003e\n\u003ch2 id=\"お問い合わせ\"\u003eお問い合わせ\u003c/h2\u003e\n\u003cp\u003e本ポリシーに関するご質問は、\u003ca href=\"/contact/\"\u003eお問い合わせ\u003c/a\u003eからご連絡ください。\u003c/p\u003e\n\u003ch2 id=\"改定について\"\u003e改定について\u003c/h2\u003e\n\u003cp\u003e本ポリシーは、必要に応じて変更することがあります。\u003cstrong\u003e変更した場合は、このページに反映します。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e制定日：2026年9月8日\u003c/p\u003e","title":"プライバシーポリシー"},{"content":"運営者 サイト名 自前AI URL https://jimae-ai.com/ 運営者 taka 開設 2026年9月 連絡先 お問い合わせ このサイトについて VPSでAIツールと業務自動化を、自分のサーバーで動かした記録を載せています。\n書いているのは、n8n・Dify・Ollama・Claude Codeといったツールを、実際にVPSへ入れて動かしたときの手順と数字です。\n書き方のルール このサイトには、自分で決めたルールが3つあります。\n① 実測値・公式情報・未確認を、はっきり分ける。\n「メモリを何MB使った」という数字は、すべて自分のサーバーで測ったものです。仕様や要件は、公式ドキュメントを出典として示します。確かめていないことは「確かめていない」と書きます。\n② 分からなかったことを、分からなかったと書く。\n原因を特定できなかった現象は、推測で埋めません。「こうだと思うが確証はない」と書きます。\n③ 間違えたら、記事の中で訂正する。\n公開後に自分の誤りに気づいた場合、該当記事に訂正を追記します。 静かに書き換えることはしません。実際に、過去の記事には訂正の追記が入っています。\n使用している環境 記事中の測定は、断りがない限り以下の環境で行っています。\nさくらのVPS 2Gプラン Ubuntu 24.04 LTS GPUなし・CPUのみ 測定に使ったコマンドは記事内に記載しています。 同じ手順で確認できるようにしているつもりですが、環境によって結果は変わります。\n広告について 当サイトはアフィリエイトプログラムに参加しています。広告リンクを掲載する記事には、その旨を明記します。\n記事の結論は、報酬額ではなく、測定結果と公式情報から書いています。おかしな点があれば、お問い合わせからご指摘ください。\n詳細はプライバシーポリシーをご覧ください。\n","permalink":"https://jimae-ai.com/about/","summary":"\u003ch2 id=\"運営者\"\u003e運営者\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eサイト名\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e自前AI\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eURL\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://jimae-ai.com/\"\u003ehttps://jimae-ai.com/\u003c/a\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e運営者\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003etaka\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e開設\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e2026年9月\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e連絡先\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"/contact/\"\u003eお問い合わせ\u003c/a\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"このサイトについて\"\u003eこのサイトについて\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eVPSでAIツールと業務自動化を、自分のサーバーで動かした記録\u003c/strong\u003eを載せています。\u003c/p\u003e\n\u003cp\u003e書いているのは、n8n・Dify・Ollama・Claude Codeといったツールを、実際にVPSへ入れて動かしたときの手順と数字です。\u003c/p\u003e\n\u003ch2 id=\"書き方のルール\"\u003e書き方のルール\u003c/h2\u003e\n\u003cp\u003eこのサイトには、自分で決めたルールが3つあります。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e① 実測値・公式情報・未確認を、はっきり分ける。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e「メモリを何MB使った」という数字は、すべて自分のサーバーで測ったものです。仕様や要件は、公式ドキュメントを出典として示します。\u003cstrong\u003e確かめていないことは「確かめていない」と書きます。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e② 分からなかったことを、分からなかったと書く。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e原因を特定できなかった現象は、推測で埋めません。「こうだと思うが確証はない」と書きます。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e③ 間違えたら、記事の中で訂正する。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e公開後に自分の誤りに気づいた場合、\u003cstrong\u003e該当記事に訂正を追記します。\u003c/strong\u003e 静かに書き換えることはしません。実際に、過去の記事には訂正の追記が入っています。\u003c/p\u003e\n\u003ch2 id=\"使用している環境\"\u003e使用している環境\u003c/h2\u003e\n\u003cp\u003e記事中の測定は、断りがない限り以下の環境で行っています。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eさくらのVPS 2Gプラン\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003eUbuntu 24.04 LTS\u003c/li\u003e\n\u003cli\u003eGPUなし・CPUのみ\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e測定に使ったコマンドは記事内に記載しています。\u003c/strong\u003e 同じ手順で確認できるようにしているつもりですが、環境によって結果は変わります。\u003c/p\u003e\n\u003ch2 id=\"広告について\"\u003e広告について\u003c/h2\u003e\n\u003cp\u003e当サイトはアフィリエイトプログラムに参加しています。\u003cstrong\u003e広告リンクを掲載する記事には、その旨を明記します。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e記事の結論は、報酬額ではなく、測定結果と公式情報から書いています。おかしな点があれば、\u003ca href=\"/contact/\"\u003eお問い合わせ\u003c/a\u003eからご指摘ください。\u003c/p\u003e\n\u003cp\u003e詳細は\u003ca href=\"/privacy/\"\u003eプライバシーポリシー\u003c/a\u003eをご覧ください。\u003c/p\u003e","title":"運営者情報"},{"content":" 本記事はプロモーションを含みます。 記事内の一部のリンクは広告リンクです。リンクの有無で内容を変えていません。 掲載している数値はすべて公式ドキュメントの記載か、自分のサーバーで実際に測った値です。\nClaude Codeを自分のVPSで動かしたい。まず決まるのは「どのプランを買うか」です。\n各社のページを調べたら、全社が「4GB以上」と書いていました。 一方、Anthropicの公式要件も4GB以上です。\nでは2GBでは動かないのか。2GBのVPSに手で入れて、動かしました。最大268MBでした。\n結論 結果 各社の要件 4GB以上（2GB以下は非対応と明記する社もある） 2GBでの実測 最大268MB / ファイル作成もコード実行も成功 Node.js 不要（ネイティブインストーラ） ディスク +206MB インストール時間 6分46秒 アカウント 有料プラン必須（無料のClaude.aiでは使えない） ただし、「4GBは要らない」とは書きません。 理由は最後に書きます。\n対応している4社と、その必要メモリ Claude Codeのテンプレート／アプリイメージを公式に出しているのは、確認できた範囲でこの4社です。\n提供元 形式 公表している必要メモリ XServer VPS アプリイメージ 4GB以上。2GB以下のプランでは利用不可 シンVPS アプリイメージ 4GB以上。2GB以下のプランでは利用不可 ConoHa VPS スタートアップスクリプト 最小3GB、推奨4GB以上 KAGOYA CLOUD VPS テンプレート 記載を確認できず （表のXServer VPSとConoHa VPSは広告リンクです。他社は提携していないため通常のリンクです。リンクの有無と、この表に書いた内容は無関係です。）\nXServer VPSとシンVPSは、2GB以下のプランでは選択肢に出てきません。 「安いプランを買ってから気づく」ことになります。\nAnthropicの公式ドキュメントも同じです。\nHardware: 4 GB+ RAM, x64 or ARM64 processor\n4社と公式で、数字が一致しています。\nConoHaのスクリプトが入れるもの ConoHaのドキュメントには、中身まで書いてあります。\nソフト バージョン Claude Code 最新 Node.js 22 ripgrep 13.0.0 UFW 最新 Fail2ban 最新 対応OSは Ubuntu 24.04 LTS のみ。\nUFWとFail2banまで入れてくれるのは親切です。 手で入れる場合、この2つは自分で用意することになります。\nさくらのVPSには、Claude Codeのスクリプトがありません さくらのVPSのスタートアップスクリプト一覧を確認しました。用意されているのはこれです。\nAI : Open WebUI + さくらのAI Engine / Dify + さくらのAI Engine / n8n 開発 : code-server ゲーム : Minecraft（Java版 / 統合版）/ Factorio その他 : Mastodon / Mailserver / Let\u0026#39;s Encrypt / BackupPC ほか AI系は3つありますが、Claude Codeは入っていません。（2026年9月8日時点）\nなので、さくらのVPSで使うなら手動インストール一択です。以下はその手順です。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS メモリ：合計1,966MB（公式要件の半分以下） 同居：別の常時稼働アプリと静的サイト1本が動いている実運用サーバー Claude Code：2.1.263 開始時の空きメモリ：1,337MB Node.jsは要りません まず、入れる前のサーバーの状態です。\nnode -v # → node なし npm -v # → npm なし Node.jsもnpmも入っていません。 この状態から、公式のネイティブインストーラで入ります。\ncurl -fsSL https://claude.ai/install.sh | bash ✔ Claude Code successfully installed! Version: 2.1.263 Location: ~/.local/bin/claude Node.jsなしで成功しました。\n公式ドキュメントにも根拠があります。npm経由で入れた場合でも、\nThe installed claude binary does not itself invoke Node.\nnpmはネイティブバイナリを取ってくるだけで、実行時にNode.jsは使いません。 npm経由を選ぶ場合のみ、Node.js 22以降が必要です（v2.1.198以降）。\nConoHaのスクリプトがNode.js 22を入れるのは、npm経由の方式だからです。 ネイティブインストーラなら不要です。\nかかった時間とディスク 値 所要時間 6分46秒 ディスク増（df） +206MB du -sh ~/.local/share/claude 206M df と du が一致しています。\n206MBは軽い。 比較するとよく分かります。\nディスク Claude Code 206MB Ollama本体 2,160MB n8n 2,470MB Dify（16コンテナ） 10,600MB Ollamaの10分の1以下です。モデルを持たないぶん当然ではありますが、置き場所の心配はまず要りません。\n6分46秒かかった理由は分かりません。 206MBに7分は遅すぎます。同じサーバーからGitHubへは11.3MB/s出ていたので、計算上は20秒で終わるはずです。原因は特定していません。 回線かCDNか、その時間帯だけの問題か、確証がありません。\nインストール直後、claude は使えません ここが最初の落とし穴です。\n⚠ Setup notes: ● Native installation exists but ~/.local/bin is not in your PATH. 公式の手順どおりに入れても、コマンドが通りません。 もう1行必要です。\necho \u0026#39;export PATH=\u0026#34;$HOME/.local/bin:$PATH\u0026#34;\u0026#39; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc 通ったか確認します。\nwhich claude # → ~/.local/bin/claude claude doctor claude doctor は認証前でも動く診断コマンドです。ここで確認できたこと。\nSearch: OK (bundled) — ripgrepは同梱。別途インストール不要 Auto-updates: enabled — ネイティブ版は自動更新される 事業用サーバーに入れるなら、ユーザーを分けてください ここがいちばん大事です。\nClaude Codeはファイルを読み書きし、コマンドを実行します。 他のシステムが動いているサーバーにそのまま入れると、そのファイルにも手が届きます。\n専用ユーザーを作って、その中だけで動かします。\nsudo useradd -m -s /bin/bash ccbox # sudo権限は与えない sudo -iu ccbox curl -fsSL https://claude.ai/install.sh | bash 作ったら、本当に見えないことを確認します。\nsudo -u ccbox ls /home/ubuntu # → ls: cannot open directory \u0026#39;/home/ubuntu\u0026#39;: Permission denied Ubuntu 24.04では、ホームディレクトリの既定が drwxr-x---（750） です。別ユーザーは最初から読めません。 権限を変える必要はありませんでしたが、確認は必ずしてください。\nls -ld /home/* drwxr-xr-x（755）になっていたら、chmod 750 が必要です。\nこの隔離には、もう1つ効果があります。 後述の --permission-mode bypassPermissions（承認をすべて飛ばす設定）を試すとき、被害範囲がこのユーザーの中に限られます。\n認証は、ブラウザのないサーバーでも通ります claude auth login Opening browser to sign in… If the browser didn\u0026#39;t open, visit: https://claude.com/cai/oauth/authorize?... Paste code here if prompted \u0026gt; 表示されたURLを手元のブラウザにコピーして開き、承認するだけです。 サーバー側にブラウザは要りません。\n注意点が1つ。 sudo -iu ccbox はパスワードを聞いてきます。複数行をまとめて貼ると、2行目がパスワード入力に飲み込まれます。 1行ずつ実行してください。\n有料プランが必要です 公式ドキュメントに明記があります。\nClaude Code requires a Pro, Max, Team, Enterprise, or Console account. The free Claude.ai plan does not include Claude Code access.\n無料のClaude.aiアカウントでは使えません。 VPSを契約してから気づくと二度手間です。\n2GBで動くのか 本題です。公式要件は4GB。このサーバーは1,966MB。\n単純な質問 claude -p \u0026#34;1+1は？数字だけ答えてください。\u0026#34; 2 real 0m3.044s 値 所要時間 3.04秒 claudeプロセスの最大メモリ 235.8MB ファイルを作って実行させる これが本来の使い方です。\nclaude -p \u0026#34;hello.py を作って、1から10までの合計を出力するコードを書き、実行して結果を見せてください。\u0026#34; \\ --permission-mode bypassPermissions `python3 hello.py` の出力: 1から10までの合計: 55 エラーなし、終了ステータス 0 です。 値 所要時間 11.2秒 最大メモリ 268.1MB 実行後の空き 1,364MB ファイル作成もコード実行も通りました。 1,966MBのサーバーで、268MBです。\n--permission-mode の落とし穴 上のコマンドで bypassPermissions を使ったのには理由があります。\n最初は acceptEdits で走らせました。 結果がこれです。\n`hello.py` を作成しました。 実行しようとしましたが、`python3 hello.py` の実行に承認が必要と表示されて止まっています。 ファイルは作られましたが、そこで止まりました。\nモード ファイル編集 コマンド実行 acceptEdits 通る 止まる bypassPermissions 通る 通る -p（非対話モード）で最後まで走らせたいなら、acceptEdits では足りません。\nただし bypassPermissions は承認を全部飛ばします。 実運用のサーバーで安易に使うものではありません。専用ユーザーに隔離してあるからこそ試せる設定です。\nついでに踏んだ罠 /tmp に記録ファイルを書こうとして、こうなりました。\n-bash: line 3: /tmp/cc-rss2.txt: Permission denied 別のユーザーで同じパスに書いた残骸があると、権限で弾かれます。 ユーザーを分けて作業するなら、一時ファイルは各ユーザーのホームに置いてください。\n料金は「VPS代 + Claudeのプラン代」です 見落としやすい点です。VPSを契約しただけでは動きません。\nVPS側の目安として、KAGOYA CLOUD VPSの料金表を挙げます（2026年9月8日時点の公表値）。\nメモリ CPU SSD 日額 月額上限 1GB 1コア 100GB 20円 550円 2GB 2コア 200GB 28円 770円 3GB 3コア 400GB 52円 1,430円 4GB 4コア 600GB 63円 1,760円 8GB 6コア 800GB 122円 3,410円 公式要件の4GBを満たす最小構成で、月1,760円。 ここにClaudeの有料プラン代が乗ります。\n結局、何GBを買えばいいのか 私は「4GBで足りる」とも「2GBで十分」とも書きません。 測ったのは軽い作業だけだからです。\n分かっていることを、そのまま並べます。\n公式と各社は4GB以上と言っている。 数字は一致している XServer VPSとシンVPSでは、2GB以下だとアプリイメージが選べない（手動インストールの可否とは別の話です） 2GBのVPSに手で入れたら、最大268MBで動いた。 ファイル作成もコード実行も成功した 測ったのは、10行程度のコードを書いて実行させる作業だけです 大きなリポジトリを読ませたら、どこまで伸びるかは測っていません。 4GBという要件は、おそらくそちらを想定した数字です。\n判断の材料としてはこう考えています。\n用途 目安 試してみたい / 小さなスクリプト 2GBでも動いた（ただし各社サポート外） 実際のプロジェクトで常用する 公式どおり4GB以上 迷ったら4GBです。 月1,760円の差で、公式要件を満たせます。\n各社の現在の料金とプラン構成は、公式ページで確認してください。アプリイメージが使えるのは4GB以上のプランです。\nVPSでいろいろ試すなら『XServer VPS』 ConoHa VPS（UFWとFail2banも一緒に入る） （上記2つは広告リンクです。）\nまとめ テンプレートを出しているのは4社（XServer VPS / シンVPS / ConoHa VPS / KAGOYA CLOUD VPS）。さくらのVPSにはない 全社と公式が「4GB以上」で一致。 XServer VPSとシンVPSは2GB以下だとイメージが選べない 2GBのVPSに手で入れたら、最大268MBで動いた。 ファイル作成もコード実行も成功 Node.jsは不要。 ネイティブインストーラで入る。npm経由のみNode.js 22以降が必要 ディスク206MB / インストール6分46秒 インストール直後は claude が使えない。 PATHを1行追加する 有料プラン必須。 無料のClaude.aiでは使えない 他のシステムが動くサーバーなら、専用ユーザーに隔離する。 Ubuntu 24.04なら既定の750で最初から守られているが、確認はすること -p で最後まで走らせるなら acceptEdits では止まる 「何GB必要か」に答えているページが見当たらなかったので、測って書きました。公式の4GBという数字と、実際に動いた268MBは、どちらも本当です。 何をやらせるかで変わります。\nAIツール全般の必要メモリは、実測から積み上げた選び方にまとめています。\n","permalink":"https://jimae-ai.com/claude-code-vps/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e本記事はプロモーションを含みます。\u003c/strong\u003e 記事内の一部のリンクは広告リンクです。\u003cstrong\u003eリンクの有無で内容を変えていません。\u003c/strong\u003e 掲載している数値はすべて公式ドキュメントの記載か、自分のサーバーで実際に測った値です。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eClaude Codeを自分のVPSで動かしたい。\u003cstrong\u003eまず決まるのは「どのプランを買うか」です。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e各社のページを調べたら、\u003cstrong\u003e全社が「4GB以上」と書いていました。\u003c/strong\u003e 一方、Anthropicの公式要件も4GB以上です。\u003c/p\u003e\n\u003cp\u003eでは2GBでは動かないのか。\u003cstrong\u003e2GBのVPSに手で入れて、動かしました。最大268MBでした。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"結論\"\u003e結論\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e結果\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e各社の要件\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4GB以上\u003c/strong\u003e（2GB以下は非対応と明記する社もある）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e2GBでの実測\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e最大268MB / ファイル作成もコード実行も成功\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eNode.js\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e不要\u003c/strong\u003e（ネイティブインストーラ）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eディスク\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e+206MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eインストール時間\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e6分46秒\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eアカウント\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e有料プラン必須\u003c/strong\u003e（無料のClaude.aiでは使えない）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eただし、\u003cstrong\u003e「4GBは要らない」とは書きません。\u003c/strong\u003e 理由は最後に書きます。\u003c/p\u003e\n\u003ch2 id=\"対応している4社とその必要メモリ\"\u003e対応している4社と、その必要メモリ\u003c/h2\u003e\n\u003cp\u003eClaude Codeのテンプレート／アプリイメージを公式に出しているのは、確認できた範囲でこの4社です。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e提供元\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e形式\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e公表している必要メモリ\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://px.a8.net/svt/ejp?a8mat=4BC72Y+6QWVLE+CO4+25EKCY\" rel=\"nofollow\"\u003e\u003cstrong\u003eXServer VPS\u003c/strong\u003e\u003c/a\u003e\u003cimg border=\"0\" width=\"1\" height=\"1\" src=\"https://www13.a8.net/0.gif?a8mat=4BC72Y+6QWVLE+CO4+25EKCY\" alt=\"\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eアプリイメージ\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4GB以上。2GB以下のプランでは利用不可\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eシンVPS\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eアプリイメージ\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4GB以上。2GB以下のプランでは利用不可\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://px.a8.net/svt/ejp?a8mat=4BC72Y+6Z8Y2A+50+4Z0M6A\" rel=\"nofollow\"\u003e\u003cstrong\u003eConoHa VPS\u003c/strong\u003e\u003c/a\u003e\u003cimg border=\"0\" width=\"1\" height=\"1\" src=\"https://www17.a8.net/0.gif?a8mat=4BC72Y+6Z8Y2A+50+4Z0M6A\" alt=\"\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eスタートアップスクリプト\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e最小3GB、推奨4GB以上\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eKAGOYA CLOUD VPS\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eテンプレート\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e記載を確認できず\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e（表の\u003cstrong\u003eXServer VPS\u003c/strong\u003eと\u003cstrong\u003eConoHa VPS\u003c/strong\u003eは広告リンクです。他社は提携していないため通常のリンクです。\u003cstrong\u003eリンクの有無と、この表に書いた内容は無関係です。\u003c/strong\u003e）\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eXServer VPSとシンVPSは、2GB以下のプランでは選択肢に出てきません。\u003c/strong\u003e 「安いプランを買ってから気づく」ことになります。\u003c/p\u003e\n\u003cp\u003eAnthropicの\u003ca href=\"https://code.claude.com/docs/en/setup\"\u003e公式ドキュメント\u003c/a\u003eも同じです。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eHardware\u003c/strong\u003e: 4 GB+ RAM, x64 or ARM64 processor\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003e4社と公式で、数字が一致しています。\u003c/strong\u003e\u003c/p\u003e\n\u003ch3 id=\"conohaのスクリプトが入れるもの\"\u003eConoHaのスクリプトが入れるもの\u003c/h3\u003e\n\u003cp\u003eConoHaのドキュメントには、中身まで書いてあります。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eソフト\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eバージョン\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eClaude Code\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e最新\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eNode.js\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e22\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eripgrep\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e13.0.0\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eUFW\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e最新\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eFail2ban\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e最新\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e対応OSは \u003cstrong\u003eUbuntu 24.04 LTS のみ\u003c/strong\u003e。\u003c/p\u003e","title":"Claude CodeをVPSで動かす｜対応4社は「4GB以上」。2GBで試したら268MBだった"},{"content":"「2GBのVPSでローカルLLMは動くのか」。動きます。ただし0.5Bまでです。\n0.5Bから1Bに上げた瞬間、生成速度が 15.36 tokens/秒 → 0.07 tokens/秒 に落ちました。219分の1です。段階的に遅くなるのではなく、崖から落ちます。\n3Bはサービスごと落ちました。\n結論 モデル ファイル ディスク増 メモリピーク 生成速度 結果 qwen2.5:0.5b 397MB +380MB 930MB 15.36 tok/s 動く llama3.2:1b 1.3GB +1,260MB 1,201MB（上限） 0.07 tok/s 実用不可 qwen2.5:3b 1.9GB +1,840MB — — 落ちた 必要メモリの目安は「モデルファイルの約2.4倍」。 0.5B（380MB）で930MBでした。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS（GPUなし・CPUのみ） Ollama：0.33.3 枠：systemdの MemoryMax=1200M / MemorySwapMax=1024M でOllamaを隔離 同居：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本が動いている実運用サーバー プロンプト：「日本の首都はどこですか。一文で答えてください。」 同居しているものがあるので、free の全体値は他の処理の影響を受けます。そのため、Ollama単体の数字はすべてcgroup（memory.current）から取っています。\nOllama本体だけで、ディスク2.1GB・メモリ36MB モデルを1つも入れていない状態です。\n値 ディスク +2,160MB 常駐メモリ（cgroup） 36MB 待ち受け 127.0.0.1:11434 メモリは驚くほど軽い。 比較すると位置づけが分かります。\n常駐メモリ Ollama本体 36MB Docker（dockerd + containerd） 約49MB n8n 402MB Dify（16コンテナ） 2,076MB 「AIツールは重い」わけではありません。重いのはモデルです。\nただしディスクは2.1GB持っていきます。CPUしかないVPSでも、GPU用のライブラリを含めて配布されるためです。\nインストールで2時間失った話 ここが実用上いちばん引っかかる場所です。\n公式の手順はこれです。\ncurl -fsSL https://ollama.com/install.sh | sh これを実行したところ、89分かけて55.6%で切れました。\ncurl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1) tar: Unexpected EOF in archive tar: Error is not recoverable: exiting now やり直しです。 インストールスクリプトは curl | zstd -d | tar -x と直結していて、ダウンロードしながら展開しています。 そのため途中で切れても再開できません。\n配布物は 1,433,825,108バイト（1.34GB）。一発勝負で落とし切る必要があります。\n落としてから展開すれば2分 同じファイルが GitHubのリリースにあります。wget -c で落としました。\nwget -c --tries=0 --waitretry=15 --timeout=60 \\ https://github.com/ollama/ollama/releases/download/v0.33.3/ollama-linux-amd64.tar.zst 2026-09-07 20:55:24 (11.3 MB/s) - saved [1433825108/1433825108] 2分1秒で完了しました。\nwget -c を使う理由は2つあります。\n-c は途中から再開できる。 切れても最初からになりません wgetはHTTP/1.1しか使わない。 今回の HTTP/2 PROTOCOL_ERROR は起きません 落としたら、壊れていないか確認してから展開します。\nzstd -t ollama-linux-amd64.tar.zst # 圧縮ファイルの検証 sudo install -o0 -g0 -m755 -d /usr/local/bin /usr/local/lib/ollama sudo tar --zstd -xf ollama-linux-amd64.tar.zst -C /usr/local 展開は10.9秒でした。\n原因は特定できていません。 失敗の直後（20:52）に同じ ollama.com のURLへ curl を投げたら 10.8 MB/s 出ました。つまり配布元が常に遅いわけではありません。あの時間帯だけ経路が細かった可能性が高いですが、確証はありません。\nただし対処法は原因に関係なく有効です。1.34GBを一発勝負で落とす構造そのものが弱い。 落としてから展開してください。\nサービス化は自分で書きます。\nsudo useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama sudo tee /etc/systemd/system/ollama.service \u0026gt; /dev/null \u0026lt;\u0026lt;\u0026#39;EOF\u0026#39; [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/local/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment=\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0026#34; Environment=\u0026#34;OLLAMA_HOST=127.0.0.1:11434\u0026#34; [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload \u0026amp;\u0026amp; sudo systemctl enable --now ollama OLLAMA_HOST=127.0.0.1:11434 を明示しています。 Ollamaに認証はありません。外に開くと誰でもモデルを叩けます。既定値も同じですが、意図として書き残します。\n0.5B：動く。ただし日本語は怪しい ollama pull qwen2.5:0.5b # 38.6秒 値 モデル表示サイズ 397MB ディスク実増 +380MB メモリピーク（cgroup） 930MB ロード時間 3.18秒 プロンプト処理 59.67 tok/s 生成速度 15.36 tok/s 枠に当たった回数 0 15 tokens/秒。 短い応答なら待てる速度です。1,200MBの枠にも当たっていません。\nただし出力がこれでした。\n日本の首都は东京です。 「東京」が簡体字の「东京」になっています。 中国語圏で作られた小型モデルなので、日本語の中に簡体字が混ざります。動くことと使えることは別という、分かりやすい実例です。\n（ollama list の「397MB」と df の「380MB」がずれるのは、Ollamaが10進のMB、du/df が2進のMiBで表示しているためです。同じ値です。）\n1B：ここが崖 ollama pull llama3.2:1b # 2分4秒 値 ディスク実増 +1,260MB メモリピーク 1,201MB（上限に張り付き） 枠に当たった回数 50,879回 ロード時間 43.6秒 プロンプト処理 2.60 tok/s 生成速度 0.07 tok/s 全体の所要時間 3分0.7秒 9トークンの返事に3分かかりました。\nそのときのサーバーの状態です。\n空きメモリ 25MB スワップ 1,304MB I/O待ち 最大86% ロード 3.8 Difyを2GBに載せたときとまったく同じ形です。枠の中でページを出し入れし続けるスラッシングが起きています。\n答え自体は正しく出ました。\n日本の首都は東京です。 0.5Bの簡体字混入がなく、日本語として正しい。品質は上がっています。速度が実用の範囲外なだけです。\n3B：落ちる ollama pull qwen2.5:3b # 2分56秒、ディスク +1,840MB ollama run qwen2.5:3b \u0026#34;...\u0026#34; Error: Post \u0026#34;http://127.0.0.1:11434/api/generate\u0026#34;: EOF サービスが死にました。 10秒刻みの記録に、その瞬間が残っています。\n21:38:42 cgroup 1,200MB スワップ 861MB ← 限界 21:38:46 cgroup 0MB スワップ 0MB ← 消滅 21:38:50 cgroup 37MB ← 再起動後 systemctl show ollama -p NRestarts は NRestarts=1。systemdが1回再起動しています。\n死因は特定できませんでした。 カーネルのOOM記録（journalctl -k）には何も残っておらず、cgroup内の oom_kill カウンタはサービス再起動時に作り直されてリセットされています。枠の中でOOMになった可能性が高いと考えていますが、証拠はありません。\n実用上の結論は変わりません。動きませんでした。\nメモリの目安：モデルファイルの約2.4倍 0.5Bの実測から出た倍率です。\nモデルファイル 380MB → 実際のピーク 930MB（2.4倍） この倍率で逆算すると、1Bのモデル（1,260MB）には約3,000MB必要になります。1,200MBの枠に入るはずがありません。 実測と一致します。\nつまり、使えるモデルの上限はこう決まります。\n載せられるモデルファイル ≒ 空きメモリ ÷ 2.4 空きが1.4GBなら 約580MB以下のモデルまで。0.5Bクラスだけです。\n（cgroupの memory.current にはモデルファイルのページキャッシュも含まれるため、この2.4倍にはキャッシュ分が乗っています。「アプリが確保した量」より大きめの数字である点は割り引いて読んでください。）\n2GBのVPSで、ローカルLLMをやるべきか やれること 0.5Bクラスのモデルが15 tok/sで動く。分類・要約・単純な抽出なら実用範囲 Ollama本体は36MBしか常駐しない。使わないときのコストはほぼゼロ モデルを止めればメモリはすぐ戻る やれないこと 1B以上は無理。 0.07 tok/sは待てる速度ではありません 日本語の品質を求めるなら0.5Bでは足りない（簡体字が混ざる） ディスクは本体2.1GB＋モデル。 3つ入れたら3.4GBでした 実際にやるなら 必要なのは「メモリ ÷ 2.4」の計算だけです。\n空きメモリ 載せられるモデル 現実的な用途 1.4GB（2GBプラン） 〜580MB（0.5Bクラス） 分類・抽出。日本語の生成は厳しい 3GB前後（4GBプラン） 〜1.2GB（1Bクラス） 未検証 7GB前後（8GBプラン） 〜2.9GB（3Bクラス） 未検証 下2行は測っていません。 上の倍率からの計算です。実測したら追記します。\nそして忘れてはいけないのは、GPUがないことです。上の速度はすべてCPUでの推論です。GPU付きの環境とは桁が違います。\nまとめ Ollama本体：メモリ36MB / ディスク2.1GB。デーモンはDockerより軽い 0.5B（380MB）：15.36 tok/s で動く。 ただし日本語に簡体字が混ざる 1B（1.3GB）：0.07 tok/s。 219分の1に落ちる。9トークンに3分 3B（1.9GB）：サービスが落ちる（死因はログに残らず） 必要メモリ ≒ モデルファイル × 2.4 公式インストールスクリプトはレジュームできない。 1.34GBを一発勝負。wget -c で落としてから展開すれば2分 2GBのVPSでローカルLLMをやるなら、0.5Bクラスが上限 「動くか動かないか」ではなく、どこで崖が来るかが分かりました。0.5Bと1Bの間です。\nVPSのプラン選びについては、実測から積み上げた選び方にまとめています。\n","permalink":"https://jimae-ai.com/ollama-2gb-vps-local-llm/","summary":"\u003cp\u003e「2GBのVPSでローカルLLMは動くのか」。\u003cstrong\u003e動きます。ただし0.5Bまでです。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e0.5Bから1Bに上げた瞬間、生成速度が \u003cstrong\u003e15.36 tokens/秒 → 0.07 tokens/秒\u003c/strong\u003e に落ちました。\u003cstrong\u003e219分の1\u003c/strong\u003eです。段階的に遅くなるのではなく、崖から落ちます。\u003c/p\u003e\n\u003cp\u003e3Bはサービスごと落ちました。\u003c/p\u003e\n\u003ch2 id=\"結論\"\u003e結論\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eモデル\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eファイル\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eディスク増\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eメモリピーク\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e\u003cstrong\u003e生成速度\u003c/strong\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e結果\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eqwen2.5:0.5b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e397MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e+380MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e930MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e15.36 tok/s\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e動く\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003ellama3.2:1b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1.3GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e+1,260MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1,201MB（上限）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e0.07 tok/s\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e実用不可\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eqwen2.5:3b\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1.9GB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e+1,840MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e—\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e—\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e落ちた\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e必要メモリの目安は「モデルファイルの約2.4倍」。\u003c/strong\u003e 0.5B（380MB）で930MBでした。\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS（\u003cstrong\u003eGPUなし・CPUのみ\u003c/strong\u003e）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOllama\u003c/strong\u003e：0.33.3\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e枠\u003c/strong\u003e：systemdの \u003ccode\u003eMemoryMax=1200M\u003c/code\u003e / \u003ccode\u003eMemorySwapMax=1024M\u003c/code\u003e でOllamaを隔離\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e同居\u003c/strong\u003e：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本が動いている実運用サーバー\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eプロンプト\u003c/strong\u003e：「日本の首都はどこですか。一文で答えてください。」\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e同居しているものがあるので、\u003ccode\u003efree\u003c/code\u003e の全体値は他の処理の影響を受けます。\u003cstrong\u003eそのため、Ollama単体の数字はすべてcgroup（\u003ccode\u003ememory.current\u003c/code\u003e）から取っています。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"ollama本体だけでディスク21gbメモリ36mb\"\u003eOllama本体だけで、ディスク2.1GB・メモリ36MB\u003c/h2\u003e\n\u003cp\u003eモデルを1つも入れていない状態です。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e値\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eディスク\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e+2,160MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e常駐メモリ（cgroup）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e36MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e待ち受け\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003e127.0.0.1:11434\u003c/code\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003eメモリは驚くほど軽い。\u003c/strong\u003e 比較すると位置づけが分かります。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e常駐メモリ\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eOllama本体\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e36MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eDocker（dockerd + containerd）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約49MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003en8n\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e402MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eDify（16コンテナ）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e2,076MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e「AIツールは重い」わけではありません。重いのはモデルです。\u003c/strong\u003e\u003c/p\u003e","title":"2GBのVPSでローカルLLMは動くのか｜0.5B・1B・3Bを実測したら1Bで崖だった"},{"content":"Difyとn8nを実測したあと、VPSのディスクに 13GB のイメージが残りました（Difyの実測記事）。\n片付けようと docker system prune を叩きました。79.75MBしか消えませんでした。\n「掃除コマンド」は1つではありません。4段階あり、それぞれ触る場所が違います。 段階ごとに df と docker system df を取って、どこで何が消えるかを測りました。\n結論：4段階で消えるものはこれだけ違う 段階 コマンド 消えたもの 回収 1 docker system prune 停止中のコンテナ 79.75MB 2 docker image prune -a 未使用イメージ13個 12.96GB 3 docker volume prune 匿名ボリューム20個 51.45kB 4 docker volume prune -a 名前付きボリューム3個 5.713MB 第1段階だけで止めると、13GBがそのまま残ります。 第3段階で止めると、データが入っているほうが残ります。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / Docker 29系 片付ける対象：Difyのイメージ12個（10.6GB）、n8nのイメージ1個（2.47GB）、コンテナ1個、ボリューム23個 稼働中のコンテナ：なし（測定前にすべて停止・削除済み） 開始時：ディスク使用 23,724MB / 空き 71,808MB 掃除を始める前の docker system df です。\nTYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 13 1 13.59GB 10.84GB (79%) Containers 1 0 79.75MB 79.75MB (100%) Local Volumes 23 1 5.764MB 68.32kB (1%) Build Cache 0 0 0B 0B 第1段階：docker system prune は79.75MBしか消さない いちばん多く紹介されているコマンドです。\ndocker system prune -f Deleted Containers: 0d66d23f8993... Total reclaimed space: 79.75MB 変化 ディスク使用 23,724MB → 23,648MB（−76MB） /var/lib/containerd 13G → 13G（変わらず） 13GBのイメージには一切触っていません。\ndocker system prune が消すのは、停止中のコンテナ・未使用のネットワーク・タグの付いていないイメージ（dangling）・ビルドキャッシュです。タグの付いた未使用イメージは対象外です。\nそして「回収できる量」が増える 掃除した直後の docker system df を見てください。\n実行前 実行後 Images RECLAIMABLE 10.84GB (79%) 13.32GB (98%) Local Volumes RECLAIMABLE 68.32kB (1%) 5.764MB (100%) 掃除したのに、掃除すべき量が増えました。\n理由は単純で、コンテナを削除したことで、そのコンテナが使っていたイメージとボリュームが、「未使用」に変わったからです。\nACTIVE の列が 1 → 0 になっているのがそれです。この数字は「いま何が使われているか」で動くので、掃除の進捗を測る指標には使えません。\n第2段階：docker image prune -a で12.96GB タグ付きの未使用イメージまで消すには -a が要ります。\ndocker image prune -a -f untagged: langgenius/dify-api:1.17.0 untagged: langgenius/dify-plugin-daemon:0.6.10-local untagged: docker.n8n.io/n8nio/n8n:latest ... Total reclaimed space: 13.59GB 変化 ディスク使用 23,648MB → 10,690MB 実際に減った量 12,958MB（12.96GB） 空き 71,884MB → 84,841MB /var/lib/containerd 13G → 3.2M ここで初めて13GBが消えます。\n申告13.59GB、実測12.96GB Dockerは「13.59GB回収した」と言いますが、df で見た実際の減少は 12.96GB。0.63GBのズレがあります。\nDifyの記事では docker images のサイズを単純に足すと約14GBになり、実際のディスク増加は10.6GBでした。どちらも多めに出ます。 レイヤーが共有されている分の数え方によるものと考えられます。\nただし、docker system df（13.59GB）のほうが docker images の合計（14GB）より実測に近いという結果でした。容量を見積もるなら docker system df を使ってください。\n第3段階：ボリュームは、両方のコマンドで生き残る ここが本題です。第2段階まで終えた時点の docker system df がこれです。\nImages 0 0 0B 0B Containers 0 0 0B 0B Local Volumes 23 0 5.764MB 5.764MB (100%) イメージもコンテナもゼロ。ボリュームだけ23個そのまま残っています。\ndocker system prune も docker image prune -a も、ボリュームには一切触りません。\ndocker volume prune -f Deleted Volumes: 2d47d733e1f370bc82a287a45663c11dea97f10f363d3e0ab7f038aaa81f54f8 b353974c60397d63681bb4157a97785b2b489cec4659f65bfdb364a6bd8dd138 （… 20個 …） Total reclaimed space: 51.45kB 20個消えて51.45kB。 残ったのはこの3つです。\nn8n_data docker_dify_agent_local_sandbox_home docker_dify_agent_local_sandbox_workspace docker volume prune は、既定では匿名ボリュームしか消しません。（2d47d733... のような16進の名前が匿名ボリュームです。コンテナが勝手に作ります。）\n第4段階：-a を付けて、ようやく名前付きが消える docker volume prune -a -f Deleted Volumes: docker_dify_agent_local_sandbox_workspace n8n_data docker_dify_agent_local_sandbox_home Total reclaimed space: 5.713MB 3個で5.713MB。\nいちばん危ないのは第3段階で止めることです 数字を並べます。\n個数 容量 全体に占める割合 匿名ボリューム 20個 51.45kB 0.9% 名前付きボリューム 3個 5.713MB 99.1% 20個消しても0.9%。3個消したら99.1%。\n当然です。名前を付けるのは、残したいデータがあるときだからです。 匿名ボリュームは中身がほとんど空で、名前付きにデータが入っている。\nそして docker volume prune は、その名前付きのほうを残します。\n容量ではなく、中身の問題です 5.7MBという数字を見て「誤差じゃないか」と思うかもしれません。容量は問題ではありません。\n今回残った n8n_data は、n8nの設定データそのものです。n8nは自動化ツールで、外部サービスに接続するためのAPIキーやパスワードを保存します。\nつまり、\nイメージを13GB消して コンテナも消して docker system df が「Images 0 / Containers 0」と表示していても 認証情報が入ったボリュームは、そこに残り続けます 「片付いた」と思って別の用途にサーバーを回す、あるいは解約する。 そのとき、この5.7MBのことは誰も覚えていません。\n消す前に、必ず中身を確認してください。\ndocker volume ls docker volume inspect \u0026lt;ボリューム名\u0026gt; # Mountpoint が実体のパス sudo ls -la /var/lib/docker/volumes/\u0026lt;ボリューム名\u0026gt;/_data /var/lib/docker を見ても何も分かりません 掃除の各段階で、この2つを測っていました。\n掃除前 掃除後 /var/lib/docker 6.3MB 368KB /var/lib/containerd 13G 3.2M Docker 29系はイメージの実体をcontainerdの管理下に置きます。 /var/lib/docker は最初から最後まで数MBしかありません。\n「ディスクが減らない」を調べるとき、/var/lib/docker の du を見ても答えは出ません。 見るべきは docker system df と、df で見たディスク全体です。\n（私は前の記事でここを間違えて、訂正を入れました。）\nメモリは戻りません ディスクは片付きましたが、メモリは別です。\nイメージ0個・コンテナ0個・ボリューム0個の状態で、上位プロセスがこれです。\npython3 70.3MB python 60.1MB dockerd 52.6MB ← 常駐 fwupd 43.7MB systemd-journal 35.4MB containerd 31.3MB ← 常駐 dockerd と containerd で合計83.9MB（RSS）が居座っています。 動かすものが1つもないのに、です。\nシステム全体への影響は約49MB（Difyの記事で実測）。Dockerを使わなくなったなら、掃除ではなくアンインストールが要ります。\n安全な片付けの順番 # 1. まず何があるか見る（消す前に必ず） docker system df docker volume ls docker ps -a # 2. 名前付きボリュームの中身を確認する docker volume inspect \u0026lt;名前\u0026gt; # 3. コンテナを止めて消す docker compose down # または docker rm # 4. イメージを消す（-a が要る） docker image prune -a # 5. ボリュームを消す（本当に消していいと確認してから） docker volume prune # 匿名だけ docker volume prune -a # 名前付きも。取り返しがつきません # 6. 結果を確認する docker system df df -h / -a を付けるコマンドは、付けた瞬間に取り返しがつきません。 特に第5段階は、中身を見てからにしてください。\nまとめ docker system prune はイメージを消さない。 今回消えたのは79.75MB（停止中コンテナのみ） タグ付きイメージを消すには docker image prune -a。 ここで12.96GB減った docker system df の RECLAIMABLE は掃除すると増える。 コンテナを消すとイメージが「未使用」に変わるため。進捗の指標にならない 申告13.59GB、実測12.96GB。 docker system df は多めに出るが、docker images の合計よりは正確 ボリュームは上記2つのどちらでも消えない docker volume prune は匿名だけ。 匿名20個=51.45kB、名前付き3個=5.713MB。容量の99.1%が残る 残るのは、データが入っているほうです。 n8nなら認証情報が入っています /var/lib/docker を見ても分からない。 Docker 29系の実体は /var/lib/containerd メモリは戻らない。 dockerd + containerd で83.9MB（RSS）が常駐したまま 「ディスクが減らない」という現象の正体は、掃除コマンドが4つあって、それぞれ触る場所が違うというだけのことでした。\nそしていちばん大事なのは、最後まで消すことではありません。 第3段階で止まったとき、何が残っているかを知っていることです。\n","permalink":"https://jimae-ai.com/docker-prune-disk-not-freed/","summary":"\u003cp\u003eDifyとn8nを実測したあと、VPSのディスクに \u003cstrong\u003e13GB\u003c/strong\u003e のイメージが残りました（\u003ca href=\"/dify-2gb-vps-memory/\"\u003eDifyの実測記事\u003c/a\u003e）。\u003c/p\u003e\n\u003cp\u003e片付けようと \u003ccode\u003edocker system prune\u003c/code\u003e を叩きました。\u003cstrong\u003e79.75MBしか消えませんでした。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e「掃除コマンド」は1つではありません。\u003cstrong\u003e4段階あり、それぞれ触る場所が違います。\u003c/strong\u003e 段階ごとに \u003ccode\u003edf\u003c/code\u003e と \u003ccode\u003edocker system df\u003c/code\u003e を取って、どこで何が消えるかを測りました。\u003c/p\u003e\n\u003ch2 id=\"結論4段階で消えるものはこれだけ違う\"\u003e結論：4段階で消えるものはこれだけ違う\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e段階\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eコマンド\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e消えたもの\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e回収\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e1\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003edocker system prune\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e停止中のコンテナ\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e79.75MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e2\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003edocker image prune -a\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e未使用イメージ13個\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e12.96GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e3\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003edocker volume prune\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e匿名\u003c/strong\u003eボリューム20個\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e51.45kB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e4\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ccode\u003edocker volume prune -a\u003c/code\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e名前付き\u003c/strong\u003eボリューム3個\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e5.713MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003e第1段階だけで止めると、13GBがそのまま残ります。\u003c/strong\u003e\n\u003cstrong\u003e第3段階で止めると、データが入っているほうが残ります。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS / Docker 29系\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e片付ける対象\u003c/strong\u003e：Difyのイメージ12個（10.6GB）、n8nのイメージ1個（2.47GB）、コンテナ1個、ボリューム23個\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e稼働中のコンテナ\u003c/strong\u003e：なし（測定前にすべて停止・削除済み）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e開始時\u003c/strong\u003e：ディスク使用 23,724MB / 空き 71,808MB\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e掃除を始める前の \u003ccode\u003edocker system df\u003c/code\u003e です。\u003c/p\u003e","title":"docker system prune では13GBが1バイトも消えなかった｜4段階に分けて実測した"},{"content":"記事を1本追加して hugo を叩いたら、ビルドごと落ちました。\nERROR error building site: render: failed to render pages: render of \u0026#34;/categories\u0026#34; failed: \u0026#34;.../themes/PaperMod/layouts/baseof.html:24:7\u0026#34;: execute of template failed: template: taxonomy.html:24:7: executing \u0026#34;taxonomy.html\u0026#34; at \u0026lt;partialCached \u0026#34;header.html\u0026#34; . .Page\u0026gt;: error calling partialCached: \u0026#34;.../PaperMod/layouts/_partials/header.html:92:38\u0026#34;: execute of template failed: template: _partials/header.html:92:38: executing \u0026#34;_partials/header.html\u0026#34; at \u0026lt;site.GetPage\u0026gt;: error calling GetPage: page reference \u0026#34;選び方\u0026#34; is ambiguous 追加した記事のフロントマターは、これでした。\ncategories: [\u0026#34;選び方\u0026#34;] tags: [\u0026#34;VPS\u0026#34;, \u0026#34;さくらのVPS\u0026#34;, \u0026#34;メモリ\u0026#34;, \u0026#34;n8n\u0026#34;, \u0026#34;Dify\u0026#34;, \u0026#34;スペック\u0026#34;, \u0026#34;選び方\u0026#34;] 選び方 をカテゴリとタグの両方に書いていました。 これだけです。\n犯人はテーマのこの1行 _partials/header.html の92行目です。\n{{- $is_search := eq (site.GetPage .KeyName).Layout `search` }} メニュー項目が検索ページかどうかを判定するために、site.GetPage を呼んでいます。\n.KeyName は、メニュー項目に identifier があればそれ、無ければ name です。 私の設定はこうでした。\nmenu: main: - name: 選び方 url: /categories/choose/ weight: 40 identifier がないので、site.GetPage \u0026quot;選び方\u0026quot; が呼ばれます。\nそこに /categories/選び方/ と /tags/選び方/ の2つが存在する。Hugoはどちらを指しているか決められず、エラーを返します。テンプレート側でエラー処理をしていないので、サイト全体のビルドが止まります。\n6パターン再現して、条件を特定した 「たぶんこれが原因」で終わらせず、同じHugo（v0.165.0+extended）とPaperModで最小構成を作り、条件を変えて試しました。\nメニューの name identifier カテゴリとタグが同名 _index.md 結果 選び方 なし あり あり 失敗 選び方 なし あり なし 失敗 選び方 なし なし あり 成功 構築（別の名前） なし あり あり 成功 選び方 choose あり あり 成功 落ちるのは、3つが同時に揃ったときだけです。\nメニュー項目の name（または identifier）が 2つのタクソノミー（categories と tags）の両方に、同じ名前の項目として存在する 分かったことが2つあります。\nカテゴリの _index.md があるかどうかは関係ありません。 無くても落ちます メニューに載っていない名前なら、カテゴリとタグが同名でも落ちません。 site.GetPage が呼ばれないからです つまり 「カテゴリ名とタグ名を同じにしてはいけない」ではなく、「メニューに出しているカテゴリ名を、タグにも使ってはいけない」 が正確な条件です。\n直し方は2つ 1. タグから消す（今回やったほう） categories: [\u0026#34;選び方\u0026#34;] tags: [\u0026#34;VPS\u0026#34;, \u0026#34;さくらのVPS\u0026#34;, \u0026#34;メモリ\u0026#34;, \u0026#34;n8n\u0026#34;, \u0026#34;Dify\u0026#34;, \u0026#34;スペック\u0026#34;] カテゴリが本体で、タグは重複していただけなので、消すのはタグの側です。\nsed -i \u0026#39;s/, \u0026#34;選び方\u0026#34;\\]/]/\u0026#39; content/posts/該当記事.md hugo --minify そもそもカテゴリとタグに同じ言葉を入れる意味はありません。 読者から見ても、同じ名前のページが2つある状態は分かりにくい。直すべきは設計のほうでした。\n2. メニューに identifier を付ける 同名のタグをどうしても残したい場合は、こちらです。\nmenu: main: - name: 選び方 identifier: choose # ← これ url: /categories/choose/ weight: 40 .KeyName が choose になるので、site.GetPage \u0026quot;choose\u0026quot; が呼ばれます。該当するページが無いので nil が返りますが、ビルドは通ります（テストで確認しました）。\n表示名は「選び方」のまま変わりません。\n再発を防ぐなら ── そして、その検査で私はもう一度つまずいた デプロイスクリプトの先頭で検査すれば、同じ事故は防げます。ただし雑に書くと、自分の首を絞めます。\n最初、私はこう書きました。\ngrep -h \u0026#34;^tags:\u0026#34; content/posts/*.md | grep -E \u0026#34;構築|実測|トラブル|選び方\u0026#34; この記事自身が引っかかって、デプロイが止まりました。\n当然です。上のほうに「悪い例」としてフロントマターを載せてあるので、grep はそれを拾います。解説のためのコード例を、本物の設定として誤検知したわけです。\n正しくは、先頭の --- で挟まれた範囲だけを見ます。\nfor f in content/posts/*.md; do line=$(awk \u0026#39;NR==1 \u0026amp;\u0026amp; $0==\u0026#34;---\u0026#34; {inb=1; next} inb \u0026amp;\u0026amp; $0==\u0026#34;---\u0026#34; {exit} inb \u0026amp;\u0026amp; /^tags:/ {print; exit}\u0026#39; \u0026#34;$f\u0026#34;) case \u0026#34;$line\u0026#34; in *\u0026#39;\u0026#34;構築\u0026#34;\u0026#39;*|*\u0026#39;\u0026#34;実測\u0026#34;\u0026#39;*|*\u0026#39;\u0026#34;トラブル\u0026#34;\u0026#39;*|*\u0026#39;\u0026#34;選び方\u0026#34;\u0026#39;*) echo \u0026#34;NG: $f: $line\u0026#34; \u0026gt;\u0026amp;2; exit 1 ;; esac done Markdownを機械的に検査するときは、フロントマターと本文を分けてください。 本文にはコード例が入ります。ファイル全体を grep すると、書けば書くほど誤検知が増えます。\nここからは、私がやった誤診の話 技術的な原因は上のとおりですが、この場で私はもう1つ間違えています。 そちらのほうが再発しやすいので書き残します。\nビルドが落ちた直後、私はこう確認しました。\ncurl -sI https://example.com/新しい記事/ # 404 curl -sI https://example.com/categories/choose/ # 404 2件とも404。私は「サイトが落ちた」と判断しました。 デプロイスクリプトが --cleanDestinationDir を使っていたので、「ビルド失敗で公開ディレクトリが空になった」と考えたわけです。\n間違いでした。\n叩いた2つのURLは、どちらも今回のビルドで初めて生成されるはずだったページです。ビルドが失敗した以上、404になって当たり前でした。既存の記事のURLを、私は1つも確認していませんでした。\n確かめました 同じHugoで、同じ手順を再現しました。成功するビルドで出力先を作り、そのあと同じ出力先へ、壊れた状態で --cleanDestinationDir 付きビルドを流します。\n1回目（成功）のファイル数 : 20 2回目 終了コード : 1 ← 同じ ambiguous エラー 2回目（失敗）後のファイル数 : 20 ← 減っていない index.html : 残っている Hugoはビルドに失敗しても、出力先のファイルを消しません。 --cleanDestinationDir の掃除は、ビルドが成功したあとに走ります。\nつまりあのとき、既存の記事は普通に配信され続けていました。 欠けていたのは新しいページだけです。\n教訓 「404が出た」と「サイトが落ちた」は別のことです。\n障害を判定するときは、今回の変更と無関係なURLを叩いてください。 トップページ1つで足ります。\ncurl -s -o /dev/null -w \u0026#39;%{http_code}\\n\u0026#39; https://example.com/ これが200なら、落ちているのはサイトではなく、新しいページだけです。対応の緊急度がまったく変わります。\n私は「サイトが落ちた」と宣言して、緊急復旧の手順を組み立てました。結果的に直りましたが、判断の根拠は足りていませんでした。\nまとめ PaperModのメニューは site.GetPage .KeyName を呼ぶ。 identifier が無ければメニューの name が使われる その名前が categories と tags の両方に存在すると、page reference is ambiguous でビルドごと落ちる 条件はメニュー名との重複。 カテゴリの _index.md の有無は無関係で、メニューに無い名前なら同名でも落ちない 直し方は2つ。 タグから消す（推奨）／メニューに identifier を付ける Hugoはビルド失敗時に出力先を消さない。 --cleanDestinationDir の掃除は成功後 404を見たら、変更と無関係なURLも叩く。 それをやらずに「落ちた」と言わない 検査スクリプトはフロントマターだけを見る。 ファイル全体を grep すると、記事内のコード例を誤検知する エラーメッセージは page reference \u0026quot;選び方\u0026quot; is ambiguous としか言いません。どこで呼ばれた GetPage なのかは、スタックの header.html:92:38 を最後まで読まないと分かりません。 Hugoのエラーは長いですが、末尾ではなく途中の行番号に答えが書いてあります。\n","permalink":"https://jimae-ai.com/hugo-papermod-ambiguous-page-reference/","summary":"\u003cp\u003e記事を1本追加して \u003ccode\u003ehugo\u003c/code\u003e を叩いたら、ビルドごと落ちました。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eERROR error building site: render: failed to render pages:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003erender of \u0026#34;/categories\u0026#34; failed: \u0026#34;.../themes/PaperMod/layouts/baseof.html:24:7\u0026#34;:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eexecute of template failed: template: taxonomy.html:24:7:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eexecuting \u0026#34;taxonomy.html\u0026#34; at \u0026lt;partialCached \u0026#34;header.html\u0026#34; . .Page\u0026gt;:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eerror calling partialCached: \u0026#34;.../PaperMod/layouts/_partials/header.html:92:38\u0026#34;:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eexecute of template failed: template: _partials/header.html:92:38:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eexecuting \u0026#34;_partials/header.html\u0026#34; at \u0026lt;site.GetPage\u0026gt;:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eerror calling GetPage: page reference \u0026#34;選び方\u0026#34; is ambiguous\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e追加した記事のフロントマターは、これでした。\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ecategories\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;選び方\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003etags\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;VPS\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;さくらのVPS\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;メモリ\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;n8n\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Dify\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;スペック\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;選び方\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e選び方\u003c/code\u003e をカテゴリとタグの両方に書いていました。\u003c/strong\u003e これだけです。\u003c/p\u003e\n\u003ch2 id=\"犯人はテーマのこの1行\"\u003e犯人はテーマのこの1行\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003e_partials/header.html\u003c/code\u003e の92行目です。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-go-html-template\" data-lang=\"go-html-template\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cp\"\u003e{{-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nx\"\u003e$is_search\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e:=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eeq\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esite\u003c/span\u003e\u003cspan class=\"na\"\u003e.GetPage\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"na\"\u003e.KeyName\u003c/span\u003e\u003cspan class=\"o\"\u003e)\u003c/span\u003e\u003cspan class=\"na\"\u003e.Layout\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e`search`\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"cp\"\u003e}}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eメニュー項目が検索ページかどうかを判定するために、\u003ccode\u003esite.GetPage\u003c/code\u003e を呼んでいます。\u003c/p\u003e","title":"Hugoが page reference is ambiguous で落ちた｜カテゴリ名とタグ名を同じにしていた"},{"content":" 本記事はプロモーションを含みます。 記事内の一部のリンクは広告リンクです。リンクの有無で内容を変えていません。 掲載している数値はすべて自分のサーバーで実際に測った値か、公式ドキュメントの記載です。\n「AI用途のVPSは4GB以上がおすすめです」。よく見る書き方です。\nその4GBの内訳がどこにも書いてありません。 OSがいくら使うのか、ツールがいくら足されるのか、どこに余裕を見ているのか。根拠が出てこないので、自分の用途に当てはめようがない。\nこのサイトでは、ここまで4本の記事で全部自分で測ってきました。 その数字を積み上げて、必要なスペックを出します。\n先に結論 やりたいこと メモリ ディスク 根拠 静的サイト＋小さな業務アプリ 1〜2GB 20GB〜 実測（アプリ3本で166MB） ＋ n8n で自動化 2GB 50GB〜 実測（+402MB、空き1.1GB残） ＋ Dify（起動して置くだけ） 4GB 100GB〜 実測（Dify単体で2,076MB） Dify を実際に使う 8GB 100GB〜 推定・未検証 ＋ ローカルLLM（0.5Bクラス） 2GB 20GB〜 実測（本体2.1GB＋モデル） ローカルLLM（1B以上） 4GB〜 50GB〜 推定・未検証 「実測」と書いた行は測った数字です。「未検証」の行は測っていません。どこまでが実測でどこからが推測か、はっきり分けて書きます。\n土台：OSと常駐デーモンで何MB持っていかれるか まずアプリを何も載せない状態のコストです。ここを知らないと積み上げができません。\nこのサーバー（さくらのVPS 2Gプラン / Ubuntu 24.04）で、再起動直後・Dockerとnginxと自作アプリ1本が動いている状態が 398MB でした。\n内訳のうち、多くの人が見落とすものが2つあります。\n1. VPSでは働きようがないデーモンが50〜100MB 最初の記事で測った内訳です。\nプロセス RSS 本来の用途 fwupd 44.0MB 物理デバイスのファームウェア更新 multipathd 26.7MB ストレージへの複数I/Oパスの管理 udisksd 13.4MB ディスク・リムーバブルメディアの管理 ModemManager 12.8MB モバイル通信モデムの管理 VPSに物理ファームウェアはありません。モバイル通信のモデムも刺さっていません。常駐3つで約53MB、fwupd が起動していると約97MB。\nさらに 43時間の連続測定では、この fwupd が瞬間的に 188MB まで跳ねていました。自作アプリの最大値（87.9MB）の2倍以上です。\nプランを上げる前に、まずここを見てください。\n2. Docker を入れると 49MB が恒久的に乗る コンテナを1本も動かしていない状態で、dockerd と containerd が常駐します。\ndockerd 49.4MB containerd 50.6MB RSSの合計は100MBですが、システム全体の増加として観測できたのは 約49MB でした（RSSは共有ライブラリを重複して数えるため、単純合計は実際の消費と一致しません）。\ncontainerd の存在を忘れないでください。 dockerd とほぼ同じサイズがもう1本います。そして docker stop してもこの2つは消えません。Dockerを入れた時点で、恒久的に49MBです。\nツールごとの実測コスト n8n：+402MB 実測記事の数字です。\n段階 増分 Dockerデーモン +38MB n8nコンテナ起動 +328MB 管理画面を開いてワークフロー1本 +36MB 合計 +402MB 正体は Node.jsのプロセス2本（305.6MB + 117.5MB）でした。アプリケーションが重いのではなく、ランタイムが2本立ち上がる構造です。\n2GBプランで、載せてもまだ1.1GB空いていました。\nDify：+2,076MB 実測記事の数字です。桁が変わります。\n値 立ち上がるコンテナ 16本 物理メモリ上 1,195MB スワップ上 881MB 合計 2,076MB n8nは1本、Difyは16本。api / worker / web / PostgreSQL / Redis / ベクトルDB / プラグイン基盤 …… が一式ついてきます。\nそしてこの2,076MBは、ワークフロー0本・ナレッジ0件・アクセス0の、完全にアイドルの状態の数字です。\nここは注意して読んでください。 この測定では、Difyに与えたメモリ枠を1,200MBに絞っていました。そのため881MBがスワップへ押し出されています。枠を広げれば、スワップに落ちていた分が物理メモリに乗るだけで、合計の要求量はおおむね変わらないと考えられます。 ただしこれは推定です。 メモリを増やした環境での実測はこれからやります。\nローカルLLM（Ollama）：本体36MB＋モデル×2.4倍 実測記事の数字です。\n値 Ollama本体（常駐メモリ） 36MB Ollama本体（ディスク） 2,160MB モデルの必要メモリ ファイルサイズ × 約2.4 本体は36MBしか常駐しません。 Docker（49MB）より軽い。重いのはモデルのほうです。\n0.5Bのモデル（ファイル380MB）で、メモリのピークは実測 930MB。この倍率で逆算できます。\n載せられるモデルファイル ≒ 空きメモリ ÷ 2.4 そして速度の崖は0.5Bと1Bの間にありました。\nモデル 生成速度 0.5B 15.36 tok/s 1B 0.07 tok/s 3B サービスが落ちた 219分の1です。 段階的に遅くなるのではありません。2GBのVPSでは0.5Bクラスが上限でした（GPUなし・CPUのみ）。\nClaude Code：+268MB Claude CodeをVPSで動かすで測りました。\n値 実行中の最大メモリ 268MB ディスク 206MB Node.js 不要 公式のシステム要件は「4GB以上のRAM」です。 2GBのこのサーバーで実際に動きましたが、測ったのは10行程度のコードを書かせる軽い作業だけです。大きなリポジトリを読ませたときは測っていません。\nOllamaと違ってモデルを持たないので、ディスクは206MBで済みます。重いのはモデルであって、AIツールそのものではないという点は、ここでも同じです。\n足し算してプランを決める 土台とツールを足すだけです。\nn8n だけの場合 土台 約400MB ＋ n8n 402MB = 約800MB → 2GBプランで、まだ1.1GB余る（実測どおり） Dify を入れる場合 土台 約400MB ＋ Dify 2,076MB = 約2,480MB → 2GBプランには入らない。4GBが最低ライン 2GBのマシンに2,076MBのものを載せようとすると何が起きるかは、実際にやりました。\nスワップに881MB押し出され CPUのI/O待ちが最大91% ロードアベレージ5.72 SSHの接続が切れました 通常は数秒で終わるデータベースのマイグレーションに約4分 起動してしまえば静止しますが（load 0.2 / CPUアイドル98%）、そこに至るまでの4分間、サーバーは事実上使えません。\n「余裕」をどれくらい見るか 実測から言うと、OSのメンテナンス用に最低300MBは空けておくべきです。\n43時間の記録で、メモリのピークを作っていたのは自作アプリではなく unattended-upgrades（Ubuntuの自動更新） でした。平常時400MBのところ、朝6時22分に641MBまで上がっていました。\nしかもこの自動更新は、依存パッケージを更新してアプリを勝手に再起動します。 実際、記録の中で自作アプリのRSSが 72.0MB → 43.3MB に落ちた瞬間が残っていました。\n空きギリギリで運用していると、深夜の自動更新でOOM Killerが走ります。 ここは削れません。\n見落とされがち：先に埋まるのはディスク メモリの話ばかりされますが、AI用途で先に効くのはディスクです。\nイメージのサイズ n8n 2.47GB Dify 10.6GB Difyの dify-api は1本で4.06GB。n8nのイメージ全体より大きい。\nさくらのVPS 2Gプランの標準SSDは50GBです。Ubuntuの基本構成で約10GB使うので、Difyを入れると残り約27GB。 ここにローカルLLMのモデルファイル（1つ数GB）を足していくと、メモリより先にディスクが苦しくなります。\n私自身、測る前はこの順番を逆に考えていました。\nなお、Docker 29系ではイメージの実体が /var/lib/containerd に置かれます。/var/lib/docker を見ても分かりません（実測すると5.9MBしかありませんでした）。内訳を見るなら docker system df を使ってください。\nCPUはほとんど要りません これは意外だと思います。プラン選びでCPUコア数を気にする必要は、ほぼありません。\n43時間・2,590サンプルの実測です。\n指標 中央値 最悪値 CPUアイドル率 100% 57% ロードアベレージ(1分) 0.02 1.21 Difyを16コンテナ動かしている定常状態でも、CPUアイドル98% / ロード0.2〜0.4 でした。\nCPUが跳ねるのは起動時と、バッチ処理が走る間だけです。しかも43時間の記録では、バッチ処理はCPUを35%使ってもメモリは動きませんでした（データを1件ずつ処理する型なので、全部をメモリに載せない）。\n「重い処理＝メモリが要る」は、いつも成り立つわけではありません。\nさくらのVPSはメモリを上げるとvCPUも一緒に増える構成なので、メモリで選べばCPUは自動的についてきます。 逆にCPU目当てで上位プランを選ぶ理由は、AI用途では薄いと考えています。\nスワップは「足りないメモリの代わり」にはならない Difyの実測で、はっきりしました。\nスワップを2GB用意してあったので、2GBのマシンで2,076MBのDifyは起動しました。落ちもしませんでした。 しかしその代償が、I/O待ち91%とSSH切断です。\nスワップは「緩衝材」であって「増設メモリ」ではありません。\n一方で、緩衝材としては確実に効きます。43時間の記録で、メモリに1.3GB以上の余裕がある状態でもスワップは最大46MB使われていました。 長時間触られていないページが静かに退避されているだけで、逼迫していなくてもLinuxはこれをやります。\nそしてさくらのVPSでは、スワップなしのイメージが提供される場合があります。 公式マニュアル「swapfileの追加」に「一部、スワップパーティションを含まないイメージの提供を行っております」と明記されており、追加手順も公式に用意されています。\n私が確認した範囲では、運用中の4台すべてがスワップ0でした。契約したら最初に確認してください。\nswapon --show # 何も出なければスワップなし free -h # Swap: の行が 0B なら同じ さくらのVPSのプラン対応 2026年9月時点の公式価格（税込・月額）と、上の積み上げを重ねたものです。\nプラン vCPU SSD 月額 この記事の用途で言うと 512MB 1 20GB ¥685 静的サイト専用。ツールは載りません 1GB 2 30GB ¥972 静的サイト＋小さなアプリまで 2GB 3 50GB ¥1,706 n8nで自動化するならここ（実測で1.1GB余る） 4GB 4 100GB ¥3,888 Difyを置くならここが最低ライン 8GB 6 200GB ¥7,776 Difyを実用する / 1B以上のローカルLLM（未検証） 16GB 8 400GB ¥15,552 — 価格・仕様は変わります。申し込む前に公式の最新情報を確認してください。\nさくらのVPS公式：https://vps.sakura.ad.jp/\n（上記は広告リンクです。この記事の数値と結論は、提携の有無とは無関係です。 私はこのサーバーで実際に測っていて、その内容をリンクのために変えていません。）\n迷ったら小さく始めてよい理由 さくらのVPSは、あとからプランを上げられます。\n公式マニュアルの「スケールアップ」に条件が書かれています。\nIPアドレスは変わりません（「プラン変更後も以前と同じIPアドレスをご利用いただけます」） サーバーを停止して行います。その間サイトは落ちます ディスク容量が減るプランへは変更できません。つまり下げられません 課金は新プラン2か月分から、旧プランの未使用分を日割りで差し引き IPが変わらないので、DNSもTLS証明書も設定し直す必要がありません。 ここは大きいです。\nしたがって、判断に迷ったら小さいプランから始めて構いません。 上げるのは簡単で、下げるのは（実質）できない。それが分かっていれば、最初に上位プランを掴む理由はありません。\n「とりあえず4GB」より「2GBで測ってから決める」 ほうが、この構造には合っています。\n測っていないこと 正直に書きます。この記事で未検証なのは3点です。\nメモリ4GB・8GBでの実測。 Difyがスワップなしで動いたとき、実際に何MBに落ち着くのか Difyを実際に使ったときのコスト。 上の2,076MBは完全にアイドルの数字です。ワークフローを組み、ナレッジを入れ、モデルを呼んだらどうなるかは測っていません 4GB以上でのローカルLLM。 2GBでは0.5Bが上限だと実測しましたが、1B・3Bがスワップなしの環境で実用速度になるかは測っていません この3つを「たぶん8GBあれば大丈夫」で埋めるつもりはありません。 測ってから追記します。\nまとめ 土台（OS＋常駐デーモン＋Docker）で約400MB。うち50〜100MBはVPSでは働きようがないデーモン n8nは+402MB。2GBプランで足りる（実測で1.1GB余る） Difyは+2,076MB。2GBには入らない。4GBが最低ライン 余裕は最低300MB。自動更新が朝6時に641MBまで上げる ディスクのほうが先に埋まる。Difyのイメージだけで10.6GB ローカルLLMは本体36MB＋モデル×2.4倍。2GBでは0.5Bクラスが上限（1Bで0.07 tok/s） CPUはほとんど要らない。実測でアイドル率の中央値100%、Dify稼働中でも98% スワップは緩衝材であって増設メモリではない。ただし無いと危ない 迷ったら小さく始めてよい。あとからIPを変えずに上げられる 「何GB必要か」は、土台の実測値にツールの実測値を足すだけで出せます。この記事の数字はすべて自分のサーバーで測ったもので、測っていないものは測っていないと書きました。\n次はメモリを増やした環境で同じ手順・同じ間隔で測り直します。 上の未検証3点を、推測ではなく数字で埋めます。\nこの記事で使った測定記事 さくらのVPS 2GBで自作システムを3本動かしている — 土台の内訳と、働きようがないデーモン 43時間、1分ごとにVPSを測り続けた — ベースライン、自動更新のピーク、CPUとメモリが連動しないこと 2GBのVPSにn8nは載るのか — n8nの402MB 2GBのVPSにDifyは載るのか — Difyの2,076MB、スワップとI/O待ち 2GBのVPSでローカルLLMは動くのか — Ollamaの36MB、モデル×2.4倍、1Bの崖 Claude CodeをVPSで動かす — 268MB、公式要件4GBとの差、対応4社の比較 ","permalink":"https://jimae-ai.com/ai-vps-memory-requirement/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e本記事はプロモーションを含みます。\u003c/strong\u003e 記事内の一部のリンクは広告リンクです。\u003cstrong\u003eリンクの有無で内容を変えていません。\u003c/strong\u003e 掲載している数値はすべて自分のサーバーで実際に測った値か、公式ドキュメントの記載です。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e「AI用途のVPSは4GB以上がおすすめです」。よく見る書き方です。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eその4GBの内訳がどこにも書いてありません。\u003c/strong\u003e OSがいくら使うのか、ツールがいくら足されるのか、どこに余裕を見ているのか。根拠が出てこないので、自分の用途に当てはめようがない。\u003c/p\u003e\n\u003cp\u003eこのサイトでは、ここまで4本の記事で\u003cstrong\u003e全部自分で測ってきました。\u003c/strong\u003e その数字を積み上げて、必要なスペックを出します。\u003c/p\u003e\n\u003ch2 id=\"先に結論\"\u003e先に結論\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eやりたいこと\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eメモリ\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eディスク\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e根拠\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e静的サイト＋小さな業務アプリ\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e1〜2GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e20GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e実測（アプリ3本で166MB）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e＋ n8n で自動化\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e2GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e50GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e実測（+402MB、空き1.1GB残）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e＋ Dify（起動して置くだけ）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e100GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e実測（Dify単体で2,076MB）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eDify を実際に使う\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e8GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e100GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e推定・未検証\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e＋ ローカルLLM（0.5Bクラス）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e2GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e20GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e実測（本体2.1GB＋モデル）\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eローカルLLM（1B以上）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4GB〜\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e50GB〜\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e推定・未検証\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e「実測」と書いた行は測った数字です。「未検証」の行は測っていません。\u003cstrong\u003eどこまでが実測でどこからが推測か、はっきり分けて書きます。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"土台osと常駐デーモンで何mb持っていかれるか\"\u003e土台：OSと常駐デーモンで何MB持っていかれるか\u003c/h2\u003e\n\u003cp\u003eまずアプリを何も載せない状態のコストです。ここを知らないと積み上げができません。\u003c/p\u003e\n\u003cp\u003eこのサーバー（さくらのVPS 2Gプラン / Ubuntu 24.04）で、\u003cstrong\u003e再起動直後・Dockerとnginxと自作アプリ1本が動いている状態\u003c/strong\u003eが \u003cstrong\u003e398MB\u003c/strong\u003e でした。\u003c/p\u003e\n\u003cp\u003e内訳のうち、多くの人が見落とすものが2つあります。\u003c/p\u003e\n\u003ch3 id=\"1-vpsでは働きようがないデーモンが50100mb\"\u003e1. VPSでは働きようがないデーモンが50〜100MB\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"/sakura-vps-2gb-memory/\"\u003e最初の記事\u003c/a\u003eで測った内訳です。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eプロセス\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eRSS\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e本来の用途\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003efwupd\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e44.0MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e物理デバイスのファームウェア更新\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003emultipathd\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e26.7MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eストレージへの複数I/Oパスの管理\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eudisksd\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e13.4MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eディスク・リムーバブルメディアの管理\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eModemManager\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e12.8MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eモバイル通信モデムの管理\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eVPSに物理ファームウェアはありません。モバイル通信のモデムも刺さっていません。\u003cstrong\u003e常駐3つで約53MB、\u003ccode\u003efwupd\u003c/code\u003e が起動していると約97MB。\u003c/strong\u003e\u003c/p\u003e","title":"AI用途のVPSは何GB必要か｜n8nとDifyを実測して積み上げた"},{"content":"前回、n8nは2GBのVPSに 402MB で載りました（実測記事）。そのとき「次はDifyを入れてみます」と書きました。\nDifyの公式要件は 2CPU / 4GB。今回の環境は2GB、しかも本番の処理と公開中のサイトが同居しています。要件を満たしていません。 それを承知で載せて、10秒ごとに測りました。\n結論から書きます。載ります。ただし2,076MB要求してきます。\n上のオレンジ色が、物理メモリに収まらずスワップへ追い出された分です。881MB。 そして下のグラフ、起動から4分間はI/O待ちが最大91%。この間、SSHの接続が切れました。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS 同居しているもの：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本 Dify：1.17.0（公式リポジトリの docker/ をそのまま使用、ベクトルDBは既定のweaviate） 記録：10秒間隔・自作スクリプト。free / vmstat / ps と cgroup の memory.current を読むだけ 時間：10分間（起動から自動停止まで） 前回までに43時間のベースラインと、n8nを載せた前後の数字が取ってあります。「載せる前」が分かっているので、増えた分がそのままDifyのコストになります。\n先に：ディスクが10.6GB増える メモリの話の前に、こちらのほうが先に効きます。\nイメージ取得前 12,971MB イメージ取得後 23,572MB 差分 +10,601MB イメージだけで10.6GB。 n8nは2.47GBだったので、4.3倍です。\n内訳の上位はこうなっています。\nイメージ サイズ dify-api 4.06GB dify-plugin-daemon 2.28GB dify-agent-backend 1.45GB dify-web 892MB dify-sandbox 848MB dify-agent-local-sandbox 779MB postgres / squid / nginx / weaviate / redis ほか 計 1.25GB dify-api の1本だけで4GB。n8nのイメージ全体（2.47GB）より大きい。\nなお docker images に出る数字を単純に足すと約14GBになりますが、実際のディスク増加は10.6GBでした。レイヤーが共有されるぶん、足し算は3.4GB多く見積もります。\n立ち上がるのは16コンテナ n8nは1本でした。Difyは16本です。\napi api_websocket worker worker_beat web nginx db_postgres redis weaviate plugin_daemon sandbox local_sandbox agent_backend ssrf_proxy agent_ssrf_proxy init_permissions 起動する前に、この一覧を出しておくことを強く勧めます。\ndocker compose config --services 理由は次の項です。\n起動前に必ず：ホストのポートを奪われないか確認する Difyの標準構成は、コンテナの中に自前のnginxを持っていて、ホストの80番と443番を要求します。\ndocker compose config --format json | python3 -c \u0026#39; import sys,json d=json.load(sys.stdin) for name,svc in sorted(d[\u0026#34;services\u0026#34;].items()): for x in svc.get(\u0026#34;ports\u0026#34;) or []: print(\u0026#34; \u0026#34;, name, x.get(\u0026#34;host_ip\u0026#34;,\u0026#34;0.0.0.0\u0026#34;), x.get(\u0026#34;published\u0026#34;), \u0026#34;-\u0026gt;\u0026#34;, x.get(\u0026#34;target\u0026#34;)) \u0026#39; 結果はこうでした。\nnginx 0.0.0.0 80 -\u0026gt; 80 nginx 0.0.0.0 443 -\u0026gt; 443 plugin_daemon 0.0.0.0 5003 -\u0026gt; 5003 すでにWebサイトを配っているサーバーで、これをそのまま起動してはいけません。 80/443の奪い合いになります。加えて plugin_daemon の5003番が全世界に開きます。\n正しい閉じ方 私は最初、.env の EXPOSE_PLUGIN_DEBUGGING_PORT に 127.0.0.1:5003 と書く方法を取りました。Composeの \u0026quot;${EXPOSE_PLUGIN_DEBUGGING_PORT}:5003\u0026quot; という記述にバインドアドレスごと差し込む、という小技です。\nこれは失敗します。 後述します。\n正解は docker-compose.override.yaml を置くことです。\nservices: nginx: ports: !override - \u0026#34;127.0.0.1:8088:80\u0026#34; plugin_daemon: ports: !override - \u0026#34;127.0.0.1:5003:5003\u0026#34; !override タグが要点です。 Composeはオーバーライドファイルの ports: を既定では追記します。 ただ書き足すだけでは80番も443番も残ったままです。!override を付けて初めてリストが置き換わります。\n書いたら、起動する前に必ず検証してください。\ndocker compose config --format json | python3 -c \u0026#39; import sys,json d=json.load(sys.stdin) bad=[(k,x.get(\u0026#34;host_ip\u0026#34;,\u0026#34;0.0.0.0\u0026#34;),x.get(\u0026#34;published\u0026#34;)) for k,v in d[\u0026#34;services\u0026#34;].items() for x in (v.get(\u0026#34;ports\u0026#34;) or []) if x.get(\u0026#34;host_ip\u0026#34;) not in (\u0026#34;127.0.0.1\u0026#34;,\u0026#34;::1\u0026#34;)] print(\u0026#34;外部公開:\u0026#34;, bad or \u0026#34;なし\u0026#34;) \u0026#39; 「なし」を確認してから up してください。\n管理画面はSSHトンネル越しに開きます。\nssh -L 8088:127.0.0.1:8088 ユーザー名@サーバーのアドレス 本番と同居させるための2つの防御 このサーバーには止められない処理が載っています。Difyが暴走したときに、そちらが巻き添えになる構成では実験できません。 2段構えにしました。\n1. 本番プロセスをOOM Killerの対象から外す sudo mkdir -p /etc/systemd/system/\u0026lt;本番のサービス名\u0026gt;.service.d printf \u0026#39;[Service]\\nOOMScoreAdjust=-800\\n\u0026#39; \\ | sudo tee /etc/systemd/system/\u0026lt;本番のサービス名\u0026gt;.service.d/oom.conf sudo systemctl daemon-reload \u0026amp;\u0026amp; sudo systemctl restart \u0026lt;本番のサービス名\u0026gt; nginxにも同じものを入れました。-800 は「メモリが尽きても、これは最後まで殺すな」という重み付けです。\n2. Difyだけを1つの枠に閉じ込める コンテナごとに --memory を付ける方法もありますが、16本あります。まとめて1つの上限に入れるほうが確実です。\nsudo tee /etc/systemd/system/dify.slice \u0026gt; /dev/null \u0026lt;\u0026lt; \u0026#39;EOF\u0026#39; [Unit] Description=Dify experiment memory budget [Slice] MemoryMax=1200M MemorySwapMax=1024M EOF sudo systemctl daemon-reload \u0026amp;\u0026amp; sudo systemctl start dify.slice そのうえで、16本すべてをこの枠に入れます。オーバーライドファイルに cgroup_parent を並べるだけです。\nSVCS=$(docker compose config --services | sort) { echo \u0026#34;services:\u0026#34; for s in $SVCS; do printf \u0026#39; %s:\\n cgroup_parent: dify.slice\\n\u0026#39; \u0026#34;$s\u0026#34;; done } \u0026gt; docker-compose.override.yaml 先にサービス一覧を変数へ取っておくのが要点です。\u0026gt; docker-compose.override.yaml は実行前にファイルを作るので、for の中で docker compose config を呼ぶと書きかけの自分自身を読んで失敗します。 私はこれで一度つまずきました。\nなぜ1,200MBかというと、空きが約1,480MBだったからです。本番サイトが同居している2GBのVPSで、実験ツールに空きメモリを全部渡す人はいません。 全体の6割を与えて入るかどうか、が答えるべき問いだと考えました。\n結果：静止するまで4分、そのあとは安定する 経過 Difyのメモリ うちスワップ load CPUアイドル I/O待ち 起動直後 1,174MB 0 1.62 0% 0% 24秒 1,199MB 378MB 3.51 7% 45% 1分10秒 1,200MB 642MB 4.68 1% 91% 2分13秒 1,199MB 780MB 4.88 0% 91% 3分07秒 1,200MB 836MB 5.72 9% 77% 4分 977MB 627MB 4.66 2% 13% 4分20秒〜 1,195MB 881MB 0.2〜0.4 98% 0% 3つの局面がはっきり分かれました。\n局面1（〜30秒）：CPUで殴られる。 idle 0 / wa 0。16本の初期化そのものです。\n局面2（25秒〜4分）：I/O待ちに変わる。 スワップへの追い出しが始まった瞬間から wa が跳ね上がり、最大91%。ここでSSHが切れました。 ロードアベレージは5.72。\n局面3（4分〜）：静止する。 load 0.2〜0.4、idle 98%、wa 0%。以降6分間まったく動きません。\n4分の正体はデータベースのマイグレーションだった グラフの4分地点にある急落を、api のログと突き合わせました。\nRunning migrations Preparing database migration... Starting database migration. INFO [alembic.runtime.migration] Context impl PostgresqlImpl. Database migration successful! [INFO] Starting gunicorn 26.1.0 [INFO] Listening at: http://0.0.0.0:5001 Database migration successful! のタイムスタンプが、あの急落と秒単位で一致しました。\n10秒刻みの記録では、上位プロセスが flask（マイグレーション）から gunicorn（本体）へ入れ替わる瞬間がそのまま写っています。\n通常なら数秒で終わる処理に、約4分かかっていました。 スワップの中で動かしていたからです。\n定常状態のコスト 値 物理メモリ上 1,195MB スワップ上 881MB Dify合計 2,076MB システム全体の使用量 1,498MB 空き（available） 468MB 2GBのマシンで、Difyだけが2,076MB要求しています。\ndocker stats でコンテナ別に見ると、物理メモリ上にいるのは合計1,160.7MiBでした。\nコンテナ メモリ worker 326.1MiB api 296.9MiB api_websocket 207.5MiB web 162.8MiB worker_beat 38.0MiB sandbox 35.2MiB plugin_daemon 24.6MiB db_postgres 22.4MiB weaviate 16.2MiB その他6本 計 31.0MiB docker stats に出るのは物理メモリ上の分だけです。 スワップに落ちた881MBはここに出てきません。この表だけを見て「Difyは1.1GBか」と判断すると、実態の半分強しか見ていないことになります。\nなお、この状態で管理画面（/）にアクセスしたところ HTTPステータス307、応答2.84秒でした。応答はします。ただし何のワークフローも作っていない、完全にアイドルの状態でこの数字です。\n記事3の訂正1：メモリ上限はOOMからは守るが、スラッシングからは守らない 前回の記事で、私はこう書きました。\n--memory=768m が要点です。（中略）上限を課しておけば、あふれるのはコンテナの中だけで済みます。\n半分しか正しくありませんでした。\n今回、cgroupの記録はこうなっています。\nmemory.peak 1,200MB（上限ちょうど） memory.swap.peak 884MB max 69,079 ← 上限に当たって回収した回数 oom 0 oom_kill 0 oom_kill は0。1本も殺されていません。 そのかわり、上限に達するたびにカーネルがページを回収し、それが 69,079回。\nMemoryMax はプロセスを殺しません。強制的にメモリを回収します。 つまり枠の中で、ページを追い出しては読み直す動作を数万回繰り返す。殺されなかったから、固まったのです。\n上限はOOMからは守る — 実際、同居している本番の処理も公開中のサイトも、一度も止まりませんでした 上限はスラッシングからは守らない — 枠の中で窒息し、そのディスクI/Oでサーバー全体が巻き添えになります 「メモリ上限を付ければ同居は安全」という前回の書き方は、この一文を足して読んでください。\n記事3の訂正2：/var/lib/docker を見ても分からない 前回、「/var/lib/docker の中身だけで2.1GB」と書きました。測る場所として不適切でした。\n/var/lib/docker 5.9M /var/lib/containerd 13G Driver=overlayfs Docker 29系は overlay2 ではなく overlayfs ドライバを使い、イメージの実体をcontainerdの管理下に置きます。/var/lib/docker は5.9MBしかありません。\n正しくは docker system df を使ってください。\ndocker system df # TYPE TOTAL ACTIVE SIZE RECLAIMABLE # Images 1 1 2.473GB 0B (0%) Docker自身に申告させるほうが確実です。なお、df で見たディスク全体の増加（10GB→13GB）という前回の数字自体は正しく、訂正が要るのは内訳を見た場所のほうです。\n私の失敗：ポートを閉じようとして、自分でDifyを壊した 最初の起動では、16本のうち api だけが延々と再起動を繰り返しました。\napi restarting Restarting (1) 29 seconds ago このとき私は「メモリ不足だ」と考えかけました。 空きは足りていない。スワップは880MB使われている。一番重いコンテナが落ちている。状況は完全にそう見えます。\n確認したら、違いました。\ndocker inspect docker-api-1 \\ --format \u0026#34;ExitCode={{.State.ExitCode}} Restarts={{.RestartCount}} OOMKilled={{.State.OOMKilled}}\u0026#34; # ExitCode=1 Restarts=17 OOMKilled=false OOMKilled=false。 メモリで殺されたわけではない。ログを見ると原因が明記されていました。\npydantic_core.ValidationError: 1 validation error for DifyConfig PLUGIN_REMOTE_INSTALL_PORT Value error, PLUGIN_REMOTE_INSTALL_PORT must be a bare port number, got \u0026#39;127.0.0.1:5003\u0026#39;. ... bind loopback via a docker-compose.override.yaml instead of overloading this var. 前述の「小技」です。EXPOSE_PLUGIN_DEBUGGING_PORT にホストIPごと突っ込んだところ、Difyは同じ値を PLUGIN_REMOTE_INSTALL_PORT としても読んでおり、そちらはポート番号単体でなければならなかった。 設定検証で弾かれ、起動のたびに落ちていました。\nエラーメッセージが「docker-compose.override.yaml を使え」と明示的に指示しています。私はそれを読む前に近道を選んでいました。\n直したら、api は Running=true / Restarts=0 で安定しました。この記事の数字は、すべて直した後の測定です。\nここが今回いちばんの教訓です もし OOMKilled を確認せずに、見た目だけで「2GBではDifyのAPIが落ちる」と書いていたら、それは誤報でした。 同じことは16GBのサーバーでも起きたはずです。\n「メモリ不足に見える障害」の多くは、メモリ不足ではありません。 コンテナが落ちたら、まずこの1行を叩いてください。\ndocker inspect \u0026lt;コンテナ名\u0026gt; --format \u0026#34;{{.State.OOMKilled}} {{.State.ExitCode}}\u0026#34; 結論：2GBで動く。ただし勧めない 動いた 16コンテナすべて起動。api も含めて安定稼働 管理画面は応答する（307 / 2.84秒） 同居している本番の処理も、公開中のサイトも一度も止まらなかった 静止状態では load 0.2 / CPUアイドル 98% それでも勧めない 常時881MBをスワップに置いている。 メモリ上のワーキングセットではなく、ディスクの上です 空きは468MB。 ここから実際にワークフローを組み、モデルを呼び、データを取り込む余地はほとんどありません 起動に4分。 再起動のたびに4分間サーバーが重くなります その4分間はI/O待ち91%。 SSHが切れました。同居しているサービスがある環境で、これは許容しづらい ディスクを10.6GB持っていく 「起動して、アイドルで放置する」ところまでは2GBで届きます。使い始めたら足りません。\n必要そうな線 今回の実測から言えるのは、アイドルで約2.1GBということです。これはワークフロー0本、ナレッジ0件、アクセス0の数字です。\n公式が4GBを要求している理由は、実際に使ったときの余地を含めてのことでしょう。2GBは、スワップという名の借金でようやく起動できる水準でした。\nn8nだけなら2GBで足りる（前回の実測：402MB、空き1.1GB） Difyを実用するなら4GB以上を見たほうがよさそうです。ただし「4GBなら快適か」は測っていないので、これは推測です 次に測ること 推測のままにはしません。 次はメモリを増やした環境で同じ手順・同じ間隔で測り、「何GBから快適になるのか」を数字で出します。\n同じ10秒刻みのスクリプトを使うので、今回のデータとそのまま比較できます。\n「AI用途のVPSは何GB必要か」という問いに、推測ではなく実測で答えるところまで持っていきます。\n使った計測スクリプト 追加パッケージは不要です。free / vmstat / ps と cgroup のファイルを読むだけです。\n#!/usr/bin/env bash set -u OUT=\u0026#34;$HOME/dify-run.csv\u0026#34; N=\u0026#34;${1:-72}\u0026#34; S=\u0026#34;/sys/fs/cgroup/dify.slice\u0026#34; echo \u0026#34;ts,used_mb,avail_mb,swap_used_mb,slice_mb,slice_swap_mb,load1,cpu_idle,cpu_wa,p1,p1_rss,p2,p2_rss,p3,p3_rss\u0026#34; \u0026gt; \u0026#34;$OUT\u0026#34; for i in $(seq 1 \u0026#34;$N\u0026#34;); do ts=$(date \u0026#39;+%H:%M:%S\u0026#39;) mem=$(free -m | awk \u0026#39;/^Mem:/{print $3\u0026#34;,\u0026#34;$7}\u0026#39;) swp=$(free -m | awk \u0026#39;/^Swap:/{print $3}\u0026#39;) sm=$(awk \u0026#39;{printf \u0026#34;%.0f\u0026#34;,$1/1048576}\u0026#39; \u0026#34;$S/memory.current\u0026#34; 2\u0026gt;/dev/null); sm=${sm:-0} ss=$(awk \u0026#39;{printf \u0026#34;%.0f\u0026#34;,$1/1048576}\u0026#39; \u0026#34;$S/memory.swap.current\u0026#34; 2\u0026gt;/dev/null); ss=${ss:-0} ld=$(awk \u0026#39;{print $1}\u0026#39; /proc/loadavg) cpu=$(vmstat 1 2 | awk \u0026#39;NR==2{for(i=1;i\u0026lt;=NF;i++){if($i==\u0026#34;id\u0026#34;)ci=i; if($i==\u0026#34;wa\u0026#34;)cw=i}} END{print (ci?$ci:\u0026#34;\u0026#34;)\u0026#34;,\u0026#34;(cw?$cw:\u0026#34;\u0026#34;)}\u0026#39;) top=$(ps -eo comm=,rss= --sort=-rss | head -3 | tr -d \u0026#39;,\u0026#39; \\ | awk \u0026#39;{printf \u0026#34;%s,%.1f,\u0026#34;, $1, $2/1024}\u0026#39; | sed \u0026#39;s/,$//\u0026#39;) echo \u0026#34;$ts,$mem,$swp,$sm,$ss,$ld,$cpu,$top\u0026#34; \u0026gt;\u0026gt; \u0026#34;$OUT\u0026#34; sleep 8 done 前回のスクリプトに cpu_wa（I/O待ち）と cgroup の使用量を足したものです。\nwa 列は今回いちばん効きました。これがないと「CPUが忙しいのか、ディスク待ちで塞がっているのか」が区別できません。 前回の測定ではそこを取りこぼしていました。\nvmstat の列位置はカーネルやprocpsのバージョンで変わるので、ヘッダー行から id と wa の位置を探してから読んでいます。 列番号を決め打ちしないでください。\n実験を安全に終わらせる仕掛け 固まる可能性がある実験なので、8分後に自分で止まるようにしてから起動しました。\nsudo nohup bash -c \u0026#39; sleep 480 cd /path/to/dify/docker docker compose ps -a \u0026gt; /home/ubuntu/dify-final.txt 2\u0026gt;\u0026amp;1 docker stats --no-stream \u0026gt;\u0026gt; /home/ubuntu/dify-final.txt 2\u0026gt;\u0026amp;1 docker compose down \u0026gt;\u0026gt; /home/ubuntu/dify-final.txt 2\u0026gt;\u0026amp;1 \u0026#39; \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 \u0026amp; sudo nohup ... \u0026amp; で端末から切り離してあるので、SSHが切れても実行されます。 実際、測定中に接続は切れました。それでも自動停止は動き、記録も残りました。\n手で止めに行く前提の実験にしないこと。 これが今回いちばん役に立った準備でした。\n","permalink":"https://jimae-ai.com/dify-2gb-vps-memory/","summary":"\u003cp\u003e前回、n8nは2GBのVPSに \u003cstrong\u003e402MB\u003c/strong\u003e で載りました（\u003ca href=\"/n8n-2gb-vps-memory/\"\u003e実測記事\u003c/a\u003e）。そのとき「次はDifyを入れてみます」と書きました。\u003c/p\u003e\n\u003cp\u003eDifyの公式要件は \u003cstrong\u003e2CPU / 4GB\u003c/strong\u003e。今回の環境は2GB、しかも本番の処理と公開中のサイトが同居しています。\u003cstrong\u003e要件を満たしていません。\u003c/strong\u003e それを承知で載せて、10秒ごとに測りました。\u003c/p\u003e\n\u003cp\u003e結論から書きます。\u003cstrong\u003e載ります。ただし2,076MB要求してきます。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Difyを2GBのVPSに載せた10分間\" loading=\"lazy\" src=\"/img/dify-10min.png\"\u003e\u003c/p\u003e\n\u003cp\u003e上のオレンジ色が、物理メモリに収まらずスワップへ追い出された分です。\u003cstrong\u003e881MB。\u003c/strong\u003e そして下のグラフ、起動から4分間はI/O待ちが最大91%。\u003cstrong\u003eこの間、SSHの接続が切れました。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e同居しているもの\u003c/strong\u003e：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDify\u003c/strong\u003e：1.17.0（公式リポジトリの \u003ccode\u003edocker/\u003c/code\u003e をそのまま使用、ベクトルDBは既定のweaviate）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e記録\u003c/strong\u003e：10秒間隔・自作スクリプト。\u003ccode\u003efree\u003c/code\u003e / \u003ccode\u003evmstat\u003c/code\u003e / \u003ccode\u003eps\u003c/code\u003e と cgroup の \u003ccode\u003ememory.current\u003c/code\u003e を読むだけ\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e時間\u003c/strong\u003e：10分間（起動から自動停止まで）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e前回までに\u003ca href=\"/vps-43h-monitoring/\"\u003e43時間のベースライン\u003c/a\u003eと、n8nを載せた前後の数字が取ってあります。\u003cstrong\u003e「載せる前」が分かっているので、増えた分がそのままDifyのコストになります。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"先にディスクが106gb増える\"\u003e先に：ディスクが10.6GB増える\u003c/h2\u003e\n\u003cp\u003eメモリの話の前に、こちらのほうが先に効きます。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eイメージ取得前  12,971MB\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eイメージ取得後  23,572MB\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        差分   +10,601MB\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eイメージだけで10.6GB。\u003c/strong\u003e n8nは2.47GBだったので、\u003cstrong\u003e4.3倍\u003c/strong\u003eです。\u003c/p\u003e\n\u003cp\u003e内訳の上位はこうなっています。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eイメージ\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eサイズ\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-api\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e4.06GB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-plugin-daemon\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e2.28GB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-agent-backend\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1.45GB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-web\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e892MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-sandbox\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e848MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003edify-agent-local-sandbox\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e779MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003epostgres / squid / nginx / weaviate / redis ほか\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e計 1.25GB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003ccode\u003edify-api\u003c/code\u003e の1本だけで4GB。\u003cstrong\u003en8nのイメージ全体（2.47GB）より大きい。\u003c/strong\u003e\u003c/p\u003e","title":"2GBのVPSにDifyは載るのか｜16コンテナを実測したら2,076MB要求してきた"},{"content":"「2GBのVPSでn8nは動くのか」を調べると、たいてい「動く」か「厳しい」のどちらかしか書いてありません。具体的に何MB増えるのかは、ほとんど出てきません。\n実際に載せて、1分刻みで測りました。\n合計402MB。 そして載せ終わってもまだ1.1GB空いています。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS 元から動いていたもの：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本 記録：1分ごとにcronで自動記録（スクリプトは前の記事に載せています） 時間：2026-09-07 01:12 〜 01:37 前の記事で43時間分のベースラインを取ってあります。「載せる前」が分かっているので、増えた分がそのままn8nのコストになります。\n結果：4段階に分けて測る 多くの記事は「n8nは○MB」で終わります。しかし実際に増えるものは1つではありません。\n段階 システム全体のメモリ 増分 元の状態 438MB — ＋Dockerデーモン 476MB +38MB ＋n8nコンテナ起動 804MB +328MB ＋UIを開いてワークフローを1本 840MB +36MB 合計 +402MB ディスクは 10GB → 13GB（+3GB）。スワップは 0 → 37MB 使われました。\n発見1：Dockerデーモンだけなら38MB 「Dockerは重い」とよく言われます。実際に測ると、デーモン単体では38MBでした。\n導入直後の記録がこれです。\n01:14 431MB python 90.8, systemd-journal 72.7, multipathd 26.7 ← 導入前 01:15 523MB apt-get 98.3, python 90.8, dockerd 87.6 ← インストール中 01:16 483MB python 90.8, dockerd 88.3, systemd-journal 72.9 ← 完了 01:19 478MB python 90.8, dockerd 87.0, systemd-journal 73.0 ← 安定 インストール中は apt-get で523MBまで上がりますが、終われば478〜485MBに落ち着きます。\n重いのはDockerではなく、コンテナの中身です。 ここを分けずに「Dockerを入れるとメモリを食う」と言うのは、少し雑だと思いました。\nプロセスのRSSを足しても、実際の増加分にはならない 面白いズレがありました。dockerd のRSSは87MBですが、システム全体の増加は38MBです。\nRSSは共有ライブラリを重複して数えるため、プロセスごとの数字を足し上げても実際の消費量にはなりません。信用すべきは free の used のほうです。\nps の数字だけを見て「87MB食っている」と書くと、倍以上ずれます。\n発見2：n8nの正体はNode.jsプロセス2本 n8nを起動した直後の上位プロセスがこれです。\nnode-MainThread 305.6MB node-MainThread 117.5MB dockerd 78.1MB docker stats ではコンテナ全体で 395.9MiB でした。\nn8nというアプリケーションが重いのではなく、Node.jsのランタイムが2本立ち上がっているという構図です。片方がメインプロセス、もう片方がワーカーだと考えられます。\n参考までに、このサーバーで元から動いている自作のPythonアプリは90MBです。同じ「1つのアプリ」でも、ランタイムが違うと3〜4倍変わります。\n発見3：UIを開くだけで36MB増える ここが今回いちばん意外でした。\nブラウザでn8nの管理画面を開き、ワークフローを1本組んだ結果です。\nコンテナのメモリ 起動直後（UI未接続） 395.9MiB UIを開いて操作した後 434.4MiB +38.5MiB。しかも、操作をやめても戻りませんでした。\nシステム全体でも 804MB → 840MB に増えています。\nつまり 「n8nは○MB」という数字は、測ったタイミングで変わります。 起動直後の数字だけを見て容量を見積もると、実際の運用では足りなくなる可能性があります。\n発見4：ディスクが3GB増えた メモリばかり見ていましたが、先に効いてきそうなのはディスクでした。\n使用量 n8n導入前 10GB n8n導入後 13GB /var/lib/docker の中身だけで 2.1GB。n8nのイメージ本体です。\n【2026-09-07 追記・訂正】 ここは測る場所を間違えていました。Docker 29系はイメージの実体を /var/lib/containerd に置くため、/var/lib/docker を見ても分かりません（実測したところ5.9MBしかありませんでした）。正しくは docker system df を使ってください。それで見ると、このイメージは 2.47GB でした。なお df で見たディスク全体の増加（10GB→13GB）という上の数字自体は正しく、訂正が要るのは内訳を見た場所のほうです。詳細はDifyの実測記事に書きました。\n100GBのディスクなので今は問題ありませんが、この調子でDify、Ollama、その他を試したら、メモリより先にディスクが苦しくなります。 ローカルLLMのモデルファイルは1つ数GBです。\n測る前は、この順番を逆に考えていました。\nメモリ上限を必ず付ける 今回はこう起動しました。\nsudo docker run -d --name n8n \\ --restart unless-stopped \\ --memory=768m \\ -p 127.0.0.1:5678:5678 \\ -v n8n_data:/home/node/.n8n \\ -e GENERIC_TIMEZONE=\u0026#34;Asia/Tokyo\u0026#34; \\ -e TZ=\u0026#34;Asia/Tokyo\u0026#34; \\ docker.n8n.io/n8nio/n8n --memory=768m が要点です。\nこのサーバーには、本番で動いている処理と公開中のサイトが同居しています。n8nが暴走してメモリを食い尽くすと、OOM Killerがどのプロセスを殺すか選べません。 上限を課しておけば、あふれるのはコンテナの中だけで済みます。\n結果は 434.4MiB / 768MiB（56.6%）。余裕を持って収まりました。上限としては妥当な線だったと思います。\n【2026-09-07 追記】 この書き方は半分しか正しくありませんでした。メモリ上限は OOM Killerからは守りますが、スラッシング（枠の中でページを出し入れし続ける状態）からは守りません。 次の記事でDifyに1,200MBの枠を与えたところ、oom_kill は0件のまま、上限に当たって回収した回数が 69,079回 に達し、そのディスクI/Oでサーバー全体が重くなりました。同居している本番の処理は守られましたが、サーバー自体は一時的に操作不能になっています。実測はこちら。\n-p 127.0.0.1:5678:5678 も必須です n8nは初期状態で誰でもアクセスできます。 -p 5678:5678 と書くと全世界に公開されてしまう。\n127.0.0.1 を頭に付けると、サーバー内部からしか繋がらなくなります。管理画面はSSHトンネル経由で開きます。\nssh -L 5678:127.0.0.1:5678 ユーザー名@サーバーのアドレス そのうえでブラウザから http://localhost:5678 を開く。外に開けずに使えます。\n自動化ツールは認証情報の塊です。APIキーもパスワードも入ります。まずポートを閉じてから起動してください。\n結論：2GBに載る。ただし条件がある 載る 合計402MB増えて、まだ1.1GB空いている 元から動いていた処理も、公開中のサイトも止まらなかった CPUは終始ほぼアイドル（ロードアベレージ0.08前後） 気をつけること 上限を課さないなら載せないほうがいい。同居しているものが道連れになります ディスクが3GB減る。ツールを増やすならここが先に効きます UIを開くと増えて、戻らない。起動直後の数字で見積もらないこと スワップは用意しておく。今回37MB使われました 載らないケース PostgreSQLを別途立てる構成（n8nは本番運用でPostgreSQL推奨。SQLiteのままなら今回の数字ですが、DBを足すとさらに100〜300MB） ワーカーを分離するスケール構成 同じサーバーでDifyやローカルLLMも動かす 次に測ること n8nは載りました。残り1.1GB。\n次はここにDifyを入れてみます。同じ手順で、同じ間隔で測ります。入るのか、入らないのか。入らないならどこで止まるのか。\n「AI用途のVPSは何GB必要か」という問いに、推測ではなく実測で答えられるところまで持っていくつもりです。\n→ 測りました：2GBのVPSにDifyは載るのか｜16コンテナを実測したら2,076MB要求してきた\n","permalink":"https://jimae-ai.com/n8n-2gb-vps-memory/","summary":"\u003cp\u003e「2GBのVPSでn8nは動くのか」を調べると、たいてい「動く」か「厳しい」のどちらかしか書いてありません。\u003cstrong\u003e具体的に何MB増えるのかは、ほとんど出てきません。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e実際に載せて、1分刻みで測りました。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"n8nを載せると何が何MB増えるか\" loading=\"lazy\" src=\"/img/n8n-cost.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e合計402MB。\u003c/strong\u003e そして載せ終わってもまだ\u003cstrong\u003e1.1GB空いています。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e元から動いていたもの\u003c/strong\u003e：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e記録\u003c/strong\u003e：1分ごとにcronで自動記録（スクリプトは\u003ca href=\"/vps-43h-monitoring/\"\u003e前の記事\u003c/a\u003eに載せています）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e時間\u003c/strong\u003e：2026-09-07 01:12 〜 01:37\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e前の記事で43時間分のベースラインを取ってあります。\u003cstrong\u003e「載せる前」が分かっているので、増えた分がそのままn8nのコストになります。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"結果4段階に分けて測る\"\u003e結果：4段階に分けて測る\u003c/h2\u003e\n\u003cp\u003e多くの記事は「n8nは○MB」で終わります。しかし実際に増えるものは1つではありません。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e段階\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eシステム全体のメモリ\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e増分\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e元の状態\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e438MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e—\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e＋Dockerデーモン\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e476MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e+38MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e＋n8nコンテナ起動\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e804MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e+328MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e＋UIを開いてワークフローを1本\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e840MB\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e+36MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e合計 +402MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eディスクは \u003cstrong\u003e10GB → 13GB（+3GB）\u003c/strong\u003e。スワップは \u003cstrong\u003e0 → 37MB\u003c/strong\u003e 使われました。\u003c/p\u003e\n\u003ch2 id=\"発見1dockerデーモンだけなら38mb\"\u003e発見1：Dockerデーモンだけなら38MB\u003c/h2\u003e\n\u003cp\u003e「Dockerは重い」とよく言われます。実際に測ると、\u003cstrong\u003eデーモン単体では38MB\u003c/strong\u003eでした。\u003c/p\u003e\n\u003cp\u003e導入直後の記録がこれです。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e01:14  431MB  python 90.8, systemd-journal 72.7, multipathd 26.7   ← 導入前\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e01:15  523MB  apt-get 98.3, python 90.8, dockerd 87.6              ← インストール中\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e01:16  483MB  python 90.8, dockerd 88.3, systemd-journal 72.9      ← 完了\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e01:19  478MB  python 90.8, dockerd 87.0, systemd-journal 73.0      ← 安定\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eインストール中は \u003ccode\u003eapt-get\u003c/code\u003e で523MBまで上がりますが、終われば478〜485MBに落ち着きます。\u003c/p\u003e","title":"2GBのVPSにn8nは載るのか｜Dockerとn8nを分けて実測したら402MBだった"},{"content":"前回の記事で、VPSのメモリを1回だけ測りました。ただしあれはアイドルに近い状態の1サンプルです。ピークは写っていません。\nそこで、1分ごとに記録するスクリプトを仕掛けて放置しました。43時間、2,590サンプル、欠測ゼロ。\n結果、予想は外れました。メモリのピークを作っていたのは、自分のアプリではありませんでした。\n上がメモリ、下がCPUです。山が重なっていません。 これが今回いちばん面白かったところです。\n測定条件 サーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS 期間：2026-09-04 01:10 〜 09-05 20:19（43.1時間） 間隔：1分（cron） サンプル数：2,590（120秒を超える欠測ゼロ） 載せているもの：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本 使ったスクリプト 追加パッケージは不要です。free / vmstat / ps / awk だけで動きます。\n#!/usr/bin/env bash set -u OUT=\u0026#34;${1:-$HOME/vps-metrics.csv}\u0026#34; if [ ! -f \u0026#34;$OUT\u0026#34; ]; then echo \u0026#34;timestamp,mem_total_mb,mem_used_mb,mem_available_mb,swap_used_mb,load1,load5,cpu_idle_pct,p1_name,p1_rss_mb,p2_name,p2_rss_mb,p3_name,p3_rss_mb\u0026#34; \u0026gt; \u0026#34;$OUT\u0026#34; fi ts=$(date \u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;) mem=$(free -m | awk \u0026#39;/^Mem:/{print $2\u0026#34;,\u0026#34;$3\u0026#34;,\u0026#34;$7}\u0026#39;) swp=$(free -m | awk \u0026#39;/^Swap:/{print $3}\u0026#39;) ld=$(awk \u0026#39;{print $1\u0026#34;,\u0026#34;$2}\u0026#39; /proc/loadavg) idle=$(vmstat 1 2 | awk \u0026#39;NR==2{for(i=1;i\u0026lt;=NF;i++) if($i==\u0026#34;id\u0026#34;) c=i} END{print (c?$c:\u0026#34;\u0026#34;)}\u0026#39;) top=$(ps -eo comm=,rss= --sort=-rss | head -3 | tr -d \u0026#39;,\u0026#39; \\ | awk \u0026#39;{printf \u0026#34;%s,%.1f,\u0026#34;, $1, $2/1024}\u0026#39; | sed \u0026#39;s/,$//\u0026#39;) echo \u0026#34;$ts,$mem,$swp,$ld,$idle,$top\u0026#34; \u0026gt;\u0026gt; \u0026#34;$OUT\u0026#34; cronに1行足すだけです。\n* * * * * /home/ubuntu/vps-sampler.sh \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 vmstat のCPUアイドル列は、カーネルやprocpsのバージョンで位置が変わります。列番号を決め打ちせず、ヘッダー行から id の位置を探してから読んでいるのはそのためです。\n平常時のベースライン まず、何も起きていないときの数字です。OSのメンテナンスが動いた時間帯を除いて集計しました。\n指標 中央値 p95 最大 メモリ使用量 415MB 443MB 466MB ロードアベレージ(1分) 0.02 0.15 1.21 CPUアイドル率 100% 86%(p5) 57%(最小) 2GBのうち21%しか使っていません。 メモリの空き（available）は最小でも1,324MB、43時間を通して1.3GBを下回りませんでした。\n発見1：メモリのピークは、全部OSのメンテナンスだった メモリ使用量の上位10件を並べると、上位6件がすべて unattended-upgrades（Ubuntuの自動更新）でした。7位から10位は fwupd。自作のアプリは1件も入っていません。\n全2,590分のうち、メモリ使用量1位のプロセスの内訳はこうなります。\nプロセス 1位だった回数 割合 python（アプリ本体） 2,155 83.2% systemd-journald 417 16.1% unattended-upgrades 12 0.5% fwupd 6 0.2% 時間の99%はアプリが1位です。 ところがピークを作るのは、残り0.7%の時間に動くOSのメンテナンスでした。\n平均を見ていたら絶対に気づきません。1分刻みで記録して、最大値を見にいったから見えた話です。\n発見2：自動更新が、アプリを再起動していた 9月4日 06:19〜06:28 の10分間を1分刻みで並べます。\n時刻 メモリ使用量 1位のプロセス RSS CPUアイドル 06:18 400MB python 72.0MB 100% 06:19 457MB unattended-upgr 113.2MB 67% 06:20 459MB unattended-upgr 113.2MB 67% 06:21 455MB unattended-upgr 118.6MB 91% 06:22 641MB unattended-upgr ×2 208.4 + 143.3MB 67% 06:23 587MB unattended-upgr 208.8MB 65% 06:24 625MB unattended-upgr 209.2MB 66% 06:25 586MB unattended-upgr 209.4MB 64% 06:26 622MB unattended-upgr 209.6MB 66% 06:27 594MB unattended-upgr 264.1MB 69% 06:28 561MB unattended-upgr 209.7MB 63% 06:29 444MB python 43.3MB 100% 最後の2行を見てください。\n06:27に自動更新が264MBまで膨らみ、06:29には python のRSSが 72.0MB → 43.3MB に落ちています。\nアプリが再起動されました。 依存パッケージが更新され、サービスが再起動されたのだと考えられます。\nそして再起動後、python のRSSは43.3MBのまま。平常時の72MBに戻るまで数時間かかっています。 つまりあの72MBは、起動直後の値ではなく、動いているうちに積み上がった状態だったわけです。\n自動更新は便利ですが、勝手にアプリを止めて起動し直します。 それが朝の6時22分に起きていて、私はまったく知りませんでした。1分刻みで記録していなければ、永久に気づかなかったはずです。\nこのとき mem_available は最小1,324MB。余裕があったので何も壊れませんでしたが、メモリが逼迫している環境で同じことが起きたら、OOM Killerが走ってもおかしくありません。\n発見3：fwupd は 188MB まで跳ねる 前回の記事で、fwupd（物理デバイスのファームウェア更新デーモン）について私はこう書きました。\nfwupd は測定の2分前に起動していました。常時この44MBを消費し続けているとは限りません。\n慎重に書いておいて正解でしたが、実態は想定より大きかったです。\n9月5日 01:07〜01:12 の6分間、fwupd は 188.8MB を占め、システム全体のメモリ使用量が578MBまで上がりました。\nアプリ本体の最大値（87.9MB）の、2倍以上です。\n43時間で fwupd が1位になったのは6分だけ。しかしその6分は、メモリ使用量の上位10件のうち4件を占めています。\nVPSに物理ファームウェアはありません。更新するものが1つもないデーモンが、アプリの2倍のメモリを瞬間的に取っていく。前回「働きようがない」と書きましたが、働かないだけでなく、たまに大きく場所を取るというのが正確なところでした。\n発見4：バッチ処理はCPUを使うが、メモリは使わない グラフの下段を見てください。9月5日の 10:40〜11:30 に、約40分続くCPUの山があります。\nCPU使用率：15分移動平均で約35%（平常時は約2%） ロードアベレージ：1.0〜1.2（平常時は0.02） CPUアイドル率：最小 57% はっきりした負荷です。ところが同じ時間帯のメモリは425〜442MB。平常時の中央値415MBとほとんど変わりません。python のRSSも85MB前後で動きません。\n私は「バッチ処理が走ればメモリが跳ねる」と予想していました。外れました。 跳ねたのはCPUだけです。\n考えてみれば当然で、データを1件ずつ読んで処理して書き出すタイプの処理は、全部をメモリに載せません。メモリを食うのは、大きなデータをまるごと展開する処理のほうです。\n「重い処理＝メモリが要る」は、いつも成り立つわけではない。 ここは測らないと分かりませんでした。\nグラフで上下の山が重なっていないのは、そういう意味です。\n発見5：計測そのものがメモリを食っていた systemd-journald（ログ管理）のRSSの推移です。\n時点 RSS 9/4 12:00 26.6MB 9/4 18:00 41.6MB 9/5 00:00 57.0MB 9/5 06:00 70.0MB 9/5 12:00 94.8MB → 27.3MB 26MBから94MBまで肥大し、ログのローテーションで一気に戻りました。\n原因は明らかで、1分ごとに走るcronが、毎回ログを吐いているからです。全2,590分のうち417分（16%）で、journaldがメモリ使用量1位になっていました。\nつまり測るという行為が、測る対象を変えている。\n1分間隔はやりすぎでした。5分間隔なら記録の密度はほとんど落ちず、journaldへの負荷は5分の1になります。これから同じことをやる人には、5分間隔を勧めます。\n発見6：スワップは無駄にならなかった このサーバーは、計測を始める前にスワップを2GB追加しました。さくらのVPSはスワップなしのイメージが提供される場合があるためです（前回の記事に書きました）。\n43時間のスワップ使用量の推移です。\n0MB → 1MB → 11MB → 40MB → 46MB → 30MB 最大46MB、実際に使われました。\nメモリには1.3GB以上の余裕があります。それでもスワップが使われるのは、長時間触られていないページがディスクに退避されるからです。逼迫していなくても、Linuxは静かに整理をしています。\nvm.swappiness=10（メモリが逼迫するまでスワップを控える設定）にしてあってこの量です。作らずにいたら、641MBのピーク時に緩衝材がまったくない状態でした。\nまとめ 43時間・2,590サンプルから言えることです。\n平常時はメモリ415MB（2GBの21%）、CPUアイドル100%、ロード0.02。43時間無停止、欠測ゼロ メモリのピークを作るのは、自分のアプリではなくOSのメンテナンス。上位10件のうち自作アプリはゼロ 自動更新はアプリを勝手に再起動する。それが1分刻みの記録に残っていた fwupd は平常時44MB、ピーク188MB。アプリ本体の2倍以上 バッチ処理はCPUを使うがメモリは使わない。「重い処理＝メモリが要る」は常に成り立つわけではない 1分間隔の計測はjournaldを肥大させる。5分間隔で十分 スワップは余裕があっても使われる。最大46MB そして、いちばん大事なこと 1回のスナップショットでは、この6つのどれも見えませんでした。\n前回の記事は「ある瞬間のメモリは504MB」で終わっています。それは正しいけれど、朝6時に641MBまで上がっていることも、そのときアプリが再起動されていることも、写っていません。\nサーバーの状態は、点ではなく線で見るものでした。仕掛けるのに5分、あとは放っておくだけです。\n次は、この環境にAIの自動化ツールを載せて、同じ方法で測ります。ベースラインが43時間分あるので、載せた後の差分がそのまま「そのツールのコスト」になります。\n","permalink":"https://jimae-ai.com/vps-43h-monitoring/","summary":"\u003cp\u003e前回の記事で、VPSのメモリを1回だけ測りました。ただしあれは\u003cstrong\u003eアイドルに近い状態の1サンプル\u003c/strong\u003eです。ピークは写っていません。\u003c/p\u003e\n\u003cp\u003eそこで、1分ごとに記録するスクリプトを仕掛けて放置しました。\u003cstrong\u003e43時間、2,590サンプル、欠測ゼロ。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e結果、予想は外れました。\u003cstrong\u003eメモリのピークを作っていたのは、自分のアプリではありませんでした。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"43時間のメモリとCPUの推移\" loading=\"lazy\" src=\"/img/vps-43h.png\"\u003e\u003c/p\u003e\n\u003cp\u003e上がメモリ、下がCPUです。\u003cstrong\u003e山が重なっていません。\u003c/strong\u003e これが今回いちばん面白かったところです。\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e期間\u003c/strong\u003e：2026-09-04 01:10 〜 09-05 20:19（43.1時間）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e間隔\u003c/strong\u003e：1分（cron）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eサンプル数\u003c/strong\u003e：2,590（120秒を超える欠測ゼロ）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e載せているもの\u003c/strong\u003e：定期的にデータを取得して予測を回すバッチ処理と、静的サイト1本\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"使ったスクリプト\"\u003e使ったスクリプト\u003c/h3\u003e\n\u003cp\u003e追加パッケージは不要です。\u003ccode\u003efree\u003c/code\u003e / \u003ccode\u003evmstat\u003c/code\u003e / \u003ccode\u003eps\u003c/code\u003e / \u003ccode\u003eawk\u003c/code\u003e だけで動きます。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cp\"\u003e#!/usr/bin/env bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eset\u003c/span\u003e -u\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003eOUT\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nv\"\u003e1\u003c/span\u003e\u003cspan class=\"k\"\u003e:-\u003c/span\u003e\u003cspan class=\"nv\"\u003e$HOME\u003c/span\u003e\u003cspan class=\"p\"\u003e/vps-metrics.csv\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"o\"\u003e[\u003c/span\u003e ! -f \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$OUT\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e]\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"k\"\u003ethen\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nb\"\u003eecho\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;timestamp,mem_total_mb,mem_used_mb,mem_available_mb,swap_used_mb,load1,load5,cpu_idle_pct,p1_name,p1_rss_mb,p2_name,p2_rss_mb,p3_name,p3_rss_mb\u0026#34;\u003c/span\u003e \u0026gt; \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$OUT\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003efi\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003ets\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003edate \u003cspan class=\"s1\"\u003e\u0026#39;+%Y-%m-%d %H:%M:%S\u0026#39;\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003emem\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003efree -m \u003cspan class=\"p\"\u003e|\u003c/span\u003e awk \u003cspan class=\"s1\"\u003e\u0026#39;/^Mem:/{print $2\u0026#34;,\u0026#34;$3\u0026#34;,\u0026#34;$7}\u0026#39;\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003eswp\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003efree -m \u003cspan class=\"p\"\u003e|\u003c/span\u003e awk \u003cspan class=\"s1\"\u003e\u0026#39;/^Swap:/{print $3}\u0026#39;\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003eld\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003eawk \u003cspan class=\"s1\"\u003e\u0026#39;{print $1\u0026#34;,\u0026#34;$2}\u0026#39;\u003c/span\u003e /proc/loadavg\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003eidle\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003evmstat \u003cspan class=\"m\"\u003e1\u003c/span\u003e \u003cspan class=\"m\"\u003e2\u003c/span\u003e \u003cspan class=\"p\"\u003e|\u003c/span\u003e awk \u003cspan class=\"s1\"\u003e\u0026#39;NR==2{for(i=1;i\u0026lt;=NF;i++) if($i==\u0026#34;id\u0026#34;) c=i} END{print (c?$c:\u0026#34;\u0026#34;)}\u0026#39;\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nv\"\u003etop\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"k\"\u003e$(\u003c/span\u003eps -eo \u003cspan class=\"nv\"\u003ecomm\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e,rss\u003cspan class=\"o\"\u003e=\u003c/span\u003e --sort\u003cspan class=\"o\"\u003e=\u003c/span\u003e-rss \u003cspan class=\"p\"\u003e|\u003c/span\u003e head -3 \u003cspan class=\"p\"\u003e|\u003c/span\u003e tr -d \u003cspan class=\"s1\"\u003e\u0026#39;,\u0026#39;\u003c/span\u003e \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e|\u003c/span\u003e awk \u003cspan class=\"s1\"\u003e\u0026#39;{printf \u0026#34;%s,%.1f,\u0026#34;, $1, $2/1024}\u0026#39;\u003c/span\u003e \u003cspan class=\"p\"\u003e|\u003c/span\u003e sed \u003cspan class=\"s1\"\u003e\u0026#39;s/,$//\u0026#39;\u003c/span\u003e\u003cspan class=\"k\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eecho\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$ts\u003c/span\u003e\u003cspan class=\"s2\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$mem\u003c/span\u003e\u003cspan class=\"s2\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$swp\u003c/span\u003e\u003cspan class=\"s2\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$ld\u003c/span\u003e\u003cspan class=\"s2\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$idle\u003c/span\u003e\u003cspan class=\"s2\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$top\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"nv\"\u003e$OUT\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ecronに1行足すだけです。\u003c/p\u003e","title":"43時間、1分ごとにVPSを測り続けた｜メモリを一番食っていたのは自分のアプリではなかった"},{"content":"さくらのVPS 2Gプランで、自作の業務システムを3本動かしています。9日間連続稼働、ロードアベレージ0.20、メモリは7割が空いたままです。\n測ってみて、想定外だったことがあります。アプリ3本が使っているのは約166MB。一方で、このサーバーでは働きようがないOSのデーモンが、合計50〜100MBを占めていました。\n自分のアプリより、使う予定のない仕組みのほうが目立つ。プラン変更を考える前に、見るべき場所がありました。\n測定条件 数字を出す記事なので、どういう状態で測ったかを先に書きます。\nサーバー：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS 測定時刻：平日15:57、業務時間内だがアクセスはほぼない状態 稼働日数：9日15時間（無停止） サンプル数：1回（vmstat のみ5秒間） したがって以下の数字はアイドルに近い状態のものです。ピーク時の値ではありません。負荷時の測定は別途行い、追記します。\n動かしている3本 すべて自作の業務システムです。フロントには Caddy を置いています。\nシステム 構成 常駐メモリ(RSS) 反応計測システム FastAPI 0.141.1 / uvicorn 0.52.4 / SQLite 約66MB 基幹システム Python + gunicorn（-w 1 --threads 8 -t 120） 約65MB 仮想待合室 Go（静的リンクの単一バイナリ）/ 設定はJSON 約35MB 3本合計 約166MB Caddy リバースプロキシ / HTTPS 約23MB 3本とも 127.0.0.1 のポートで待ち受けていて、外部に直接は晒していません。Caddyが受けて振り分けています。\n基幹システムは自社の業務用なので、フレームワークやデータ構造の詳細は伏せます。この記事で必要なのはメモリの数字だけなので、そこは支障ありません。\n3本で166MBに収まっている理由 DBサーバーを1台も動かしていないからです。\nsystemctl list-units --type=service --state=running \\ | grep -iE \u0026#34;postgres|mysql|maria|redis|mongo\u0026#34; # → 何も返らない PostgreSQLもMySQLもRedisも入っていません。反応計測システムはSQLiteのファイル1つ（data/dareyomi.db）で動いています。\nMySQLやPostgreSQLを1つ立てるだけで、デフォルト設定なら100〜300MBは持っていかれます。 アプリ3本の合計より重い。「2GBで足りるか」は、アプリの本数ではなくDBサーバーを立てるかどうかで決まる面が大きい、というのが実測から見えたことです。\nもうひとつ効いているのが、gunicornの -w 1 --threads 8 です。ワーカーを増やすとプロセスがまるごと複製されてメモリを食うので、限られたメモリではスレッドで捌く構成が有利になります。\n仮想待合室のGoバイナリが34.7MBでマルチテナントを捌いているのも、数字としては効いています。ランタイムを持たない単一バイナリなので、Pythonの2本と比べて素直に軽い。\nメモリ実測 total used free shared buff/cache available Mem: 1.9Gi 504Mi 362Mi 1.0Mi 1.3Gi 1.4Gi Swap: 0B 0B 0B 15:57:45 up 9 days, 15:58, 1 user, load average: 0.20, 0.34, 0.17 項目 値 意味 total 1.9Gi 2GBプランで実際に使える量 used 504Mi 使用中。全体の約1/4 available 1.4Gi これから使える量。見るべきはここ buff/cache 1.3Gi ディスクキャッシュ。必要になれば解放される free でつまずきやすいところ buff/cache の1.3GiBは「奪われている」わけではありません。Linuxは空きメモリをディスクキャッシュに回し、アプリが必要とすれば解放します。無駄ではなく、働いている状態です。\n見るべきは available。これが「これから何かを載せられる余地」で、今回は1.4GiB。全体の約7割が空いています。\nfree の数字が小さいことを理由に上位プランへ変える前に、まず available を見てください。\nプロセス別の内訳 ps aux --sort=-%mem の上位を、役割ごとに分けました。\n自分のアプリ：約166MB プロセス RSS 反応計測 / uvicorn 66.5MB 基幹システム / gunicorn worker 38.8MB 基幹システム / gunicorn master 25.9MB 仮想待合室 / Goバイナリ 34.7MB 動いていて当然のもの：約74MB プロセス RSS 役割 systemd-journald 24.5MB ログ caddy 23.0MB Webサーバー systemd 13.5MB init systemd-resolved 12.9MB DNS このサーバーでは働きようがないもの ここが今回の発見です。\nプロセス RSS 本来の用途 fwupd 44.0MB 物理デバイスのファームウェア更新 multipathd 26.7MB ストレージへの複数I/Oパスの管理 unattended-upgrade-shutdown 22.2MB 自動更新中のシャットダウン待機 udisksd 13.4MB ディスク・リムーバブルメディアの管理 ModemManager 12.8MB モバイル通信モデムの管理 VPSに物理ファームウェアはありません。モバイル通信のモデムも刺さっていません。USBメモリを挿すこともありません。\n常駐している3つ（multipathd + ModemManager + udisksd）だけで 約53MB。ここに fwupd が起動していると 約97MB になります。\n自作アプリ3本が166MBなので、使う予定のない仕組みが、その3割から6割に相当する量を占めていたことになります。\nmultipathd は本当に何もしていないのか 「不要そう」で終わらせず、確認しました。\nmultipathd の役割について、Ubuntu公式ドキュメントはこう説明しています。マルチパスは「複数の物理的なSAN接続（別々のケーブル、スイッチ、コントローラを含む）を通じて、複数のI/Oパスを集約する仮想デバイスを作成する」ための機能で、冗長性やI/O分散を目的としています。\nつまりストレージへの経路が複数ある環境のための仕組みです。では、このVPSに経路は何本あるのか。\n$ systemctl is-active multipathd active $ ls /dev/mapper/ control $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sr0 11:0 1 1024M 1 rom vda 253:0 0 100G 0 disk ├─vda1 253:1 0 1M 0 part └─vda2 253:2 0 100G 0 part / multipathd は動いています。しかし /dev/mapper/ にあるのは control だけ ── これはdevice-mapperの制御ノードで、マルチパスの管理対象ではありません。mpath で始まるデバイスは1つもない。\nlsblk を見ても、ディスクは vda が1本だけです。束ねるべき2本目の経路が、そもそも存在しない。\n管理対象ゼロで常駐している、ということが確認できました。\n補足：上記3コマンドは、同じさくらのVPS・Ubuntu 24.04の別の1台で実行したものです。構成は同じですが、厳密には測定対象のサーバーとは別の機体です。\n止める前に、自分の環境で確認してください 「不要だから止めろ」と書くつもりはありません。 環境によって前提が変わります。上の3コマンドを自分のサーバーで叩いて、同じ結果になることを確かめてから判断してください。\nsudo multipath -ll # 何も出なければ、束ねる経路はない systemctl status multipathd ModemManager udisks2 fwupd 止める場合も、1つずつ、間隔を空けて。本番サーバーなら、まず検証用の環境で試してください。\nsudo systemctl disable --now ModemManager # しばらく様子を見る sudo systemctl disable --now udisks2 # しばらく様子を見る sudo systemctl disable --now multipathd fwupd は測定の2分前（15:55）に起動していました。常時この44MBを消費し続けているとは限りません。この記事では「観測時点で起動していた」という事実のみを書いています。\nまた RSS は共有ライブラリを重複して数えるため、各プロセスの単純合計は used と一致しません。プロセス間の大小を比べるための目安として見てください。\nSwapが0だった ── 4台とも SwapTotal: 0 kB SwapFree: 0 kB スワップ領域がありませんでした。そして、これはこのサーバーだけの話ではありません。\nさくらのVPSを4台運用していますが、4台すべてがスワップ0でした。 ログイン時のバナーに出る Swap usage: 0% が、全台で並びます。\nこれは設定漏れではなく、提供側の仕様として説明されています。さくらのVPS公式マニュアル「swapfileの追加」には「一部、スワップパーティションを含まないイメージの提供を行っております」と明記されており、スワップファイルを後から追加する手順も公式に用意されています。\n危険なのか スワップがないということは、メモリを使い切った瞬間にOOM Killerが走り、プロセスが選ばれて強制終了されるということです。緩衝材がない。\nただし、実際に起きているかは別の話です。確認しました。\njournalctl -k | grep -i \u0026#34;killed process\u0026#34; # → 3台とも何も返らない OOM Killerの発動履歴は、どのサーバーにもありませんでした。 メモリ使用率が26〜31%で安定している以上、当然といえば当然です。\nつまり現状は「危険な構成だが、余裕があるので問題が表面化していない」状態です。ディスクは99GB中81GBが空いているので、スワップを置かない理由も特にありません。何かを追加で載せる前には作っておくべきだと考えています。\n2GBで足りる人・足りない人 実測から言えることを整理します。\n足りる 少人数が使う業務システム。今回は3本載せてメモリ使用は約1/4 DBサーバーを立てない（SQLiteやファイルベースで足りる） アクセス数が読める。急なスパイクがない 画像・動画・PDFの重い生成処理がない ワーカーを増やさず、スレッドで捌く構成にできる 足りない可能性が高い 不特定多数が使う公開サービス PostgreSQLやMySQLを立てる サーバー上でビルドやCIを回す（一瞬でメモリが跳ねる） AI系のツールを載せたい 最後の項目が、このサイトの本題です。\nこのサーバーは available 1.4GiB、ロードアベレージ0.20。数字の上では、まだ何かを載せる余地があります。 ただし n8n や Dify のような自動化ツールは、Docker・データベース・ワーカーがセットで付いてきます。166MBで動いている自作アプリとは要求される桁が違うはずですが、それは実際に載せてみないとわかりません。\n次の記事で、43時間・1分ごとに測り続けた結果を出しました → 43時間、1分ごとにVPSを測り続けた｜メモリを一番食っていたのは自分のアプリではなかった\nまとめ さくらVPS 2Gで自作システム3本：使用504MB / 空き1.4GiB / ロードアベレージ0.20、9日間無停止 アプリ3本の実使用は約166MB。2GBは思ったより余裕がある 収まっている最大の理由はDBサーバーを立てていないこと このサーバーでは働きようがないデーモンが53〜97MBを占めていた。プラン変更の前に、まずここを見る multipathd は動いているが、管理対象はlsblkと/dev/mapper/で確認する限りゼロ free は used ではなく available を見る 4台すべてスワップ0。さくらのVPSではスワップなしのイメージが提供される場合があり、公式に追加手順が用意されている スワップなしだが、OOM Killerの発動履歴は3台とも無し 参考 さくらのVPS マニュアル「swapfileの追加」 Ubuntu Server Documentation「Introduction to device mapper multipathing」 ","permalink":"https://jimae-ai.com/sakura-vps-2gb-memory/","summary":"\u003cp\u003eさくらのVPS 2Gプランで、自作の業務システムを3本動かしています。9日間連続稼働、ロードアベレージ0.20、メモリは\u003cstrong\u003e7割が空いたまま\u003c/strong\u003eです。\u003c/p\u003e\n\u003cp\u003e測ってみて、想定外だったことがあります。\u003cstrong\u003eアプリ3本が使っているのは約166MB。一方で、このサーバーでは働きようがないOSのデーモンが、合計50〜100MBを占めていました。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e自分のアプリより、使う予定のない仕組みのほうが目立つ。プラン変更を考える前に、見るべき場所がありました。\u003c/p\u003e\n\u003ch2 id=\"測定条件\"\u003e測定条件\u003c/h2\u003e\n\u003cp\u003e数字を出す記事なので、どういう状態で測ったかを先に書きます。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eサーバー\u003c/strong\u003e：さくらのVPS 2Gプラン / Ubuntu 24.04 LTS\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e測定時刻\u003c/strong\u003e：平日15:57、業務時間内だがアクセスはほぼない状態\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e稼働日数\u003c/strong\u003e：9日15時間（無停止）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eサンプル数\u003c/strong\u003e：1回（\u003ccode\u003evmstat\u003c/code\u003e のみ5秒間）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eしたがって以下の数字は\u003cstrong\u003eアイドルに近い状態のもの\u003c/strong\u003eです。ピーク時の値ではありません。負荷時の測定は別途行い、追記します。\u003c/p\u003e\n\u003ch2 id=\"動かしている3本\"\u003e動かしている3本\u003c/h2\u003e\n\u003cp\u003eすべて自作の業務システムです。フロントには Caddy を置いています。\u003c/p\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eシステム\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e構成\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003e常駐メモリ(RSS)\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e反応計測システム\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eFastAPI 0.141.1 / uvicorn 0.52.4 / \u003cstrong\u003eSQLite\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約66MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e基幹システム\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003ePython + gunicorn（\u003ccode\u003e-w 1 --threads 8 -t 120\u003c/code\u003e）\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約65MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e仮想待合室\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003eGo\u003c/strong\u003e（静的リンクの単一バイナリ）/ 設定はJSON\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約35MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e3本合計\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003cstrong\u003e約166MB\u003c/strong\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eCaddy\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eリバースプロキシ / HTTPS\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e約23MB\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e3本とも \u003ccode\u003e127.0.0.1\u003c/code\u003e のポートで待ち受けていて、外部に直接は晒していません。Caddyが受けて振り分けています。\u003c/p\u003e\n\u003cp\u003e基幹システムは自社の業務用なので、フレームワークやデータ構造の詳細は伏せます。\u003cstrong\u003eこの記事で必要なのはメモリの数字だけ\u003c/strong\u003eなので、そこは支障ありません。\u003c/p\u003e\n\u003ch3 id=\"3本で166mbに収まっている理由\"\u003e3本で166MBに収まっている理由\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eDBサーバーを1台も動かしていないから\u003c/strong\u003eです。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003esystemctl list-units --type\u003cspan class=\"o\"\u003e=\u003c/span\u003eservice --state\u003cspan class=\"o\"\u003e=\u003c/span\u003erunning \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e|\u003c/span\u003e grep -iE \u003cspan class=\"s2\"\u003e\u0026#34;postgres|mysql|maria|redis|mongo\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# → 何も返らない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ePostgreSQLもMySQLもRedisも入っていません。反応計測システムはSQLiteのファイル1つ（\u003ccode\u003edata/dareyomi.db\u003c/code\u003e）で動いています。\u003c/p\u003e","title":"さくらのVPS 2GBで自作システムを3本動かしている｜実測したら、要らないプロセスがアプリより食っていた"}]