DurinDoor
Getting started

Installation

Install DurinDoor with npm, from source, or Docker, and set DATA_DIR and JWT_SECRET.

Choose npm, a source checkout, or Docker. Native installs use Node.js 20.20.2 and npm 10.8.2. Docker includes Node.js. You need disk for persistent data, a browser for the dashboard and OAuth, and access to your upstream providers.

Before a native start, set a strong INITIAL_PASSWORD and a persistent JWT_SECRET in the process environment. For a source install, copy .env.example to .env and replace its CHANGE_ME values. Keep the same signing secrets on later starts. A source deployment without an explicit DATA_DIR also needs API_KEY_SECRET to create client keys.

export JWT_SECRET="$(openssl rand -hex 32)"
export API_KEY_SECRET="$(openssl rand -hex 32)"
export INITIAL_PASSWORD="CHANGE_ME_STRONG_PASSWORD"
npm install -g durindoor
durindoor --host 127.0.0.1

The CLI binary name is durindoor. Default port is 20128. Default bind is 0.0.0.0. Use --host 127.0.0.1 for loopback only, --port to change the port, --no-browser to skip opening the dashboard.

Data directory

DATA_DIR is the persistent root. Set it at deploy time. If it is unset, the process uses ~/.9router on macOS and Linux, or %APPDATA%\9router on Windows. The directory is created if missing. A Unix-style path on Windows is ignored and the default is used.

Layout:

DATA_DIR/
├── db/
│   ├── data.sqlite
│   └── backups/
├── auth/
├── logs/
├── mitm/
└── runtime/

SQLite lives at DATA_DIR/db/data.sqlite. Pre-upgrade copies go in DATA_DIR/db/backups.

Environment

Copy .env.example and fill every CHANGE_ME value before a production boot. Environment variables is the full list.

VariableDefaultRole
PORT20128HTTP listen port
HOSTNAME127.0.0.1 for npm start; CLI default bind is 0.0.0.0Listen address. Do not set 0.0.0.0 on a public network without a proxy in front
DATA_DIR~/.9routerPersistent data
JWT_SECRETnone (legacy DATA_DIR/jwt-secret still accepted)Dashboard session signing. Fresh installs fail closed without env or file
INITIAL_PASSWORD123456First dashboard password when none is stored
API_KEY_SECRETminted under DATA_DIR when DATA_DIR is setHMAC secret for API key checksums. Set it when keys must survive redeploys
BASE_URLlocal URLServer-side URL for callbacks
NEXT_PUBLIC_BASE_URLlocal URLBrowser-visible URL

JWT_SECRET is required. DurinDoor does not write a new DATA_DIR/jwt-secret file. An existing file from an older install is reused with a warning. Generate a value with openssl rand -hex 32.

Upgrading

Back up DATA_DIR first. Then follow Upgrading. Global npm installs update with npm update --global durindoor.

Migration from 9router

DurinDoor can reuse a 9router data directory. Stop the old process, back up that directory, start DurinDoor with the same DATA_DIR, then check providers, keys, combos, and usage in the dashboard. Identifiers the runtime still honors, and the optional cutover script, are in Migrating from 9router.

Check the process

curl http://localhost:20128/api/health

A JSON body { "ok": true } means the HTTP server is up. Open http://localhost:20128/dashboard and sign in with your initial password. Add a provider and create a client key, then list models:

curl http://localhost:20128/v1/models \
  -H "Authorization: Bearer YOUR_DURINDOOR_API_KEY"

The response is a model list. Send a first request to verify provider access. If the process cannot start, check for an occupied port and missing JWT_SECRET. If Docker cannot reach a local model server, use a host gateway or compose service name instead of container localhost.

On this page

Edit on GitHub