Railway

Deploy 9router

Self-host 9router: OpenAI-compatible endpoint, 100+ models, fallback & more

Deploy 9router

Just deployed

/app/data

9Router official website hero

Deploy and Host 9Router on Railway

9Router is an open-source AI gateway that puts a single OpenAI-compatible endpoint in front of 40+ model providers and 100+ models.

Rather than wiring every coding tool to a different SDK, key, and base URL, you point Claude Code, Cursor, Cline, Copilot, OpenCode, or any OpenAI-compatible client at one /v1 URL and manage providers, keys, fallback order, and spend from one dashboard.

Teams self-host 9Router to consolidate scattered provider keys, ride out rate limits without editing config, and see which model answered which request at what cost.

Deploy 9Router on Railway and the gateway runs as one container with a persistent volume and public HTTPS in front of it. It keeps providers, issued API keys, fallback chains ("combos"), usage history, and settings in an embedded SQLite database on that volume, so there is no Postgres or Redis to operate. Your tool sends an OpenAI-format request to https:///v1; 9Router authenticates it against a key you issued, picks a provider from your chain, translates to that provider's native format, and streams the response back.

Getting Started with 9Router on Railway

When the deploy goes green, open the service's public URL and you will hit a password gate at /login. The password comes from the INITIAL_PASSWORD variable — copy the generated value from the service's Variables tab in Railway, then change it under Settings, since that value only seeds the account.

Next open Providers and connect an upstream by pasting a key from a provider you already use; OpenAI, Anthropic, Gemini, DeepSeek, Groq, GLM, Kimi, and MiniMax work out of the box.

Then go to Endpoint & Key, click Create Key, and copy the issued 9Router key — this is what your tools send, and it is separate from your provider keys.

Verify the path by calling /v1/models with that key and confirming you get a model list rather than a 401.

Finally, open Combos to build a fallback chain so a rate-limited model hands off automatically.

9Router dashboard screenshot

9Router dashboard screenshot

About Hosting 9Router

9Router addresses a problem that appears as soon as a team uses more than one provider: each tool wants its own configuration, each provider has its own auth scheme and request format, and one rate limit can stall everything. Self-hosting keeps the gateway, credentials, and request logs on infrastructure you control.

Key features:

  • One OpenAI-compatible /v1 endpoint fronting 40+ providers and 100+ models
  • Fallback chains that reroute automatically on rate limits and errors
  • Per-provider quota and usage tracking with cost estimation
  • Format translation across OpenAI, Anthropic, and Gemini request styles
  • RTK token compression that shrinks diffs, grep output, and file trees
  • Separately issued API keys, so tools never hold your upstream credentials

One Node.js service serves the dashboard and routing layer on port 20128, and one volume at /app/data holds the SQLite database and backups — no database tier to provision or pay for.

Why Deploy 9Router on Railway

Railway removes the server work around a self-hosted gateway:

  • One container, one volume — no Postgres or Redis to run
  • Public HTTPS and a domain provisioned automatically
  • Persistent storage that survives redeploys and restarts
  • Secrets managed as service variables, never baked into an image
  • Redeploy to a new pinned version in a single click

Common Use Cases

  • Consolidating provider keys — issue one 9Router key per developer or tool and revoke access without rotating upstream credentials.
  • Surviving rate limits — fall back to a secondary provider when the first returns HTTP 429.
  • Tracking AI spend — attribute cost per provider and model instead of reconciling vendor invoices.
  • Standardising on one API surface — point internal scripts at one base URL and swap models without touching code.

Dependencies for 9Router

  • decolua/9router — the application image on Docker Hub, multi-arch for linux/amd64 and linux/arm64. Mirrored at ghcr.io/decolua/9router, but semantic version tags are published only to Docker Hub.
  • A persistent volume at /app/data — holds db/data.sqlite and db/backups/. Without it, every provider, key, and combo is lost on redeploy.

There is no external database, cache, or message broker, which is why the volume is the one dependency you must not drop.

Environment Variables Reference

VariablePurpose
PORTListening port; must match the domain's target port
DATA_DIRWhere SQLite lives; point at the mounted volume
JWT_SECRETSigns dashboard session cookies — must be strong and random
INITIAL_PASSWORDSeeds the first dashboard login
API_KEY_SECRETHMAC secret for keys issued by the dashboard
REQUIRE_API_KEYRejects unauthenticated calls to /v1/*
BASE_URLPublic URL the server uses to call itself
ENABLE_REQUEST_LOGSWrites full request/response bodies to disk

Deployment Dependencies

Runtime is Node.js 22 on Alpine with Next.js 16, bundled in the image. Source: https://github.com/decolua/9router

Hardware Requirements for Self-Hosting 9Router

The gateway forwards and translates requests rather than running inference, so requirements stay modest.

ResourceMinimumRecommended
CPU0.5 vCPU1–2 vCPU
RAM512 MB1–2 GB
Storage1 GB volume5 GB volume
RuntimeNode.js 22 (in image)Node.js 22 (in image)

A fresh install uses well under 100 MB. Growth comes from usage history and backups; full request logging increases it much faster.

Self-Hosting 9Router with Docker

The quickest way to run 9Router outside Railway is the published image. This Docker command mounts a named volume and sets the security-relevant variables:

docker run -d \
  --name 9router \
  -p 20128:20128 \
  -v 9router-data:/app/data \
  -e DATA_DIR=/app/data \
  -e JWT_SECRET="$(openssl rand -hex 32)" \
  -e API_KEY_SECRET="$(openssl rand -hex 32)" \
  -e INITIAL_PASSWORD="choose-a-strong-password" \
  -e REQUIRE_API_KEY=true \
  decolua/9router:latest

Before exposing any instance, confirm it refuses unauthenticated traffic:

curl -i https://your-domain.example/v1/models

A correctly configured instance answers 401 with API key required for remote API access. If it returns a model list, REQUIRE_API_KEY is unset and anyone who finds the URL can spend your provider credits.

How Much Does 9Router Cost to Self-Host?

9Router is free and open source under the MIT licence — no paid tier, seat cost, or per-request fee. Self-hosting costs are infrastructure only, and on Railway that is one small container plus a volume, which stays inexpensive because the gateway idles cheaply between requests. You still pay upstream providers at their own rates; 9Router meters those calls but does not resell tokens.

Troubleshooting

The login screen warns that no password is set → this banner can appear even when INITIAL_PASSWORD is set and working. Trust the login attempt over the banner.

Dashboard says "Endpoint is exposed without an API key" → the in-app toggle and the REQUIRE_API_KEY variable are separate switches. The variable already blocks unauthenticated remote calls; enable the toggle too so both agree.

FAQ

What is 9Router? An open-source, self-hosted AI gateway exposing one OpenAI-compatible endpoint that routes across 40+ model providers, with fallback chains, quota tracking, token compression, and a dashboard.

What does this Railway template deploy? A single 9Router service from the official decolua/9router image, with a persistent volume at /app/data, a public HTTPS domain on port 20128, and the security-relevant variables pre-set.

Why a volume instead of a database service? 9Router keeps providers, issued keys, combos, sessions, and usage history in an embedded SQLite file. The volume makes that state survive a redeploy — remove it and every provider connection is wiped.

How do I stop other people from using my deployed 9Router endpoint? Keep REQUIRE_API_KEY set to true. Every /v1/* request then needs a Bearer key you issued, and unauthenticated callers get a 401. The endpoint is public and spends against your upstream credits.

Which version of 9Router should I pin for production? Pin an explicit version tag rather than latest, and stay on 0.4.45 or newer — earlier releases shipped a hardcoded fallback session secret allowing dashboard auth bypass when JWT_SECRET was unset. Always set JWT_SECRET yourself.

Can I point Claude Code or Cursor at a self-hosted 9Router? Yes. Set the tool's base URL to https:///v1 and its API key to one issued from the dashboard.


Template Content

More templates in this category

View Template
Chat Chat
Chat Chat, your own unified chat and search to AI platform.

okisdev
113
View Template
stella
Self-host stella with web, API, Postgres, Redis, and object storage.

Jan Kubica
1
View Template
Hermes Agent | OpenClaw Alternative with Dashboard
Self-Hosted Hermes AI Agent for Telegram, Discord & Slack

codestorm
55