Setup for a MacBook Pro M4 Pro (24GB) with models stored on the external drive /Volumes/ROG_PRO.
Verified on this machine: gpt-oss:20b loads from the drive and generates at ~52 tok/s (Ollama 0.40.14).
brew install ollama # CLI
Check: ollama -v
Models live in OLLAMA_MODELS. Default is ~/.ollama/models.
mkdir -p /Volumes/ROG_PRO/ollama/models
touch /Volumes/ROG_PRO/ollama/models/.t && rm /Volumes/ROG_PRO/ollama/models/.t # writable?
If not writable: Finder β drive β Cmd+I β turn off "Ignore ownership". NTFS drives are read-only on macOS; use APFS.
| Setup | Command |
|---|---|
Terminal ( ollama serve ) |
echo 'export OLLAMA_MODELS=/Volumes/ROG_PRO/ollama/models' >> ~/.zshrc && source ~/.zshrc |
| Menu bar app (until reboot) | launchctl setenv OLLAMA_MODELS /Volumes/ROG_PRO/ollama/models , then quit and reopen the app |
| Symlink (works everywhere) | mv ~/.ollama/models /Volumes/ROG_PRO/ollama/ ; ln -sfn /Volumes/ROG_PRO/ollama/models ~/.ollama/models |
Persistent menu-bar setting: create ~/Library/LaunchAgents/ollama.models.plist:
<?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>ollama.models</string>
<key>ProgramArguments</key><array>
<string>/bin/launchctl</string><string>setenv</string>
<string>OLLAMA_MODELS</string><string>/Volumes/ROG_PRO/ollama/models</string>
</array>
<key>RunAtLoad</key><true/>
</dict></plist>
Load it: launchctl load ~/Library/LaunchAgents/ollama.models.plist
- "address already in use" on
ollama serve: an instance is already running (menu bar app or brew service) and ignores your env var. Stop it first:
pkill -f ollama; brew services stop ollama 2>/dev/null; lsof -i :11434 # should print nothing
- Drive unplugged : Ollama can't see your models or creates an empty folder. Mount the drive before starting it.
- macOS may ask for Removable Volumes / Full Disk Access for Ollama. Allow it.
OLLAMA_MODELS=/Volumes/ROG_PRO/ollama/models ollama serve
Leave it running; use a second terminal for everything else. Server: http://127.0.0.1:11434.
Useful server variables:
| Variable | Purpose | Example |
|---|---|---|
OLLAMA_MODELS |
Model storage path | /Volumes/ROG_PRO/ollama/models |
OLLAMA_CONTEXT_LENGTH |
Default context window (default 4096) | 32768 |
OLLAMA_KEEP_ALIVE |
How long a model stays in RAM (default 5m) | 30m |
OLLAMA_MAX_LOADED_MODELS |
Concurrent models | 1 |
OLLAMA_HOST |
Bind address | 127.0.0.1:11434 |
ollama pull gpt-oss:20b # download
ollama list # installed models
ollama run gpt-oss:20b # interactive chat (/bye to exit)
ollama run gpt-oss:20b "text" # one-shot
ollama ps # loaded models
ollama stop gpt-oss:20b # unload from RAM
ollama show gpt-oss:20b # details
ollama cp a b # copy/rename
ollama rm gpt-oss:20b # delete (frees drive space)
Verify storage: ls /Volumes/ROG_PRO/ollama/models/blobs and du -sh /Volumes/ROG_PRO/ollama/models.
Budget about 17β20GB for the model. Q4_K_M costs ~0.6 GB per billion parameters. Speeds below are third-party estimates (modelfit.io), not benchmarks. Only gpt-oss:20b has been measured here (~52 tok/s).
| Model | Size | Est. speed | Use |
|---|---|---|---|
gpt-oss:20b |
~14 GB | ~53 tok/s | Daily driver, reasoning, coding |
qwen3.5:9b |
~7 GB | ~43 tok/s | Multimodal, light on RAM |
gemma4:26b |
~16 GB | ~53 tok/s | Text + images |
lfm2:24b-a2b |
~14 GB | ~92 tok/s | Agents / tool calling |
qwen3.8:27b |
~17.5 GB | ~14 tok/s | Max quality, tight fit |
ministral-3:14b |
~9 GB | ~24 tok/s | Multimodal 14B |
Coding: gpt-oss:20b is the easy choice in Ollama. JetBrains Mellum2.1 12B-A2.5B Thinking is coding-specific but has no Ollama tag (see Β§8).
Avoid: 70B models (~43GB, won't fit), Q8 above 14B, 32B at Q4 (swaps).
Docker:
docker run -d -p 3000:8080 \
-e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
-v open-webui:/app/backend/data \
--name open-webui --restart always \
ghcr.io/open-webui/open-webui:main
Without Docker (Python 3.11): pip install open-webui && open-webui serve (port 8080).
Open http://localhost:3000, create the local admin account, pick the model. If none appear: Settings β Connections β Ollama URL http://host.docker.internal:11434 (Docker) or http://localhost:11434.
Open WebUI's own data (chats, settings) is on the internal disk, not ROG_PRO.
brew install sst/tap/opencode # or: npm i -g opencode-ai
Raise the context first. The 4096 default is too small for agent prompts:
OLLAMA_CONTEXT_LENGTH=32768 OLLAMA_MODELS=/Volumes/ROG_PRO/ollama/models ollama serve
32K fits comfortably with gpt-oss:20b. Drop to 16K if memory gets tight.
~/.config/opencode/opencode.json (global) or opencode.json in the project:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ollama": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama (local)",
"options": { "baseURL": "http://localhost:11434/v1" },
"models": { "gpt-oss:20b": { "name": "GPT-OSS 20B" } }
}
}
}
Run opencode in a project directory, then /models and choose Ollama (local).
A 20B local model handles small edits and questions. It is weaker than hosted models at long multi-step agent work, so review its changes.
- LM Studio : My Models tab β change models directory to the drive.
- llama.cpp (e.g. Mellum2.1):
LLAMA_CACHE=/Volumes/ROG_PRO/llama llama-server -hf JetBrains/Mellum2.1-12B-A2.5B-Thinking-GGUF:Q4_K_M - Hugging Face / MLX :
export HF_HOME=/Volumes/ROG_PRO/hf
curl http://localhost:11434/api/chat -d '{"model":"gpt-oss:20b","messages":[{"role":"user","content":"hi"}],"stream":false}'
curl http://localhost:11434/v1/chat/completions -H 'Content-Type: application/json' \
-d '{"model":"gpt-oss:20b","messages":[{"role":"user","content":"hi"}]}'
| Symptom | Fix |
|---|---|
| Models missing after reboot | OLLAMA_MODELS not persisted, or drive not mounted. See Β§2. |
Pull writes to ~/.ollama |
Server started without the env var. Restart per Β§2 gotchas. |
| Slow or swapping | Model too big, or too many apps open. Use a smaller model, lower context, ollama stop . |
| Agent forgets or truncates | Context still 4096. Set OLLAMA_CONTEXT_LENGTH . |
| Open WebUI sees no models | Wrong Ollama URL. Use host.docker.internal from Docker. |
| Slow first response | Initial model load (~18s here). Raise OLLAMA_KEEP_ALIVE . |