August 23, 2026

9Router and Standardizing LLM Endpoints

9Router consolidates multiple LLM providers behind one local OpenAI-compatible endpoint: central credentials, automatic fallback, and token savings, with security defaults that need tightening.

The AI clients on the homelab — Hermes, OpenCode, and a few others — talk to LLM providers over their own APIs. The friction shows once the provider count grows: OpenRouter, OpenAI, Anthropic, plus local models. Every tool stores its own credentials, each provider speaks a slightly different request format, and when one account hits a rate limit, work stops until the quota resets. 9Router addresses all three at once.

Why LLM endpoints need standardization

Without a gateway, switching providers means editing the config in every client one by one. With 9Router every client points at one local endpoint, and provider selection happens in a single place.

  • Central credentials: provider API keys are stored once in 9Router instead of scattered across tool configs.
  • Automatic fallback: provider order can be defined — cheap or free first, then fall back on error or rate limit.
  • One format for all: an OpenAI-compatible endpoint understood by almost every AI CLI and web app.

Architecture and how it works

The flow is simple: a client sends a request to http://localhost:20128/v1, 9Router translates the format, picks a provider according to the configured order, and forwards the request upstream.

  • Format translation: the client side always speaks OpenAI format; 9Router translates into the provider’s native format (OpenAI, Claude, Gemini, Cursor, down to Ollama). An OpenAI-only tool can still use Claude or Gemini models.
  • RTK token saver: tool results such as git diff, grep, and ls are compressed before they reach the LLM; the official claim is 20-40% input token savings per request, and it is on by default.
  • Quota tracking: the dashboard shows per-provider token usage and estimated cost. The cost figure is a savings tracker, not a bill from 9Router.
  • Prefixed model IDs: models are referenced as provider/model, e.g. kr/claude-sonnet-4.5, or simply by the name of a configured combo.

Deployment

9Router installs as a global Node.js package:

npm install --global 9router@latest

The daemon runs with IPv4-first DNS resolution on a custom port:

node --dns-result-order=ipv4first ~/.npm-global/bin/9router --skip-update -p 20128

Once running, open the dashboard at localhost:20128 to register provider API keys and build model combos. The OpenAI-compatible endpoint is active at /v1, and /api/health can be polled by monitoring tools for daemon liveness.

A container alternative is available via the decolua/9router image:

docker run -d --name 9router -p 20128:20128 \
  -v "$HOME/.9router:/app/data" -e DATA_DIR=/app/data \
  decolua/9router:latest

All state — configuration, the SQLite database, provider routes — lives in ~/.9router.

Security and operations

A few defaults are worth tightening from day one:

  • Initial password: if INITIAL_PASSWORD is unset, the first login password is the built-in 123456. Change it immediately.
  • Endpoint API key: REQUIRE_API_KEY defaults to false, so /v1/* is open without a Bearer token. Enable it unless the service is only exposed on localhost.
  • Auth cookie: behind an HTTPS reverse proxy, set AUTH_COOKIE_SECURE=true so the login cookie only travels over a secure connection.
  • JWT secret: auto-generated at ~/.9router/jwt-secret; override via the JWT_SECRET env var when consistency across instances is needed.

Backup and recovery

9Router’s data is a single SQLite file at ~/.9router/db/data.sqlite — providers, combos, aliases, and usage history. The directory also keeps automatic backups under db/backups/. Backing up the ~/.9router folder is enough to restore the entire routing configuration on a new machine.

Benefits that show up in practice

  • Provider swaps without touching clients. Change the combo in the dashboard and every tool pointing at /v1 follows.
  • Layered fallback. A subscription → cheap → free chain keeps sessions alive when one provider’s quota runs out.
  • Token savings on tool-heavy workloads. RTK pays off most when git diffs and log dumps ride along.
  • Flexible provider roster. API-key providers (OpenRouter, OpenAI, Anthropic, DeepSeek, GLM, and dozens more), OAuth subscriptions, free tiers such as Kiro and OpenCode Free, plus local endpoints like Ollama and llama-server.

Trade-offs and limitations

  • Single point of failure. Every client targets one daemon; if it stops, all tools lose model access. A restart policy and /api/health monitoring are required.
  • Loose security defaults. The 123456 initial password and keyless /v1 routes out of the box are not meant for exposure beyond the LAN.
  • Free tiers depend on third parties. Kiro credits, OpenCode Free’s model list, and Vertex credits can change; some free tiers (iFlow, Qwen Code, Gemini CLI) were already discontinued in 2026.
  • State must be protected. All configuration and provider credentials sit in a single SQLite file; losing it means rebuilding everything from scratch.
  • Cost figures can mislead. The dashboard shows estimates “as if paying provider APIs directly”, not real bills — easy to misread as a balance.

Conclusion

9Router solves a real problem: standardizing LLM endpoints across multiple clients, centralizing credentials, and adding automatic fallback. For a single-machine homelab it is comfortable to run as long as the daemon stays up, the state is backed up, and the security defaults get tightened. It does not replace the decision of which provider to use, but it removes the manual chore of moving configuration between tools.

References