Blog · AI
Run Ollama on a Mac mini server
Install Ollama on a Mac mini, pick a model that fits 16GB or 24GB, run it as a service, expose the OpenAI-compatible API and keep it secure.

A Mac mini makes a quiet, capable private LLM endpoint. This guide shows how to run Ollama on a Mac mini server, from installation to a secured, OpenAI-compatible API your apps can call.
What you need
- A Mac mini with Apple silicon and at least 16GB of unified memory. 24GB gives you noticeably more room.
- Admin access to a terminal, locally or over SSH.
- Enough free disk for models. A 7–8B model at 4-bit is roughly 4–5GB on disk; a 14B model is roughly 8–10GB.
Unified memory is the reason this works well. The GPU reads model weights from the same memory pool as the CPU, so there is no separate VRAM limit to fit inside. By default macOS lets the GPU use most, roughly two-thirds to three-quarters, of that memory.
Step 1: install Ollama
There are two common ways to install on macOS. On a server you manage over SSH, Homebrew is the easiest:
brew install ollama
ollama --version
Alternatively, download the macOS app from ollama.com. The app runs a menu bar item and starts the server when you log in. That suits a desktop. For a headless server, the Homebrew binary plus launchd, shown below, is easier to control.
Start the server in the foreground once to check it works:
ollama serve
In another terminal, confirm it answers on its default port, 11434:
curl http://127.0.0.1:11434/api/version
Step 2: pull a model sized for your memory
The rule of thumb: a 4-bit quantised model needs roughly 0.5–0.7GB of memory per billion parameters, plus room for the context window. Apply that to the GPU's share of memory, not the full total.
| Mac mini memory | Comfortable model size (4-bit) | Example pulls |
|---|---|---|
| 16GB | 7–8B | llama3.1:8b, qwen2.5:7b |
| 24GB | up to roughly 14B | qwen2.5:14b, phi4:14b |
ollama pull llama3.1:8b
ollama run llama3.1:8b "Summarise what a launchd agent is in two sentences."
On 16GB, a 14B model may load, but it leaves little room for context and for the rest of macOS, so it tends to swap and slow down. Stay inside the comfortable range for a server that runs all day. For a fuller explanation of the memory maths, see local LLMs on Apple silicon: memory.
Step 3: choose a quantisation
Most Ollama model tags default to a 4-bit quantisation such as Q4_K_M. That is a good default. Other tags let you trade memory for quality:
- Q4_K_M: the usual balance. Small, fast and good enough for chat, summarising and coding help.
- Q5_K_M / Q6_K: a little larger, slightly closer to full quality. Worth it when you have spare memory.
- Q8_0: roughly double the 4-bit size. Useful for a small model on a larger machine, such as an 8B model on 24GB.
ollama pull llama3.1:8b-instruct-q8_0
ollama list
A practical rule: a bigger model at 4-bit usually beats a smaller model at 8-bit, as long as it fits comfortably. Check the tags list for each model on ollama.com before pulling, as available variants differ per model.
Step 4: run Ollama as a background service
The quick way: brew services
brew services start ollama
brew services list
This registers a launchd agent that starts Ollama at login and restarts it if it exits. It listens on localhost only, which is the safe default.
The configurable way: your own launchd plist
To set environment variables such as the bind address or keep-alive, write your own agent. Stop the brew service first with brew services stop ollama, then save this as ~/Library/LaunchAgents/com.example.ollama.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>com.example.ollama</string>
<key>ProgramArguments</key>
<array><string>/opt/homebrew/bin/ollama</string><string>serve</string></array>
<key>EnvironmentVariables</key>
<dict>
<key>OLLAMA_HOST</key><string>127.0.0.1:11434</string>
<key>OLLAMA_KEEP_ALIVE</key><string>24h</string>
</dict>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardErrorPath</key><string>/tmp/ollama.err.log</string>
</dict></plist>
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.ollama.plist
launchctl print gui/$(id -u)/com.example.ollama | head
A LaunchAgent runs while that user is logged in. On a remote Mac that stays logged in, that is fine. If you need Ollama to start at boot before anyone logs in, use a LaunchDaemon in /Library/LaunchDaemons with a UserName key and set HOME in its environment so models are stored in the right place.
Step 5: OLLAMA_HOST and keep-alive
OLLAMA_HOST sets the address and port the server binds to. 127.0.0.1:11434 accepts only local connections. 0.0.0.0:11434 accepts connections on every interface, and Ollama has no built-in authentication, so only bind to all interfaces behind a firewall or proxy you control. Keeping it on localhost and using a tunnel or proxy, as below, is safer.
OLLAMA_KEEP_ALIVE controls how long a model stays in memory after its last request. The default is a few minutes, after which the next request pays a load delay. On a dedicated server, a longer value such as 24h, or -1 for indefinitely, keeps responses quick. You can also set it per request with a keep_alive field. Check what is loaded with:
ollama ps
Two related settings: OLLAMA_CONTEXT_LENGTH raises the default context window, and OLLAMA_NUM_PARALLEL lets one model serve several requests at once. Both use more memory, so raise them gradually and watch ollama ps.
Step 6: use the OpenAI-compatible endpoint
Ollama exposes an OpenAI-compatible API under /v1, so many existing tools work by changing the base URL.
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "llama3.1:8b",
"messages": [{"role": "user", "content": "Write a haiku about build servers."}]}'
With the official OpenAI Python client:
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11434/v1", api_key="ollama")
r = client.chat.completions.create(
model="llama3.1:8b",
messages=[{"role": "user", "content": "Hello"}],
)
print(r.choices[0].message.content)
The API key is required by the client library but ignored by Ollama. That is exactly why access control has to happen in front of it.
Step 7: secure remote access
Option A: SSH tunnel
The simplest secure setup. Leave Ollama on localhost and forward the port from your laptop:
ssh -N -L 11434:127.0.0.1:11434 admin@your-mac-mini
Your local tools now call http://127.0.0.1:11434/v1 and traffic is encrypted over SSH. This suits one developer or a small team with SSH keys.
Option B: reverse proxy with authentication
For apps or several users, put a reverse proxy with TLS and authentication in front. A minimal Caddy example, after generating a hash with caddy hash-password:
llm.example.com {
basic_auth {
apiuser $2a$14$REPLACE_WITH_HASH
}
reverse_proxy 127.0.0.1:11434
}
Caddy obtains a certificate automatically if the domain points at the machine and ports 80 and 443 are reachable. Whether a rented Mac can accept inbound public traffic depends on its network setup, so if you need that, tell us what you need. For larger deployments, consider per-user API keys at the proxy and rate limits.
Running it on a rented Mac mini
Everything above works on a Hatmac machine because each one is a dedicated physical Mac with a full terminal, not a shared VM. You install Ollama yourself and can enable SSH as one of your access methods. The 24GB Mac mini M6 is a good fit for 14B-class models; the 16GB Mac mini M4 handles 7–8B models from $119/mo on a 12-month term. See the Mac mini LLM server page for more, or Mac Studio for local LLMs if you need larger models.
FAQ
Can a 16GB Mac mini run Ollama as a server?
Yes. It runs 7–8B models at 4-bit comfortably. For 14B-class models, 24GB gives more room for context and the system.
Is it safe to set OLLAMA_HOST to 0.0.0.0?
Only behind a firewall or authenticated proxy. Ollama has no built-in authentication, so anyone who can reach the port can use it.
Do OpenAI client libraries work with Ollama?
Yes. Point the base URL at /v1 on your server and pass any placeholder API key.