ferrumox/fox

By ferrumox

Updated about 23 hours ago

High-performance LLM inference engine — drop-in replacement for Ollama and vLLM

Image
Security
Machine learning & AI
Developer tools
0

1.4K

ferrumox/fox repository overview

fox

The fastest local LLM server. Drop-in replacement for Ollama.

CI License: MIT OR Apache-2.0 Version Rust GitHub Stars

Sponsor

Fox is free forever. No asterisks. No "free for now." No pivot to paid. MIT licensed, always.


Try it in 30 seconds

# Linux / macOS
curl -fsSL https://github.com/ferrumox/fox/releases/latest/download/install.sh | sh

# Windows
irm https://raw.githubusercontent.com/ferrumox/fox/main/install.ps1 | iex
# Pull a model and start
fox pull llama3.2
fox serve

# Ask something (OpenAI-compatible)
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"llama3.2","messages":[{"role":"user","content":"Hello!"}],"stream":true}'

# If you already use Ollama — just change the port from 11434 to 8080. That's it.

Performance vs Ollama

RTX 4060 · Llama-3.2-3B-Instruct-Q4_K_M · 4 concurrent clients · 50 requests:

MetricfoxOllamaImprovement
First token (P50)87ms310ms+72%
First token (P95)134ms480ms+72%
Response time (P50)412ms890ms+54%
Response time (P95)823ms1740ms+53%
Throughput312 t/s148 t/s+111%

Reproduce: ./scripts/benchmark.sh gemma3 4 50


Why is fox faster?

Conversations get faster over time. Fox remembers the context it already processed — system prompts and previous messages aren't re-read from scratch on every turn. Ollama does. In a long conversation, fox skips up to 75% of that work from the second message onward, which is why the first token arrives much sooner.

Multiple users don't block each other. Fox processes several requests at the same time instead of waiting for one to finish before starting the next. A long generation for one user doesn't delay a quick question from another.


Works with every tool you already use

No code changes needed — just change the base URL to http://localhost:8080.

Client / ToolProtocolStatus
Open WebUIOllama✓ Works out of the box
Continue.devOllama✓ Works out of the box
LangChainOpenAI✓ Works out of the box
LlamaIndexOpenAI✓ Works out of the box
Cursor / Copilot ChatOpenAI✓ Works out of the box
ollama CLIOllama✓ Works out of the box
openai Python SDKOpenAI✓ Works out of the box
Python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8080/v1", api_key="sk-local")

resp = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Say hi in 5 words."}],
)
print(resp.choices[0].message.content)
Node.js
import OpenAI from "openai";

const openai = new OpenAI({ baseURL: "http://localhost:8080/v1", apiKey: "sk-local" });

const resp = await openai.chat.completions.create({
  model: "llama3.2",
  messages: [{ role: "user", content: "Say hi in 5 words." }],
});
console.log(resp.choices[0].message?.content);
IDE configuration

VSCode / Cursor

{ "github.copilot.advanced": { "serverUrl": "http://localhost:8080" } }

Continue.dev (~/.continue/config.json)

{
  "models": [{
    "title": "fox (local)",
    "provider": "openai",
    "model": "llama3.2",
    "apiBase": "http://localhost:8080/v1"
  }]
}

See examples/ for more integration guides.


GPU support

Fox detects CUDA, Metal, and Vulkan at runtime — one binary runs on any hardware.

PlatformGPU backendsAuto-detects
Linux x86_64CUDA + Vulkan
Windows x86_64CUDA + Vulkan
macOS Apple SiliconMetal
macOS IntelCPU only
Linux ARM64CPU only

Auto-detection priority: CUDA → Vulkan → Metal → CPU. Override with --gpu-backend cuda|vulkan|cpu.


Installation

Linux / macOS
curl -fsSL https://github.com/ferrumox/fox/releases/latest/download/install.sh | sh

Or download a binary directly:

# Linux x86_64
curl -L https://github.com/ferrumox/fox/releases/latest/download/fox-linux-x86_64 -o fox && chmod +x fox

# macOS Apple Silicon
curl -L https://github.com/ferrumox/fox/releases/latest/download/fox-macos-arm64 -o fox && chmod +x fox

# macOS Intel
curl -L https://github.com/ferrumox/fox/releases/latest/download/fox-macos-x86_64 -o fox && chmod +x fox
Windows
irm https://raw.githubusercontent.com/ferrumox/fox/main/install.ps1 | iex

Or download fox-windows-x86_64.exe directly.

Build from source
git clone --recurse-submodules https://github.com/ferrumox/fox
cd fox
cargo build --release

GPU backend is detected at runtime — no recompilation needed when switching between CPU, CUDA, and Metal.

Docker
docker run -p 8080:8080 \
  -v ~/.cache/ferrumox/models:/root/.cache/ferrumox/models \
  ferrumox/fox serve

# Or with docker compose
docker compose up

Usage

# Search HuggingFace for GGUF models
fox search gemma
fox search qwen coder --limit 5

# Pull a model
fox pull llama3.2            # top result, balanced quantization
fox pull gemma3:12b          # specific size
fox pull gemma3:12b-q4       # specific quantization
fox pull bartowski/gemma-3-12b-it-GGUF  # specific HF repo

# Start the server
fox serve                    # lazy loading — no model needed upfront
fox serve --max-models 3     # keep up to 3 models loaded simultaneously

# Interactive REPL
fox run
fox run "Explain ownership in Rust"  # single-shot

# Manage models
fox list                     # list downloaded models
fox show llama3.2            # model info: architecture, quantization, size
fox ps                       # list currently loaded models

# Manage aliases
fox alias set llama3 Llama-3.2-3B-Instruct-Q4_K_M
fox alias list

# Benchmark
fox bench llama3.2
fox bench llama3.2 --runs 10

API endpoints

MethodPathDescription
POST/v1/chat/completionsChat completions — streaming + non-streaming (OpenAI)
POST/v1/completionsText completions (OpenAI)
POST/v1/embeddingsEmbeddings (OpenAI)
GET/v1/modelsList all models on disk
POST/api/chatChat — NDJSON streaming (Ollama)
POST/api/generateGenerate — NDJSON streaming (Ollama)
POST/api/embedEmbeddings (Ollama)
GET/api/tagsList models (Ollama)
GET/api/psList loaded models (Ollama)
POST/api/showModel metadata (Ollama)
DELETE/api/deleteRemove a model (Ollama)
POST/api/pullPull a model from HuggingFace (SSE)
GET/api/versionServer version — for Ollama client detection
GET/healthHealth + KV cache metrics
GET/metricsPrometheus scrape endpoint

Features

  • Runs any GGUF model (Llama, Mistral, Gemma, Qwen, DeepSeek, and more)
  • OpenAI-compatible API — works with any tool that supports OpenAI
  • Ollama-compatible API — works with any tool that supports Ollama
  • Multi-model serving — keep multiple models loaded, switch between them instantly
  • Lazy loading — no need to specify a model upfront; fox loads it on first request
  • Prefix caching — shared system prompts are processed once and reused across requests
  • Continuous batching — multiple concurrent users processed in parallel, not serialized
  • Function calling and structured JSON output (OpenAI spec)
  • Request cancellation — closing the connection immediately frees GPU memory
  • KV cache quantization--type-kv q8_0 or q4_0 cuts VRAM usage with minimal quality loss
  • API key authentication — optional FOX_API_KEY for access control
  • Prometheus metrics — latency, throughput, KV cache usage out of the box
  • Config file at ~/.config/ferrumox/config.toml
  • Aliases — short names instead of full model filenames
  • Docker and systemd support included

Configuration

All flags can also be set via environment variable or ~/.config/ferrumox/config.toml.

FlagEnvDefaultDescription
--model-pathFOX_MODEL_PATHGGUF model to pre-load (optional)
--portFOX_PORT8080Bind port
--hostFOX_HOST0.0.0.0Bind host
--max-modelsFOX_MAX_MODELS1Max models in memory simultaneously
--keep-alive-secsFOX_KEEP_ALIVE_SECS300Evict idle models after N seconds
--max-context-lenFOX_MAX_CONTEXT_LEN4096Context window size
--gpu-memory-fractionFOX_GPU_MEMORY_FRACTION0.85Fraction of GPU RAM for KV cache
--type-kvFOX_TYPE_KVf16KV cache precision: f16, q8_0, or q4_0
--max-batch-sizeFOX_MAX_BATCH_SIZE32Continuous batch size
--system-promptFOX_SYSTEM_PROMPTSystem prompt injected in every request
--api-keyFOX_API_KEYRequire Authorization: Bearer <key> on all requests
--hf-tokenHF_TOKENHuggingFace token for private repos
--alias-fileFOX_ALIAS_FILE~/.config/ferrumox/aliases.tomlShort name → model stem mapping
--json-logsFOX_JSON_LOGSfalseStructured JSON logs
Config file (~/.config/ferrumox/config.toml)
port = 8080
max_models = 3
keep_alive_secs = 300
system_prompt = "You are a helpful assistant."
Aliases (~/.config/ferrumox/aliases.toml)
[aliases]
"llama3"   = "Llama-3.2-3B-Instruct-Q4_K_M"
"mistral"  = "Mistral-7B-Instruct-v0.3-Q4_K_M"

Benchmark

# Compare fox vs Ollama side by side
./target/release/fox-bench \
  --url http://localhost:8080 \
  --compare-url http://localhost:11434 \
  --model llama3.2

# JSON output for CI
./target/release/fox-bench \
  --url http://localhost:8080 \
  --compare-url http://localhost:11434 \
  --model llama3.2 \
  --output json

# Reproducible benchmark (saves to benches/results.md)
./scripts/benchmark.sh llama3.2 4 50

Sample output:

┌─────────────────┬──────────────┬──────────────┬──────────┐
│ Metric          │     fox      │    ollama    │ Δ        │
├─────────────────┼──────────────┼──────────────┼──────────┤
│ TTFT P50        │          87ms│         310ms│ +72%     │
│ TTFT P95        │         134ms│         480ms│ +72%     │
│ Latency P50     │         412ms│         890ms│ +54%     │
│ Latency P95     │         823ms│        1740ms│ +53%     │
│ Latency P99     │        1204ms│        2600ms│ +54%     │
│ Throughput      │    312.4 t/s │    148.1 t/s │ +111%    │
└─────────────────┴──────────────┴──────────────┴──────────┘

Project structure

fox/
├── src/
│   ├── main.rs              # Entry point, config, signal handling
│   ├── metrics.rs           # Prometheus metrics registry
│   ├── model_registry.rs    # Multi-model registry with LRU eviction
│   ├── config.rs            # Config file loading
│   ├── registry.rs          # Model discovery helpers
│   ├── api/                 # REST API (OpenAI + Ollama compat)
│   │   ├── router.rs        # Axum router setup
│   │   ├── types.rs         # Request/response types
│   │   ├── auth.rs          # API key middleware
│   │   ├── error.rs         # Unified error types
│   │   ├── pull_handler.rs  # POST /api/pull SSE streaming
│   │   ├── v1/              # OpenAI-compat handlers
│   │   │   ├── chat.rs
│   │   │   ├── completions.rs
│   │   │   ├── embeddings.rs
│   │   │   └── models.rs
│   │   ├── ollama/          # Ollama-compat handlers
│   │   │   ├── chat.rs
│   │   │   ├── generate.rs
│   │   │   ├── embed.rs
│   │   │   └── management.rs
│   │   └── shared/          # Shared inference + streaming helpers
│   │       ├── inference.rs
│   │       ├── streaming.rs
│   │       └── digest.rs
│   ├── scheduler/           # Continuous batching + prefix cache
│   ├── kv_cache/            # PageTable, ref-counted block manager
│   ├── engine/              # Inference engine, sampling, output filtering
│   └── cli/                 # Subcommands: serve, run, pull, list, show, ps
├── examples/
│   ├── curl.sh              # curl examples for all API routes
│   ├── langchain.py         # LangChain integration
│   └── openwebui.md         # Open WebUI setup guide
├── scripts/
│   └── benchmark.sh         # Reproducible benchmark vs Ollama
├── benches/
│   └── results.md           # Benchmark results (generated)
├── vendor/llama.cpp/        # Git submodule
├── Dockerfile
├── docker-compose.yml
├── fox.service              # systemd unit
├── install.sh               # One-liner installer
├── Makefile
├── CHANGELOG.md
└── Cargo.toml

Make targets

make build           Compile release binaries (fox + fox-bench)
make run             Build and start the server
make dev             Start with RUST_LOG=debug
make test            Run unit tests
make check           Fast type-check (cargo check)
make bench           Run fox-bench against a running server
make docker          Build Docker image
make docker-run      Start via docker compose
make install-rust    Install Rust toolchain
make download-model  Download default model (Llama-3.2-3B Q4_K_M)

Requirements

BackendRequirement
CPUx86_64 or arm64, AVX2
CUDACUDA 12.x
MetalmacOS 13+, Apple Silicon
VulkanWindows x86_64, Vulkan SDK 1.3+

No runtime dependencies beyond GPU drivers — single static binary.


Community

To run tests:

FOX_SKIP_LLAMA=1 cargo test --all

Support the project

Fox is built and maintained by Manuel S. Lemos in his spare time. It's free forever — no paid tiers, no feature gating, no VC money.

If fox saves you time or replaces a paid API bill, consider sponsoring:

$5 / monthCoffee tier — eternal gratitude + sponsor badge
🐛 $25 / monthBug priority — your issues move to the front of the queue + name in SPONSORS.md
🏢 $100 / monthTeam supporter — your logo in the README + shoutout in every release
🚀 $500 / monthInfrastructure partner — direct line + input on the roadmap

❤️ GitHub Sponsors · ☕ Buy Me a Coffee

100% of sponsorships go toward keeping fox free and actively maintained.


License

Dual-licensed under MIT or Apache 2.0 — your choice.

Tag summary

Content type

Image

Digest

sha256:22b08d24c

Size

284.8 MB

Last updated

about 23 hours ago

docker pull ferrumox/fox