2026年10月4日 / 投稿

Proxmoxで日本語ローカルLLMを動かす — 小さな構成の作り方と高速化の展望

ProxmoxのLXCコンテナに、OllamaとOpen WebUIを組み合わせた日本語チャット環境を構築した。モデルはQwen3 1.7B。ブラウザから利用でき、日本語の応答と画面の日本語化まで確認できた。

ただし、CPUだけで動かす小さな環境では、返答を待つ時間が気になる。「動いた」から「日常的に使いやすい」へ進むには、モデルと設定、そして計算資源の見直しが必要になる。今回は構築の流れを振り返り、次に試したい高速化の道筋を整理する。

小さなコンテナに、モデルとチャット画面を用意する

構成は、Debian 12の非特権LXCにOllamaを入れ、同じコンテナ内のOpen WebUIから接続する形にした。Dockerを重ねず、Open WebUIはPython 3.11の仮想環境とsystemdで動かす。GPUの割り当ては行っていない。

Ollamaがモデルを実行し、Open WebUIがログイン、チャット画面、会話履歴を担当する。画面からモデルサーバーへの接続は、コンテナ内のループバックアドレスを使う。公開用の記事では、実環境のIPアドレス、ノード名、コンテナ番号、利用者名、内部文書のURLを省いている。

資源配分の目安は、少人数の短い会話から始めるなら2〜4 vCPU、メモリ4 GiB程度、ディスク20〜30 GiB程度。ただし、これは容量を考える出発点であり、快適な速度を保証する値ではない。ホストOSと他のサービスに必要な余裕も残す。

選んだQwen3 1.7Bは、配布サイズ約1.4 GBの量子化モデル。日本語を含む多言語の会話を試すため、まず小さいモデルを使うことにした。

構築の流れ

1.ProxmoxでOSテンプレートと空き資源を確認する。対象ノードのCPU、メモリ、ストレージ、ネットワークブリッジを確認し、空いているCT番号を選ぶ。Debian 12の公式テンプレートを取得し、非特権コンテナを作成する。実環境のCT番号をそのまま公開用の例へ流用しないことも意識した。

2.コンテナ内の基本パッケージを整える。以下はDebianコンテナ内で実行するコマンド。Proxmoxホストに直接インストールするものではない。

apt-get update
apt-get install -y curl ca-certificates python3-venv python3-pip zstd

3.Ollamaとモデルを導入する。Ollama公式のLinux導入手順に従ってインストールし、サービスが起動したことを確認してからモデルを取得する。

curl -fsSL https://ollama.com/install.sh | sh
systemctl is-active ollama
ollama pull qwen3:1.7b

4.Open WebUIを仮想環境に導入する。PythonパッケージはOSの環境から分離する。今回の作業ではCPU向けPyTorchの導入を先に試し、依存パッケージの取得エラーに対処してからOpen WebUIの導入を完了した。通常の導入方法はOpen WebUIの公式Quick Startで確認できる。

python3 -m venv /opt/open-webui
/opt/open-webui/bin/pip install --upgrade pip
/opt/open-webui/bin/pip install --no-cache-dir open-webui

最初のエラーは、PyTorch用の配布元だけを指定したため、別のビルド依存パッケージが見つからなかったこと。pipの更新とPyPIの追加で解消した。また、端末の通常のバックグラウンド実行が中断したため、nohupを使って導入ログをファイルに残しながら再開した。「コマンドを実行した」で終わらず、ログと終了結果を確認することが大切だった。

5.データを永続化し、自動起動を設定する。Open WebUI専用のOSユーザーを作り、会話履歴・ユーザー設定の保存先と作業ディレクトリを固定した。systemdでは仮想環境のopen-webuiコマンドを起動し、コンテナ自体にも自動起動を設定する。次はサービス内で使う主な設定例。

WorkingDirectory=/var/lib/open-webui
Environment=DATA_DIR=/var/lib/open-webui/data
Environment=OLLAMA_BASE_URL=http://127.0.0.1:11434
Environment=DEFAULT_MODELS=qwen3:1.7b
Environment=OFFLINE_MODE=true
Environment=HF_HUB_OFFLINE=1
ExecStart=/opt/open-webui/bin/open-webui serve --host 0.0.0.0 --port 8080

これはsystemdサービスの一部を示す例で、単独では完全なサービス定義ではない。専用ユーザー、起動順序、再起動方針を含めて定義し、daemon-reloadとenable、startを実行する。データディレクトリと作業ディレクトリには、その専用ユーザーが書き込めるようにする。

6.APIとブラウザの両方で確認する。Ollamaが返答することを確認してから、ブラウザで「コンテナのアドレス:8080」にアクセスする。初回アカウントを作り、モデルを選ぶ。表示言語はユーザーメニューのSettings → General → LanguageでJapaneseを選び、「保存」を押す。

curl -s http://127.0.0.1:11434/api/chat -d '{"model":"qwen3:1.7b","messages":[{"role":"user","content":"Reply in Japanese. Introduce yourself in one short sentence."}],"think":false,"stream":false,"options":{"num_predict":60,"num_ctx":2048}}'

このテストでは日本語の短い自己紹介が返ってきた。入力を英語にしたのは、ブラウザ内の端末へ日本語を貼り付ける際の文字化けを避けるため。WebUIの表示言語と、モデルにどの言語で答えさせるかは別の設定になる。

動いたものの、CPUでの会話は待ち時間がある

小型モデルでも、古い低電力CPUで文章を生成するには時間がかかる。今回の構成は日本語チャットの土台として動作したが、快適な対話速度を達成したとは言えない。まだ比較ベンチマークを行っていないため、CPU性能、モデル読み込み、会話履歴の処理、思考モードのどれが待ち時間をどれだけ占めるかは、これから切り分ける。

LXCへ割り当てるコア数を増やしても、ホストに存在する計算能力が増えるわけではない。メモリ増設は不足やswapの解消には役立つが、CPUでのトークン生成そのものが必ず大幅に速くなるわけでもない。設定変更の前後を測って判断したい。

高速化の第一歩は、同じ条件で測ること

まず同じ質問、同じモデル、同じ出力上限で数回試す。起動直後の測定と、モデルがメモリに載った後の測定を分ける。APIのload_duration、prompt_eval_duration、eval_durationを見れば、読み込み、入力処理、生成のどこで時間を使っているかを把握しやすい。生成速度は「eval_count ÷(eval_duration / 1,000,000,000)」でtokens/sに換算できる。Ollama Chat APIの応答項目を基準に記録する。

同時にホストとコンテナのCPU使用率、空きメモリ、swap、他のサービスとの競合を確認する。画面が少しずつ文章を表示するストリーミングは待ち時間の感じ方を改善するが、生成能力そのものを増やす設定ではない。

まず試したい、費用をかけない改善

思考モードを用途に合わせる。短い挨拶や日常の質問では、長い思考を省けるか試す。Open WebUIの高度なパラメータにはthink (Ollama)があり、Offはthink:falseを送信する。思考表示を隠すだけでは、計算を省いたことにならない点に注意したい。Open WebUIの思考モデル設定に沿って、応答品質との両立を確認する。今回のAPIテストでは無効にしたが、WebUIの標準設定にはまだ適用していない。

会話を必要以上に長くしない。新しい話題は新しいチャットに分け、短く答えてほしい場合はそう指示する。今回、Ollamaにはコンテキスト2048、並列処理1、ロードするモデル数1を設定した。WebUI側から別の値を送れば設定が変わり得るため、実際のリクエストも確認する。Ollama公式FAQでは、並列処理とコンテキストがメモリ使用量に影響すると説明されている。

[Service]
Environment=OLLAMA_CONTEXT_LENGTH=2048
Environment=OLLAMA_NUM_PARALLEL=1
Environment=OLLAMA_MAX_LOADED_MODELS=1

モデルの再読み込みを減らす。頻繁に使うならkeep_aliveやOLLAMA_KEEP_ALIVEで保持時間を延ばす案がある。これは初回の読み込み待ちを減らすための調整で、生成中のtokens/sを直接上げるものではない。メモリを占有する時間との兼ね合いを見て決める。設定方法はOllama公式FAQを参照する。

もっと小さいモデルと比較する。短文応答、定型案内、簡単な分類に用途を絞れば、小型モデルが適する可能性がある。一方で、日本語の自然さ、指示への追従、事実の正確さが下がることもある。「速いが役に立たない」を避けるため、普段の質問を評価用に揃えて比較したい。量子化をさらに強める案もあるが、速度・品質・実行環境の対応をセットで検証する。

次の展望:画面を残して、推論を強いマシンへ移す

設定だけで限界が見えたら、計算を担当する場所を変える。新しいCPUと十分なメモリを持つマシンへ推論を移す案、対応GPUを持つマシンへ移す案を比較する。GPUの効果はモデル、VRAM容量、ドライバー、実際にGPUへ載った割合で変わるため、導入前にOllamaのハードウェア対応を確認する。

Open WebUIとOllamaを別のマシンに分ければ、ブラウザ画面と会話履歴を維持しながら、推論側だけを交換できる。将来はこの分離構成が有力だと考えている。LXCでGPUを使う場合はホストのドライバーとデバイスへのアクセスを整える必要があり、場合によってはGPUを割り当てたVMや別の専用マシンの方が管理しやすい。

移行後はモデルを実際にGPUへ載せてからollama psでPROCESSOR欄を確認する。APIを別マシンへ出す場合は、接続を必要な範囲に限定する設計も一緒に行う。今回の作業ではGPU化や別マシンへの移行は実施していない。

次回は「待ち時間の内訳」を記録したい

今回確認できたのは、非特権LXCへの導入、モデル取得、日本語のAPI応答、ログイン後の画面、日本語表示、自動起動の設定まで。ホストやコンテナの再起動後の復帰、バックアップの復元、長時間運転、複数人での負荷試験はまだ行っていない。

まずは短い会話の条件を揃え、思考モードとモデル保持時間を調整したときの待ち時間を測る。その結果から小型モデルへの変更や推論マシンの移行を判断する。自分の環境でLLMを動かせた今回の構成を、用途に合った速度と品質へ育てていきたい。