Skip to main content
kRouter

Deployment

Run kRouter on a server with npm and PM2, in Docker, with Docker Compose and the Presidio sidecar, or from source. Environment variables and HTTPS.


kRouter is a Node.js server with a SQLite database, so anything that keeps a Node 20.9+ process running can host it. It is not built for serverless or edge platforms such as Cloudflare Workers. Pick one of the paths below.

npm and PM2

The simplest setup on a VPS:

npm install -g @sifxprime/krouter pm2
 
# A first-login password that works remotely; note it down
export INITIAL_PASSWORD="$(openssl rand -base64 18)" && echo "Dashboard password: $INITIAL_PASSWORD"
 
pm2 start krouter --name krouter -- --skip-update
pm2 save && pm2 startup

INITIAL_PASSWORD matters because the default 123456 is accepted only from the machine kRouter runs on. Instead of setting it, you can open the dashboard through an SSH tunnel (ssh -L 20128:localhost:20128 you@server, then http://localhost:20128/dashboard), which counts as local, and set a password under Settings → Security.

Use --port and --host here, not PORT and HOSTNAME: the krouter command ignores those variables. Add --host 127.0.0.1 after --skip-update when a reverse proxy on the same machine should be the only way in. --skip-update lets kRouter run without a terminal; see the CLI reference.

Docker

The image is on Docker Hub (sifxprime/krouter) and GitHub Container Registry (ghcr.io/sifxprime/krouter), built for linux/amd64 and linux/arm64.

KROUTER_PASSWORD="$(openssl rand -base64 18)" && echo "Dashboard password: $KROUTER_PASSWORD"
docker run -d \
  --name krouter \
  -p 20128:20128 \
  -v "$HOME/.krouter:/app/data" \
  -e INITIAL_PASSWORD="${KROUTER_PASSWORD:?run the line above first}" \
  sifxprime/krouter:latest

The first line prints the dashboard password. The image already sets PORT=20128, HOSTNAME=0.0.0.0 and DATA_DIR=/app/data, and the bind mount keeps the database and OAuth tokens on the host, so restarts and upgrades keep your state. If ~/.krouter already holds a password from an npm install, that password applies instead. MITM mode does not work inside a container.

Forgot the password? With image 0.5.162 or newer: docker exec krouter node scripts/reset-password.js.

Docker Compose with PII redaction

The repository's Compose file runs kRouter next to a Presidio sidecar that can redact personal data from prompts before they reach a provider. It builds from a clone and refuses to start until KROUTER_INITIAL_PASSWORD is set:

git clone https://github.com/sifxprime/krouter.git && cd krouter
echo "KROUTER_INITIAL_PASSWORD='$(openssl rand -base64 18)'" > .env && cat .env
docker compose up -d

cat .env shows the dashboard password. Redaction stays off until you turn on both Presidio Sidecar and PII Redaction on the dashboard's Presidio page. It then covers the chat endpoints only, and if the sidecar is down, those requests fail instead of going out unredacted.

From source

git clone https://github.com/sifxprime/krouter.git
cd krouter
npm install
npm run build:deploy
 
export INITIAL_PASSWORD="$(openssl rand -base64 18)" && echo "Dashboard password: $INITIAL_PASSWORD"
export DATA_DIR="/var/lib/krouter"      # must be writable by this user
export HOSTNAME="0.0.0.0"
export AUTH_COOKIE_SECURE="true"        # only when you serve it over HTTPS
 
npm run start

npm run start runs node custom-server.js on port 20128. For another port, run PORT=8080 node custom-server.js instead. To keep it running under PM2: pm2 start npm --name krouter -- start.

Environment variables

VariableDefaultPurpose
INITIAL_PASSWORD123456, accepted only locallyFirst-login password until you set one under Settings → Security. Needed for Docker, a reverse proxy or any remote first login. Example values from docs are treated like 123456.
JWT_SECRETgenerated, saved at $DATA_DIR/jwt-secretSigns the dashboard session. Leave it unset unless several instances must share sessions; then use openssl rand -hex 32. Values under 32 characters, or copied from docs, are ignored with a warning.
DATA_DIR~/.krouter (on Windows %APPDATA%\krouter)Database, MITM certificate and runtime files
PORT, HOSTNAME20128 and 0.0.0.0 in the Docker imagePort and bind address for Docker and source installs. The krouter command ignores them; use --port and --host.
REQUIRE_API_KEYfalseRemote callers always need an API key. true also requires one from the local machine.
AUTH_COOKIE_SECUREfalseForce the Secure flag on the session cookie. It is set anyway when the request says it arrived over HTTPS (X-Forwarded-Proto: https).
HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXYunsetOutbound proxy for calls to providers
KROUTER_SKIP_RUNTIME_HEALunsetSkip the npm self-repair of the SQLite and tray runtime at start, for air-gapped machines
API_KEY_SECRETbuilt-in valueHMAC secret for the checksum part of generated API keys
ENABLE_REQUEST_LOGSfalseWrites every request and response in full, headers included, to a logs/ folder. Debugging only; see Security.

The dashboard's Environment page shows which of these are set on a running instance.

Reverse proxy (HTTPS, custom domain)

For HTTPS on your own domain, put kRouter behind Nginx, Caddy or a Cloudflare Tunnel. An Nginx example:

server {
  listen 443 ssl;
  server_name router.example.com;
 
  ssl_certificate     /etc/letsencrypt/live/router.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/router.example.com/privkey.pem;
 
  location / {
    proxy_pass         http://127.0.0.1:20128;
    proxy_set_header   Host $host;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto https;
    proxy_buffering    off;          # needed for streaming replies
    proxy_read_timeout 600s;
  }
}

Behind a proxy that sends X-Forwarded-For or X-Real-IP, every request counts as remote: /v1/* needs an API key, and the first dashboard login needs INITIAL_PASSWORD. Start kRouter with --host 127.0.0.1 so the proxy is the only way in. kRouter also has a built-in tunnel (Cloudflare or Tailscale) on the dashboard's Endpoint page.

Data persistence

Everything kRouter keeps lives under $DATA_DIR:

$DATA_DIR/
├── db/
│   ├── data.sqlite      # providers, accounts, combos, settings, keys, history
│   └── backups/         # copies made before upgrades, migrations and imports (newest 5 kept)
├── mitm/                # MITM root certificate, only if you used MITM mode
└── jwt-secret           # generated session secret (file mode 0600)

data.sqlite holds your provider tokens and keys, so back it up and store the backups like secrets. Exporting or importing the database from the dashboard asks for your password again. Delete $DATA_DIR for a clean reset.

Updating in production

# npm and PM2
npm install -g @sifxprime/krouter@latest
pm2 restart krouter
 
# Docker
docker pull sifxprime/krouter:latest
docker rm -f krouter
# then run the two Docker lines above again
 
# From source
cd krouter
git pull
npm install
npm run build:deploy
pm2 restart krouter

With Docker, a password you already set under Settings → Security stays in force; the new one printed by the first line is only used if none is stored. kRouter migrates its database on the first start of a new version and takes a backup first.

Where to go next