oMLX

oMLX models on an external SSD, backed up with Kopia

October 6, 2026 · 5 min read

The mem0 post mentioned that oMLX serves chat and embedding models on this machine. What it left out: none of those models live on the internal disk. The whole model library sits on an external SSD, and a second drive takes hourly backups of it. This post covers both halves.

Why an external SSD

The Mac mini doing the serving has a 1 TB internal disk, and MLX models add up fast — a single 27B 4-bit model is ~15 GB. My library is at 36 GB and growing:

/Volumes/Mate_Mini/omlx/base/models/
├── Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed
└── mlx-community/
    ├── bge-m3-mlx-8bit
    ├── gemma-4-e2b-it-4bit
    └── Kokoro-82M-bf16

Model loading from a Thunderbolt-attached SSD is effectively indistinguishable from internal storage — the weights stream into unified memory once, then inference is compute-bound anyway. What the internal disk gains (free space, less wear from multi-GB downloads) outweighs a load time I never notice.

Pointing oMLX at the SSD

oMLX keeps everything — models, HF cache, logs, settings, usage stats — under one base path. Relocating it is a single setting in the app, which persists the choice to a bootstrap file:

$ cat ~/Library/Application\ Support/oMLX/base-path
/Volumes/Mate_Mini/omlx/base

The Homebrew-installed omlx CLI is just a shim that reads that file and exports it before handing off to the real binary inside the app bundle:

BOOTSTRAP="$HOME/Library/Application Support/oMLX/base-path"
if [ -r "$BOOTSTRAP" ]; then
    IFS= read -r OMLX_BASE_PATH < "$BOOTSTRAP" || OMLX_BASE_PATH=""
    if [ -n "$OMLX_BASE_PATH" ]; then
        export OMLX_BASE_PATH
    fi
fi
exec '/Applications/oMLX.app/Contents/MacOS/omlx-cli' "$@"

The one file that matters inside the base path is settings.json, which records the model directory explicitly:

{
  "model": {
    "model_dirs": ["/Volumes/Mate_Mini/omlx/base/models"]
  }
}

Restart the server (omlx restart) and it serves from the SSD. launch_at_login is on, and on a desktop mini the drive is always attached — if yours isn’t, see the gotchas below.

Why back up re-downloadable files at all

Model weights are public — you can always re-download them. But 36 GB over a slow or metered connection is hours of waiting, and the directory is more than weights: settings.json, per-model tuning in model_settings.json, hf_download_tasks.json, and a usage.sqlite3 with serving statistics are not re-downloadable. The goal isn’t disaster-proofing Hugging Face’s catalog; it’s making “restore directory, restart server” a five-minute operation.

Kopia does the backups

Kopia is a deduplicating, encrypted, content-addressed backup tool — think restic with a friendlier scheduler. I run KopiaUI on the mini, with the repository on a second external drive (a 9 TB spinning disk), because a backup on the same device as the source is a copy, not a backup:

Source:     /Volumes/Mate_Mini/omlx          (3 TB SSD)
Repository: /Volumes/Getea/VM-backups/mate_mini_backups   (9 TB HDD)

The repository is password-encrypted at rest, as every Kopia repository is. It also holds three other directories off the same SSD (VMs, voice models, container data) — Kopia deduplicates across all of them.

The policy for the oMLX directory, as configured in the UI:

The CLI equivalent, using the binary bundled inside KopiaUI:

KOPIA="/Applications/KopiaUI.app/Contents/Resources/server/kopia"

"$KOPIA" policy set /Volumes/Mate_Mini/omlx \
  --snapshot-interval=1h \
  --keep-latest=5 --keep-hourly=24 --keep-daily=12 \
  --keep-weekly=4 --keep-monthly=24 --keep-annual=3 \
  --compression=zstd-fastest

Model libraries are Kopia’s best case

Snapshots of a model directory are nearly free, because model weights are immutable: once bge-m3-mlx-8bit is downloaded, those gigabytes never change again. Kopia chunks and content-addresses everything, so after the first snapshot, hourly runs upload almost nothing. The actual snapshot list shows it:

2026-10-04 07:01  38.4 GB  files:1091  (daily-4)     ← Qwen3.8-27B landed
2026-10-04 23:02  38.4 GB  files:1099  (hourly-19..24, daily-3, weekly-2)
   + 7 identical snapshots until 2026-10-05 19:02
2026-10-05 20:02  38.4 GB  files:1099  (latest-1..5, hourly-1..18, ...)
   + 17 identical snapshots until 2026-10-06 13:00

Thirty snapshots deep, and the “identical” runs cost a few KB of metadata each. The jump from 13.1 GB to 38.4 GB in early October was the 27B model arriving — one incremental upload of the new blobs, then back to silence. This is the ideal backup profile: aggressive schedule, generous retention, negligible incremental cost.

Compression choice deserves a note: 4-bit quantized safetensors are already dense, so no compressor will shrink them meaningfully. zstd-fastest is cheap insurance for the JSON/SQLite/text files in the directory without burning CPU on the weights.

Gotchas

Checking it works

KOPIA="/Applications/KopiaUI.app/Contents/Resources/server/kopia"
"$KOPIA" snapshot list /Volumes/Mate_Mini/omlx \
  --config-file ~/Library/Application\ Support/kopia/repository.config

And the restore drill that actually matters: mount a snapshot (kopia mount), or kopia snapshot restore <id> /tmp/omlx-test, then point oMLX’s base path at the restored directory and confirm the models load. A backup you’ve never restored from is a hypothesis.

← Back to all posts