🌿Self-hosting 9router - one endpoint for every LLM provider
9router is a self-hosted LLM gateway. It exposes a single OpenAI/Anthropic-compatible endpoint and routes your requests to 40+ backend providers - with automatic fallback when one is rate-limited or down, and token compression to stretch your quota. You point your coding tools (Claude Code, Cursor, Cline, Copilot, Codex…) at one URL and switch providers/models from a dashboard instead of reconfiguring each tool.
[!warning] This holds the keys to your AI accounts 9router stores your provider API keys and OAuth tokens so it can route on your behalf. Treat it like a secret store: keep it local (bound to
localhostor your tailnet), and if you ever expose it, put it behind forward-auth and setREQUIRE_API_KEY=true. Also: routing through providers' free tiers can brush against their terms of service - worth a glance before you lean on it.
Run it - docker-compose.yml
The official compose runs 9router plus a headroom sidecar (the token-compression
service):
services:
9router:
image: decolua/9router:latest
container_name: 9router
restart: always
ports:
- "20128:20128"
volumes:
- 9router-data:/app/data
env_file:
- .env
environment:
DATA_DIR: /app/data
PORT: "20128"
HOSTNAME: "0.0.0.0"
NODE_ENV: production
HEADROOM_URL: http://headroom:8787
depends_on:
- headroom
headroom:
image: ghcr.io/chopratejas/headroom:latest
container_name: headroom
restart: always
ports:
- "8787:8787"
volumes:
9router-data:
name: 9router-dataMinimal .env (change the two secrets - the defaults are weak):
JWT_SECRET=change-me-to-a-long-random-secret # openssl rand -hex 32
INITIAL_PASSWORD=change-me # first dashboard login
DATA_DIR=/app/data
PORT=20128
NODE_ENV=production
REQUIRE_API_KEY=true # require a key on the proxy endpointdocker compose up -d, then open the dashboard at http://localhost:20128 and
log in with INITIAL_PASSWORD.
The different ways to connect a provider
This is the point of 9router - it supports several auth patterns, so "any LLM provider" really means any of these. All are done in Dashboard → Providers:
| Method | Providers it fits | How |
|---|---|---|
| API key | OpenAI, Anthropic, Gemini, DeepSeek, Groq, GLM, MiniMax, Kimi, … | Add provider → paste the key. The classic path - any provider that issues an API key. |
| OAuth login | Claude Code, Codex, GitHub Copilot, Cursor, Antigravity | Connect → sign in; 9router stores and auto-refreshes the token (uses your existing subscription). |
| No-auth passthrough | OpenCode Free | Connect → it auto-fetches available models, no credentials. |
| GCP service account | Vertex AI (Gemini) | Upload the service-account JSON; good for the $300 free-trial credits. |
| Free OAuth | Kiro AI | Sign in via AWS Builder ID / Google / GitHub. |
Add as many as you like - 9router will fall back across them in the order you set, so a rate-limit on one provider transparently spills to the next.
Point your tools at it
Every tool uses 9router's OpenAI-compatible endpoint. Grab an API key from the dashboard, then:
- Base URL:
http://localhost:20128/v1 - API key: (from dashboard)
- Model:
{provider}/{model}- e.g.cc/claude-opus-4-7, or a saved combo
Claude Code (~/.claude/config.json):
{
"anthropic_api_base": "http://localhost:20128/v1",
"anthropic_api_key": "your-9router-key"
}Cursor / Cline / Continue - pick OpenAI-Compatible, set the base URL + key
above, and the {provider}/{model} model string.
Related
Linked from
- 🌿 Tools
Practical guides for the software I reach for when something breaks the battletested, often…