Hanish Rao’s Garden
Notes/guide

🌿Self-hosting 9router - one endpoint for every LLM provider

tools#homelab

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 localhost or your tailnet), and if you ever expose it, put it behind forward-auth and set REQUIRE_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-data

Minimal .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 endpoint

docker 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.