VPS上に Ollama + 軽量ローカルLLMを構築した手順

  • ツール
  • VPS
  • LLM

GPUなしのVPS上に、Ollama と軽量なローカルLLMを構築した記録です。今回は「中国製モデルは避けたい」「日本語に強いものがよい」という条件で、ELYZA 系の日本語モデルを採用しました。

6 vCPU / 11 GiB RAM / GPUなし のVPSでも、短文用途なら十分実用になります。

一方で、長文生成はCPU推論なので重く、初回ロードは特に待ち時間が出ます。

今回の構成

項目内容
OSUbuntu系 Linux
サーバーGPUなし VPS
CPU6 vCPU
メモリ11 GiB
ディスク約 99 GiB
ランタイムOllama 0.17.7
モデルelyza/Llama-3-ELYZA-JP-8B-GGUFq4_k_m
Ollama上のモデル名elyza-jp-lite

このモデルを選んだ理由はシンプルです。

  • ELYZA は日本企業で、中国系モデルを避けたい条件に合う
  • 日本語寄りの調整が入っていて、汎用軽量モデルより日本語用途に向く
  • q4_k_m のGGUFなら、CPU-onlyでも現実的に動かせるサイズだった

先に結論

この構成でできたことは次の通りです。

  • Ollamasystemd 管理で常駐化
  • 127.0.0.1:11434 のみにバインドしてローカル限定公開
  • ELYZA のGGUFモデルを取り込み
  • OLLAMA_KEEP_ALIVE=-1 で常時ウォーム状態に変更
  • 短い日本語プロンプトで応答確認

常時ウォーム後は、X投稿程度の短文ならかなり使いやすくなります。

ただし「一瞬で返る」というより、「初回ロードの重さを避けられる」という理解が正確です。

正常系の構築手順

1. サーバー資源を確認する

まずは本当に載るかを確認します。

uname -a
free -h
df -h /
nproc

今回のサーバーでは、モデル常駐後でも1本なら十分回せる見込みでした。

ただし複数モデル常駐は厳しめです。

2. Ollama本体をインストールする

公式配布のLinuxバイナリを使います。

curl -fsSL https://ollama.com/download/ollama-linux-amd64.tar.zst | sudo tar —zstd -x -C /usr

インストール確認:

/usr/bin/ollama —version

3. 専用ユーザーを作る

root 直実行ではなく、専用の ollama ユーザーで管理した方が扱いやすいです。

sudo useradd —system —create-home —home-dir /usr/share/ollama —shell /usr/sbin/nologin ollama

4. systemdサービスを作る

今回は外部公開せず、127.0.0.1:11434 だけで待ち受ける構成にしました。

/etc/systemd/system/ollama.service

[Unit]
Description=Ollama Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=ollama
Group=ollama
Environment="HOME=/usr/share/ollama"
Environment="OLLAMA_HOST=127.0.0.1:11434"
Environment="OLLAMA_KEEP_ALIVE=-1"
ExecStart=/usr/bin/ollama serve
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

反映

sudo systemctl daemon-reload
sudo systemctl enable --now ollama.service
sudo systemctl status ollama.service --no-pager

5. モデルをダウンロードする

GGUFの保存先を作って、ollama ユーザーで取得します。

sudo install -d -o ollama -g ollama /usr/share/ollama/import
sudo -u ollama curl -L --fail --progress-bar \
-o /usr/share/ollama/import/Llama-3-ELYZA-JP-8B-q4_k_m.gguf \
https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/resolve/main/Llama-3-ELYZA-JP-8B-q4_k_m.gguf

このファイルは約 4.9 GB あります。 回線が遅い環境だと、ここが一番時間のかかる工程です。

6. Modelfileを作る

モデル名を分かりやすくするため、Modelfile を作って Ollama に取り込みます。

FROM /usr/share/ollama/import/Llama-3-ELYZA-JP-8B-q4_k_m.gguf

PARAMETER num_ctx 4096 PARAMETER temperature 0.6

SYSTEM あなたは簡潔で実務的な日本語アシスタントです。特に指定がない限り日本語で回答し、根拠が弱い場合は推測だと明示してください。

例えば /usr/share/ollama/import/Modelfile.elyza-jp-lite に置きます。

7. Ollamaへモデル登録する

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 \
/usr/bin/ollama create elyza-jp-lite \
-f /usr/share/ollama/import/Modelfile.elyza-jp-lite

登録確認

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 /usr/bin/ollama list

Sponsored

期待する結果のイメージ

NAMEIDSIZE elyza-jp-lite:latestxxxxxxxxxxxx4.9 GB

8. 動作確認する

まずは短い日本語で疎通確認します。

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 \
/usr/bin/ollama run elyza-jp-lite \
"ローカルLLMを127.0.0.1だけで待ち受ける利点を、日本語で一文で説明してください。"

ロード状態も確認できます。

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 /usr/bin/ollama ps

セキュリティです、的な応答がありました。

運用上のポイント

localhost限定にした理由

今回は 127.0.0.1:11434 に限定しました。

理由は単純で、Ollama APIをそのまま外部公開するのは雑だからです。 外から使いたいなら、別途次のような層を挟む方が安全です。

  • 認証付きのリバースプロキシ
  • Cloudflare Tunnel
  • Tailscale
  • SSHトンネル

とりあえずローカル限定にしておけば、事故率はかなり下がります。

常時ウォーム化は有効

OLLAMA_KEEP_ALIVE=-1 を設定すると、一度ロードされたモデルが常駐します。 これで「最初だけ異様に遅い」問題がかなり緩和されます。

確認コマンド:

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 /usr/bin/ollama ps

常駐していれば UNTIL が Forever になります。

実際に詰まったポイント

ここからが本題です。 正常系だけ書くと簡単そうに見えますが、実際にはいくつか引っかかりました。

1. tar で展開時に —zstd が必要だった

最初に次のように実行すると失敗しました。

curl -fsSL https://ollama.com/download/ollama-linux-amd64.tar.zst | sudo tar x -C /usr

エラー

tar: Archive is compressed. Use —zstd option

修正版はこちらです。

curl -fsSL https://ollama.com/download/ollama-linux-amd64.tar.zst | sudo tar —zstd -x -C /usr

.tar.zst なので当然ではあるのですが、つい -x だけで通ると思って詰まりました。

2. Modelfileを ollama ユーザーが読めなかった

最初は Modelfile をホーム配下に置いて、こんな感じで作ろうとしました。

sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434
/usr/bin/ollama create elyza-jp-lite
-f /home/username/work/local-llm/Modelfile.elyza-jp-lite

すると権限エラーになりました。

Error: stat /home/username/work/local-llm/Modelfile.elyza-jp-lite: permission denied

原因は、sudo -u ollama で実行しているのに、ホーム配下の権限が閉じていたことです。 これは Modelfile を /usr/share/ollama/import に置き直して解決しました。

3. GGUF本体も「誰が読むか」を揃えた方が安全だった

モデル取り込み時は、クライアント実行ユーザーとファイル所有者がズレると面倒です。 今回のように最初から以下を統一しておくとトラブルが少ないです。

項目内容
保存先/usr/share/ollama/...
所有者ollama:ollama
実行ユーザーsudo -u ollama

4. サービス再起動直後に叩くと、たまに早すぎる

systemctl restart ollama.service の直後にすぐ ollama run すると、起動直後のタイミングで失敗することがありました。

Sponsored

たとえばこういう系です。

Error: could not connect to ollama server, run ‘ollama serve’ to start it

実際にはサービスは立ち上がっていて、ほんの少し待てば問題ありません。 この手の処理は以下のようにすると安定します。

sudo systemctl restart ollama.service sleep 2 sudo -u ollama env OLLAMA_HOST=127.0.0.1:11434 /usr/bin/ollama ps

5. 「短文を作って」と言っても、モデルは長めに話しがち

これはエラーではないですが、運用上の詰まりポイントでした。

たとえば「X向け140字前後で」と投げても、モデルによっては必要以上に長く説明し始めます。 そのため、実運用では次のような工夫が必要です。

  • 「140字以内」
  • 「1文だけ」
  • 「箇条書き禁止」
  • num_predict を絞る
  • 定型の短文プロンプトを用意する

つまり、モデルを入れただけで即SNS運用に使えるわけではなく、出力制御の設計は別途必要です。

性能感

このVPSでは、初回ロード込みの短文生成は約30秒かかりました。 一方、ロード済み状態では短い応答がかなり速くなります。

体感としてはこんな感じです。

条件体感
初回ロード直後重い
ウォーム状態の短文十分実用
X投稿サイズ下書き用途なら問題なし
長文生成まだ重い

重要なのは、「常時ウォームでコールドスタートを避ける」ことです。 CPU-only環境では、ここをやるだけで使い勝手がかなり変わります。

不要ファイルの整理

ollama create 後は、元のGGUFを必ずしも残す必要はありません。 ディスク節約のため、取り込み後に削除してもよいです。

sudo rm -f /usr/share/ollama/import/Llama-3-ELYZA-JP-8B-q4_k_m.gguf sudo rm -f /usr/share/ollama/import/Modelfile.elyza-jp-lite

Ollama内部ストア側に取り込み済みなら、通常利用には問題ありません。

まとめ

GPUなしVPSでも、Ollama + 軽量GGUFモデル で日本語ローカルLLMは十分構築できます。 今回の条件なら、ELYZA 系はかなり素直な選択でした。

ポイントをまとめると次の通りです。

  • 日本語重視なら、日本語寄りモデルを選ぶ
  • localhost 限定で始める
  • systemd 管理にする
  • モデル所有者と実行ユーザーを揃える
  • OLLAMA_KEEP_ALIVE=-1 でウォーム状態を維持する
  • 長文より、短文アシスト用途から始める

「VPSでローカルLLMを動かす」と聞くと大げさに見えますが、短文用途に割り切れば十分現実的です。 特に、下書き生成、要約、短文案出し、日本語の壁打ち用途にはかなり向いています。

次にやるなら、用途別にモデルやプロンプトを分けるのが良さそうです。

  • X投稿用の短文プリセット
  • 要約用プリセット
  • サーバー内専用のAPIラッパー
  • 認証付きの外部公開経路

ローカルLLMは「万能な本番AI」ではないですが、「自分のVPSで軽く使う道具」としてはかなり面白いです。