M4 Mac mini(32GB)ローカルLLM構築!失敗からAIと二人三脚で立ち上げた実践記

M4 Mac miniローカルLLM構築!失敗から大逆転し26GB限界突破した全記録

こんにちは、中のひとアツです。

ついに手元に届いたM4チップ搭載の新型Mac mini(32GBモデル)

「32GBのユニファイドメモリを活かして、最強のローカルLLM環境を作るぞ!」と意気込んで開封したのですが……実は稼働にこぎつけるまで、以下のような波乱万丈な3日間を過ごすことになりました。

  • 1日目:Mac miniにマウスを繋げられず詰む(Type-Cのみの洗礼)
  • 2日目:アダプタを使いマウスを繋げたが、ポンコツプロンプトによりOS再インストールを選ぶことに
  • 3日目:改良型プロンプトを使い、エラーを吐きながらも数時間で構築完了

ここで、読者の皆様に重大なお詫びがあります。

連載第2回で「評価9.8の神プロンプト!」とドヤ顔で紹介した指示書ですが……
あれ、実は指示が甘い箇所がありました。本当に申し訳ありません!
あのプロンプトのせいで私は見事に「権限地獄」へ叩き落とされ、OS再インストールを余儀なくされました。
数々の絶望とエラーを乗り越えて完成した「プロンプト」は、後日公開するまとめ記事にて全公開しますので、そちらをお待ちください!

失敗の詳細はまとめ記事に譲るとして、今回は大逆転を果たした「3日目」の全記録を公開します。

【連載:M4 Mac miniで最強ローカルLLM環境を作る!】


目次

1. 【フェーズ0〜1】OSダイエットと「最大26GB」のメモリ最適化

今回の構築要件は非常にシビアなものでした。IPを固定し、外部からのアクセス基盤を堅牢にすること。
そして何より、「メモリ32GBのうち、最大26GB程度を推論(GPU)用に確保する」という極限の最適化です。

決死のOS再インストール(英語UIの洗礼)

権限地獄をリセットするため、私はディスクユーティリティからOSの再インストールを断行しました。

リカバリーモードから再インストールすると、UIが全部「English」になるんですね……! 英語メッセージを読み解きながらクリーンインストールを完了。
Siriや常駐アプリを徹底排除し、OS側のメモリ消費を極限まで削ぎ落としました。

ちなみに今回のプロンプトが提示してきたシステムはこちらです。

[Client PC (Browser & SSH Terminal)]

├─(1) HTTP Access ───▶ [Mac mini M4 (192.168.2.100)]
│ │
│ ├─ Port 8080: Open WebUI (uv Python daemon)
│ │ └─ Data: /Users/llm-admin/OpenWebUI_Data
│ │
│ ├─ Port 11434: Ollama API (macOS native daemon)
│ │ └─ Models: /Users/llm-admin/OllamaModels (Total ~110GB)
│ │ ├─ Qwen 3.5-VL 32B / DeepSeek-R1 32B 等
│ │ └─ Qwen 3.5 14B / Phi-4 14B 等
│ │
│ └─ [Metal API / Apple Silicon M4 Unified Memory (32GB)]

└─(2) SSH Access ────▶ [リソースモニタリング (VRAM/GPU使用率の監視)]

メモリ消費の最適化と揮発対策

仕上げに sysctl 設定により、macOSがシステム維持のために予約している領域を調整。ユニファイドメモリの特性を活かし、推論用に最大26GB程度を割り当て可能なインフラを完成させました。この設定が再起動で消えないよう、自動実行プログラムとしてデーモン化しています。


2. 【フェーズ2】開発ツールの導入と「見えないGUI」の罠

メイン作業はSSH経由。ここでmacOS特有の「ヘッドレス構築の罠」に遭遇します。

前半戦: Mac mini 本体の物理セットアップ(GUI操作)

工場出荷状態からの初回セットアップ(キーボードとマウス、HDMIディスプレイを一時的に繋いだ状態)にて、以下の設定を行ってください。
1. 初期セットアップアシスタント(OS初回起動時)
ユーザー作成: アカウント名を llm-admin として作成します。
Apple ID: 「あとで設定」等を選択し、絶対にサインインしないでスキップします。
位置情報: 「このMacで位置情報サービスを有効にする」のチェックを外し、無効化します。
時間帯(タイムゾーン): 日本(東京/大阪など)を手動で選択します。
※位置情報を無効化したままだとアメリカしか選べなかったので、一度位置情報を有効にしたうえで日本時間を選択した後で無効化しました。
解析/スクリーンタイム: すべてオフ(共有しない)にします。
2. デスクトップ表示後のシステム設定
「システム設定」アプリを開き、以下の項目を順に変更します。
[ネットワーク] > [Wi-Fi または Ethernet]: 詳細設定からIPアドレスを 192.168.2.100 に手動固定します。
[一般] > [共有]: 「リモートログイン(SSH)」と「画面共有(VNC)」の2つをオンにします。
[ディスプレイ] > [詳細] または [省エネルギー]: 「ディスプレイがオフのときは自動でスリープさせない」をオン
「停電後に自動的に起動」をオン
[一般] > [ログイン項目と拡張機能]: バックグラウンド実行が許可されている不要なアプリがあれば全てオフにします。
[ユーザーとグループ]: 「自動ログイン」がオフになっていることを確認します。
3. 完全ヘッドレス化の実行
Mac miniをシステム終了(シャットダウン)します。
ディスプレイ、キーボード、マウスのケーブルをすべて抜きます。(電源ケーブルとLANケーブルのみ残す)
Mac miniの電源ボタンを押し、起動させます。
※画面はありませんが、裏側では「ログイン画面」で待機している状態になります。

SSH経由のフリーズ事件

xcode-select --install を叩いた瞬間、ターミナルが完全にフリーズ。

実はコマンドの裏側で「インストールに同意しますか?」というGUIのダイアログボックスが出現し、マウスクリックを待機していたのです。

XCODEがインストールできていないためエラーが発生している様子


VNC(画面共有)で一時的にデスクトップに入り、マウスで「同意」をクリックして突破しました。

Geminiが提示した解決策

画像のご提示ありがとうございます。エラー内容を完全に把握しました。

xcode-select: error: no developer tools were found, and no install could be requested (perhaps no UI is present)

これは**「画面(UI)が存在しないため、インストールの許可ポップアップを出せない」**というmacOSのセキュリティ仕様によるエラーです。 先ほど自動ログインをオフにして完全にケーブルを抜いたため、Mac miniが現在「ログイン画面」で待機しており、GUIセッションが存在しないことが原因です。設計通りに極限までシステムが削ぎ落とされている証拠でもありますので、ご安心ください。

このブロックを突破するために、以下の手順で一時的にGUIを呼び出してインストールし、終わったらGUIを消す作業を行います。

解決手順:VNC経由でのインストールとメモリ解放

1. VNC(画面共有)でログインする クライアントPC(WindowsならVNC Viewer、Macなら「画面共有」アプリ)を開き、192.168.2.100 に接続します。 ログイン画面が表示されたら、パスワードを入力して一度デスクトップ画面を表示させてください。

2. SSHターミナルで再実行 VNCでデスクトップが表示されている状態のまま、先ほどエラーが出たSSHターミナルで、もう一度以下のコマンドを実行します。

Bash

xcode-select --install

3. VNC画面でクリック 今度はVNCの画面上(Mac miniのデスクトップ)に「インストールしますか?」というポップアップが正常に出現します。「インストール」をクリックし、ゲージが最後までいって完了するのをお待ちください。

4. ログアウトしてGUIを殺す(最重要) インストールが完了したら、VNC画面の左上にあるリンゴマーク(Appleメニュー)をクリックし、**「llm-admin をログアウト」**を選択してください。 画面が再びログイン画面に戻ったら、VNCを閉じて構いません。


3. 【フェーズ3】デーモン化の壁。権限と「迷子」のトラブル

Macを再起動しても自動でシステムが立ち上がるよう、/Library/LaunchDaemons に設定ファイル(.plist)を作成。ここが最大の難所でした。

後半戦: クライアントPCからのSSH構築(CUI操作)

ここからは、お手元の作業用PC(Windowsや別のMac等)のターミナルを開き、以下の手順を順番にコピペして実行します。

Step 1: 接続と事前準備・VRAM限界突破

まずSSHで接続し、基盤を整えます。

Bash

# 1. SSH接続
ssh llm-admin@192.168.2.100
# (パスワードを入力してログイン)

# 2. ディレクトリの作成
mkdir -p /Users/llm-admin/OllamaModels
mkdir -p /Users/llm-admin/OpenWebUI_Data

# 3. Xcode Command Line Tools のインストールトリガー
xcode-select --install

【重要】 ここでターミナル上の処理が止まります。クライアントPCからMac mini(192.168.2.100)へ VNC(画面共有)で接続 してください。ログイン画面の背後に「インストールしますか?」という警告ポップアップが出ているはずなので、「インストール」をクリックし、完了するまで待ちます。完了したらSSHターミナルに戻り、以下を続行します。

Bash

# 4. 超高速Pythonパッケージマネージャ `uv` の最速インストール
curl -LsSf https://astral.sh/uv/install.sh | sh

# ★ 5. 直後に環境変数を読み込み (必須)
source $HOME/.local/bin/env

# 6. asitop の隔離インストール (モニタリング用)
uv tool install asitop

# 7. 【VRAM限界突破】26GB(26624MB)の永続化デーモン作成と即時適用
sudo sh -c 'cat > /Library/LaunchDaemons/com.apple.vram_override.plist << "EOF"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.apple.vram_override</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/sbin/sysctl</string>
        <string>iogpu.wired_limit_mb=26624</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF'

sudo chown root:wheel /Library/LaunchDaemons/com.apple.vram_override.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.apple.vram_override.plist
sudo sysctl iogpu.wired_limit_mb=26624

Step 2: Spotlightの除外設定(CUIで実行)

重いインデックス作成プロセス(mdworker)の暴走を防ぐため、作成したディレクトリを検索対象から除外します。

Bash

sudo mdutil -i off /Users/llm-admin/OllamaModels
sudo mdutil -i off /Users/llm-admin/OpenWebUI_Data

Step 3: Ollamaのネイティブ導入とファイアウォール許可

Bash

# 1. Ollamaアプリのダウンロードと配置
cd ~
curl -L https://ollama.com/download/Ollama-darwin.zip -o Ollama-darwin.zip
unzip Ollama-darwin.zip
sudo mv Ollama.app /Applications/
rm Ollama-darwin.zip

# ★ 2. 手動シンボリックリンク作成 (必須)
sudo ln -s /Applications/Ollama.app/Contents/Resources/ollama /usr/local/bin/ollama

# 3. ファイアウォールのGUIブロックダイアログをCUIでサイレント許可
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/ollama
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /usr/local/bin/ollama

Step 4: Open WebUIの構築と ★プレフライト(初回動作確認)

Bash

# 1. Open WebUI の隔離インストール
uv tool install open-webui

# 2. ファイアウォール許可
WEBUI_BIN=$(which open-webui)
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add $WEBUI_BIN
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp $WEBUI_BIN

# ★ 3. プレフライト (フォアグラウンドでの初回起動・動作確認)
export DATA_DIR=/Users/llm-admin/OpenWebUI_Data
export HOST=0.0.0.0
export PORT=8080
open-webui serve

【確認手順】 ターミナルにログが流れたら、クライアントPCのブラウザから http://192.168.2.100:8080 にアクセスしてください。ログイン画面が出たら成功です。SSHターミナル上で Ctrl + C を押してプロセスを終了させてください。

Step 5: 完全ヘッドレス向けデーモン化(LaunchDaemons登録)

Bash

# 1. Ollamaデーモンのplist作成
sudo sh -c 'cat > /Library/LaunchDaemons/com.ollama.server.plist << "EOF"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.ollama.server</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/ollama</string>
        <string>serve</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>OLLAMA_MODELS</key>
        <string>/Users/llm-admin/OllamaModels</string>
        <key>OLLAMA_HOST</key>
        <string>0.0.0.0</string>
    </dict>
    <key>UserName</key>
    <string>llm-admin</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/Users/llm-admin/ollama.err</string>
    <key>StandardOutPath</key>
    <string>/Users/llm-admin/ollama.log</string>
</dict>
</plist>
EOF'

# 2. Open WebUIデーモンのplist作成
sudo sh -c 'cat > /Library/LaunchDaemons/com.openwebui.server.plist << "EOF"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.openwebui.server</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/llm-admin/.local/bin/open-webui</string>
        <string>serve</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>OLLAMA_BASE_URL</key>
        <string>http://127.0.0.1:11434</string>
        <key>DATA_DIR</key>
        <string>/Users/llm-admin/OpenWebUI_Data</string>
        <key>HOST</key>
        <string>0.0.0.0</string>
        <key>PORT</key>
        <string>8080</string>
        <key>PATH</key>
        <string>/Users/llm-admin/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
    <key>UserName</key>
    <string>llm-admin</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/Users/llm-admin/openwebui.err</string>
    <key>StandardOutPath</key>
    <string>/Users/llm-admin/openwebui.log</string>
</dict>
</plist>
EOF'

# ★ 3. 権限設定とデーモンの登録 (必須)
sudo chown root:wheel /Library/LaunchDaemons/com.ollama.server.plist
sudo chown root:wheel /Library/LaunchDaemons/com.openwebui.server.plist

sudo launchctl bootstrap system /Library/LaunchDaemons/com.ollama.server.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.openwebui.server.plist

Step 6: モデルの導入(SSH切断対策)

Bash

# ★ 1. screen セッションの開始 (必須)
screen -S model_download

# ★ 2. 手動での環境変数適用 (必須: デーモンと同じ領域に保存させるため)
export OLLAMA_MODELS=/Users/llm-admin/OllamaModels

# 3. ベンチマーク用7モデルのダウンロード (総計約110GB)
ollama pull qwen3.5-vl:32b
ollama pull hf.co/RedHatAI/Llama-4-Scout-17B-16E-Instruct-quantized.w4a16
ollama pull deepseek-r1:32b
ollama pull command-r:35b
ollama pull qwen3.5:14b
ollama pull deepseek-r1:14b
ollama pull phi4:14b

# ※ダウンロード中にPCを閉じても問題ありません。
# 再接続後に `screen -r model_download` で進行状況を再確認できます。

以上が、開封から稼働までの一連の完全な手順書となります。 Spotlightの除外設定もコマンド(mdutil)で一撃で終わるようStep 2に組み込みましたので、GUIであちこち探す手間も省いてあります。

こちらの手順を手元に控え、実際の構築作業を開始していただいてよろしいでしょうか? もし途中でお困りのことがあれば、いつでもサポートいたします。

エラー1:フルディスクアクセス権限の制限

SpotLightの除外設定でエラーがでました。

フルディスクアクセス権限の制限でエラーが発生している様子
Geminiが提示した解決策

mdutil エラーの原因について

Error: invalid operation. unknown indexing state.

これはmacOSの強固なセキュリティ(TCC:フルディスクアクセス権限)により、SSH経由のターミナルから特定のフォルダのSpotlight設定を直接書き換えることがブロックされたために発生したエラーです。

システムに悪影響は一切ありませんのでご安心ください。権限で弾かれるなら、**macOSのシステムが絶対に逆らえない別の「隠し仕様」**を使ってSpotlightの検索インデックス作成をブロックします。

解決手順:隠しファイルによるSpotlightブロック

macOSのSpotlightは、フォルダ内に .metadata_never_index という名前の空ファイルが存在すると、強制的にそのフォルダの中身の解析を放棄する仕様になっています。

現在のSSHターミナルで、以下の2行をコピペして実行してください(一瞬で終わります)。

Bash

touch /Users/llm-admin/OllamaModels/.metadata_never_index
touch /Users/llm-admin/OpenWebUI_Data/.metadata_never_index

何もエラーが出ずに次の入力行(%)が出れば成功です。これで重いインデックス作成プロセス(mdworker)の暴走を完全に防ぐ処置が完了しました。

エラー2:リダイレクトの権限弾き

フォルダが存在しないとエラーが出ました。

フォルダが存在しないためエラーが発生している様子
Geminiが提示した解決策

画像のご提示ありがとうございます。状況を確認しました。

ln: /usr/local/bin/ollama: No such file or directory

このエラーは「ollamaが存在しない」という意味ではなく、**「リンク先を置くための /usr/local/bin というフォルダ自体が、まだMacに存在しない」**という意味です。

これは非常に良い傾向です! Apple SiliconのMacでは、余計な開発ツール(Homebrewなど)が一切入っていない**「工場出荷状態の最もクリーンな環境」**だと、このフォルダが最初から作られていない仕様になっています。まさに推論サーバーとして純度の高い状態が保たれています。

解決手順:フォルダを作ってからリンクを貼る

リンクの置き場所(フォルダ)を作成してから、再度シンボリックリンクのコマンドを実行します。 現在のターミナルに以下のコマンドを順にコピペしてください。

Bash

# 1. リンクを置くためのフォルダ(/usr/local/bin)を作成する
sudo mkdir -p /usr/local/bin

# 2. 先ほど失敗したシンボリックリンク作成を再実行する
sudo ln -s /Applications/Ollama.app/Contents/Resources/ollama /usr/local/bin/ollama

# 3. 続くファイアウォールの設定も一気に実行する
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/ollama
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /usr/local/bin/ollama

これでエラーなく通過できるはずです。 無事に通過しましたら、元の手順書の 【Step 4: Open WebUIの構築と ★プレフライト】 へお進みください!

エラー3:リダイレクトの権限弾き

sudo を使っても、リダイレクト先(>)には管理者権限が引き継がれない仕様に阻まれました。sudo sh -c 'cat << EOF > ...' という構文を用いることで、安全にファイルを生成できました。

エラー4:WebUIがホームを見失う

デーモンはroot実行されるため、ユーザーのホームディレクトリを見失います。


plist内の <key>EnvironmentVariables</key> 辞書に、HOME や秘密鍵を直接ハードコード(絶対パス指定)することで、デーモンの「迷子」を防止しました。

Geminiが提示した解決策

1. デーモン(裏側の自動起動プログラム)がシステムに登録されているかの確認

Bash

sudo launchctl list | grep openwebui

2. Open WebUIの裏側のエラーログの確認

Bash

cat /Users/llm-admin/openwebui.err

(※もし「そのようなファイルはありません」と出た場合や、何も表示されない場合は、まだStep 5が実行されていない状態です)

画像のご提示、本当にありがとうございます。エラーの全貌を完全に把握しました。

OSError: [Errno 30] Read-only file system: '/.webui_secret_key'

これは、Open WebUIがログインパスワード等を暗号化するための「秘密鍵(.webui_secret_key)」を、macOSの最深部であるルートディレクトリ(/)に作成しようとして、OSの強固なセキュリティに弾かれたというエラーです。

macOSのルートディレクトリは「Read-only(書き込み禁止)」の聖域であるため、このエラーが出ました。現在のターミナルの作業場所(カレントディレクトリ)が、何かの拍子にルート(/)に移ってしまっていたことが原因です。

この問題を完全に解決し、さらに**次の【Step 5: デーモン化】でも同じエラーが裏側で起きないようにするための「完璧な修正手順」**をご案内します。

解決手順 1: プレフライト(手動起動)のやり直し

まずは作業場所(カレントディレクトリ)を、先ほど作成したデータ保存用フォルダに移動してから起動します。以下のコマンドをコピペして実行してください。

Bash

# 1. データ保存用フォルダへ移動する
cd /Users/llm-admin/OpenWebUI_Data

# 2. 環境変数を再設定して起動
export DATA_DIR=/Users/llm-admin/OpenWebUI_Data
export HOST=0.0.0.0
export PORT=8080
open-webui serve

これでターミナルにログが流れ始めたら、ブラウザから http://192.168.2.100:8080 にアクセスしてください。今度は正常にログイン画面が表示されるはずです。 確認できたら、ターミナルで Ctrl + C を押してプロセスを終了させてください。


解決手順 2: 【Step 5】の設計図(plist)の修正

プレフライトが成功したら、次は【Step 5: 完全ヘッドレス向けデーモン化】に進みますが、私の提示した元の設計図に1箇所だけ致命的な抜けがありました。 デーモン(バックグラウンドプロセス)は、指定しないと強制的にルートディレクトリ(/)で起動してしまう性質があるため、元のままStep 5を実行すると全く同じエラーで裏側で死んでしまいます。アーキテクトとしてお詫びいたします。

起動場所を指定する <key>WorkingDirectory</key> を追加した修正版のStep 5を作成しました。 プレフライト終了後、以下のコマンドを全てコピペして実行してください。

Bash

# 1. Ollamaデーモンのplist作成
sudo sh -c 'cat > /Library/LaunchDaemons/com.ollama.server.plist << "EOF"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.ollama.server</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/ollama</string>
        <string>serve</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>OLLAMA_MODELS</key>
        <string>/Users/llm-admin/OllamaModels</string>
        <key>OLLAMA_HOST</key>
        <string>0.0.0.0</string>
    </dict>
    <key>UserName</key>
    <string>llm-admin</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/Users/llm-admin/ollama.err</string>
    <key>StandardOutPath</key>
    <string>/Users/llm-admin/ollama.log</string>
</dict>
</plist>
EOF'

# 2. Open WebUIデーモンのplist作成 (★WorkingDirectoryを追加した修正版)
sudo sh -c 'cat > /Library/LaunchDaemons/com.openwebui.server.plist << "EOF"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.openwebui.server</string>
    <key>WorkingDirectory</key>
    <string>/Users/llm-admin/OpenWebUI_Data</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/llm-admin/.local/bin/open-webui</string>
        <string>serve</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
        <key>OLLAMA_BASE_URL</key>
        <string>http://127.0.0.1:11434</string>
        <key>DATA_DIR</key>
        <string>/Users/llm-admin/OpenWebUI_Data</string>
        <key>HOST</key>
        <string>0.0.0.0</string>
        <key>PORT</key>
        <string>8080</string>
        <key>PATH</key>
        <string>/Users/llm-admin/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
    <key>UserName</key>
    <string>llm-admin</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/Users/llm-admin/openwebui.err</string>
    <key>StandardOutPath</key>
    <string>/Users/llm-admin/openwebui.log</string>
</dict>
</plist>
EOF'

# 3. 権限設定とデーモンの登録
sudo chown root:wheel /Library/LaunchDaemons/com.ollama.server.plist
sudo chown root:wheel /Library/LaunchDaemons/com.openwebui.server.plist

sudo launchctl bootstrap system /Library/LaunchDaemons/com.ollama.server.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.openwebui.server.plist

これでエラーの根本原因が完全に排除され、鉄壁の自動起動システムが完成します。 プレフライトでブラウザにアクセスできるか確認後、上記の修正版Step 5を実行して、最後の【Step 6: モデルの導入(ダウンロード)】 へお進みください!

画像のご提示ありがとうございます。完全に理解しました。 またしても同じ「ルートディレクトリ(/)への書き込みエラー」ですね。これはあなたの操作ミスではなく、macOSのデーモン(LaunchDaemons)特有の非常に厄介な仕様が原因です。

なぜ同じエラーが出たのか?

先ほど WorkingDirectory(作業フォルダ)を指定して対策しましたが、macOSの LaunchDaemons はセキュリティが厳しすぎるあまり、「環境変数 $HOME(ホームディレクトリの場所)」をデーモンに教えてあげないと、Pythonが「自分の家はルート(/)だ」と勘違いしてしまうという仕様があります。 そのため、Open WebUIが「秘密鍵(.webui_secret_key)を自分の家(/)に作ろう!」として、OSに怒られて自爆していました。

解決手順:環境変数 HOME と 秘密鍵 の明示的付与

これを完封するため、設定ファイルに「家は /Users/llm-admin だよ」という指定と、いっそのこと「秘密鍵はこれを使って(新しく作らないで)」という指定(WEBUI_SECRET_KEY)を直接埋め込みます。

現在のターミナルに、以下の手順を順番にコピペして実行してください。

1. エラーを起こしているデーモンを止める

Bash

sudo launchctl bootout system /Library/LaunchDaemons/com.openwebui.server.plist 2>/dev/null

2. 完璧に修正した設定ファイルで上書きする(1行コピペ) ※長文ですが、そのまま一気にコピーしてペーストしてください。

Bash

sudo sh -c 'echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"><plist version=\"1.0\"><dict><key>Label</key><string>com.openwebui.server</string><key>WorkingDirectory</key><string>/Users/llm-admin/OpenWebUI_Data</string><key>ProgramArguments</key><array><string>/Users/llm-admin/.local/bin/open-webui</string><string>serve</string></array><key>EnvironmentVariables</key><dict><key>HOME</key><string>/Users/llm-admin</string><key>WEBUI_SECRET_KEY</key><string>llm_admin_secret_key_2026</string><key>OLLAMA_BASE_URL</key><string>http://127.0.0.1:11434</string><key>DATA_DIR</key><string>/Users/llm-admin/OpenWebUI_Data</string><key>HOST</key><string>0.0.0.0</string><key>PORT</key><string>8080</string><key>PATH</key><string>/Users/llm-admin/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string></dict><key>UserName</key><string>llm-admin</string><key>KeepAlive</key><true/><key>RunAtLoad</key><true/><key>StandardErrorPath</key><string>/Users/llm-admin/openwebui.err</string><key>StandardOutPath</key><string>/Users/llm-admin/openwebui.log</string></dict></plist>" > /Library/LaunchDaemons/com.openwebui.server.plist'

3. 権限を整えて、再登録(起動)する

Bash

sudo chown root:wheel /Library/LaunchDaemons/com.openwebui.server.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.openwebui.server.plist

これで、Pythonが迷子になって自爆する可能性を100%潰しました。 登録コマンドを実行してから 10秒ほど待って、再度ブラウザで http://192.168.2.100:8080 にアクセスしてみてください。

いかがでしょうか? 今度こそログイン画面が表示されるはずです!


4. 【フェーズ4〜5】巨大モデルと「依存関係エラー」の回避

【フェーズ4】巨大モデルDLのタイムアウト

WebUI画面からのダウンロードは不安定なため、SSHから screen(仮想端末)を立ち上げ、直接 ollama pull コマンドで確実にバックグラウンド処理させる運用へ変更しました。

【フェーズ5】Open WebUIのアップデートと依存関係の矛盾

uv を用いて最新版へ上げようとした際、ddgs 等のライブラリに起因する依存関係が解決不能な状態(いわゆる broken release)に遭遇しました。

これは環境側の問題ではなく、リリース時点のパッケージ構成に矛盾がある状態です。無理に進めず、安定バージョンへフォールバックすることでシステムの安定動作を確保しました。


5. 【フェーズ6〜7】推論の実行とメモリの「ところてん」パージ

【フェーズ6】推論の実行とメモリの大渋滞

26GBの領域を使い巨大モデルを切り替えていると、メモリが渋滞を起こしフリーズ。

一番軽いモデルを一度呼び出して短い挨拶を送ることで、メモリ領域を「ところてん式」にパージ(強制解放)する運用ルールを確立しました。

【フェーズ7】モニタリングとSSHの警告

asitop で監視しようと標準ターミナルからSSHを叩いた瞬間、REMOTE HOST IDENTIFICATION HAS CHANGED! の警告。OS再インストールによる暗号鍵の変更が原因でした。
ssh-keygen -R で古い鍵を消去し、ついに最大26GBのメモリをフル活用する様子を確認。すべての苦労が報われました。


6. エラー解決の新常識:スクショ一発で解決する安心感

今回の構築で心強かったのが、AIの視覚解析能力です。

エラーが出たら、ターミナルの画面をスクリーンショットしてAIに投げるだけ。

AIが瞬時に「所有権がrootになっています」「依存バージョンが矛盾しています」と原因を特定してくれました。
この「スクショ解決術」のおかげで、隣にシニアエンジニアがいるような安心感で作業を進めることができました。


メリット・デメリット比較(完全ヘッドレス・AIサーバー構成)

メリットデメリット
圧倒的メモリコスパ: 32GB中26GBを推論に回せる驚異の効率。構築難易度: GUIの罠や環境変数の指定など、深い知識が必要。
完全自動復帰: デーモン化により、再起動後も勝手に稼働。メモリ管理の癖: モデル切り替え時の「パージ運用」が必要。

まとめ:これこそがMac mini M4構築の「参考書」

M4 Mac mini(32GB)を最強のAIサーバーにするまでの3日間。

正直なところ、ネットで情報を調べてもそれが正しいのかもわからず、泥沼にはまること必須でした。
もし、AIの弱点を理解して制御するプロンプトを作らず、独力でこの迷宮を彷徨っていたら、一体何度OSを再インストールしていたか分かりません。

しかし、この記録にある手順と、後日公開する「真のプロンプト」さえあれば、皆さんは私の踏み抜いた地雷をすべて回避できます。
この全記録が、これからMac miniでローカルLLMの限界に挑む皆さんの「最強の参考書」になれば幸いです。

今後は顛末のまとめとインストールしたLLMモデルがどの程度の速度で動くのかベンチマークの記事を予定しています。

さあ、最大26GBの翼を手に入れたあなたも、自分だけの最強AIサーバーを構築してみませんか?

「本記事の内容は筆者の環境での結果であり、設定変更は自己責任で行ってください」

👉シリーズまとめ記事はこちら

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

目次