How to Set Up OmniRoute in Remote Mode with Scoped Tokens for VPS Installations
Use scoped sync tokens to securely operate OmniRoute from your local machine while the server runs remotely on a VPS.
This guide walks you through deploying OmniRoute in remote mode on a VPS, creating fine-grained access credentials, and connecting your local CLI to the remote instance. Remote mode lets you run the heavy routing logic on a server while keeping your development workflow local and secure.
Install OmniRoute on the VPS
Start with a clean Node.js environment and the release version you want to deploy.
Prerequisites and Setup
- Node.js ≥ 22
- Git access to
diegosouzapw/OmniRoute
# 1. Clone and checkout a stable release
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
git checkout release/v3.8.50
# 2. Install dependencies cleanly
npm ci
# 3. Configure environment
cp .env.example .env
Required Environment Variables for Remote Mode
Edit .env to expose the service securely:
# Core remote settings
PORT=20128
OMNIROUTE_PUBLIC_BASE_URL=https://my-omniroute.example.com
REQUIRE_API_KEY=true
PORT— HTTP port the server binds toOMNIROUTE_PUBLIC_BASE_URL— Public URL clients will useREQUIRE_API_KEY=true— Critical: enforces token-based authentication for all remote API calls
Start the server with systemd, Docker, or npm run dev. The service is now ready to accept remote connections.
The sync token authentication logic lives in
src/app/api/sync/tokens/route.ts【/src/app/api/sync/tokens/route.ts】.
Create a Scoped Sync Token
Scoped sync tokens are short-lived, JWT-like credentials that restrict access to specific API routes. Unlike global API keys, they follow the principle of least privilege.
Token Creation via the Sync Token API
Token data is stored in the sync_tokens SQLite table, managed through src/lib/db/syncTokens.ts.
curl -X POST https://my-omniroute.example.com/api/sync/tokens \
-H "Authorization: Bearer <management-api-key>" \
-H "Content-Type: application/json" \
-d '{
"name": "vps-cli-token",
"scope": ["v1/chat/completions"],
"ttl": 3600
}'
Response:
{
"id": "tok_abc123",
"name": "vps-cli-token",
"token": "omni_tok_eyJ...",
"scope": ["v1/chat/completions"],
"expires_at": "2024-01-15T14:30:00Z"
}
scope— Array of permitted route patterns (e.g.,["v1/chat/completions"],["v1/*"])ttl— Time-to-live in secondstoken— The actual credential (store this securely; it is not retrievable again)
Endpoint implementations and error handling are defined in
src/app/api/sync/tokens/route.tsandsrc/app/api/sync/tokens/[id]/route.ts【/src/app/api/sync/tokens/route.ts】【/src/app/api/sync/tokens/[id]/route.ts】.
Connect the Local CLI in Remote Mode
The CLI detects remote mode when you provide --remote <url> or set OMNIROUTE_REMOTE_URL. Authentication uses --api-key with your scoped token.
Basic Remote Invocation
omniroute launch \
--remote https://my-omniroute.example.com \
--api-key omni_tok_eyJ... \
--model claude-3.5-sonnet
Once configured, subsequent commands inherit these settings:
omniroute configure \
--remote https://my-omniroute.example.com \
--api-key omni_tok_eyJ...
omniroute setup
omniroute chat "Optimize this Python function"
Remote mode applies to all sub-commands: launch, configure, setup, chat, and tool invocations.
Remote-mode semantics are documented in
docs/guides/REMOTE-MODE.md【/docs/guides/REMOTE-MODE.md】 with changelog references inCHANGELOG.md【/CHANGELOG.md】.
Verify Token Scope Restrictions
Scoped tokens reject unauthorized routes with a clear error message.
Test Scope Enforcement
# This should succeed (within scope)
curl -X POST https://my-omniroute.example.com/api/v1/chat/completions \
-H "Authorization: Bearer omni_tok_eyJ..." \
-H "Content-Type: application/json" \
-d '{"model":"claude-3.5-sonnet","messages":[{"role":"user","content":"test"}]}'
# This should fail (outside scope)
curl -X GET https://my-omniroute.example.com/api/v1/models \
-H "Authorization: Bearer omni_tok_eyJ..."
Expected 401 response for out-of-scope access:
{
"error": {
"message": "Unauthorized: token scope does not permit this route"
}
}
This confirms your token is correctly limited to only the intended routes.
Manage Tokens Through the API
The Sync Token API supports full lifecycle management.
List All Tokens
curl -H "Authorization: Bearer <management-api-key>" \
https://my-omniroute.example.com/api/sync/tokens
Revoke a Token Immediately
curl -X DELETE https://my-omniroute.example.com/api/sync/tokens/tok_abc123 \
-H "Authorization: Bearer <management-api-key>"
Revocation logic is implemented in
src/app/api/sync/tokens/[id]/route.ts【/src/app/api/sync/tokens/[id]/route.ts】.
Complete Working Examples
Automated Token Creation Script
#!/bin/bash
# create-vps-token.sh — Issue a 24-hour token for CI/CD
MANAGEMENT_KEY="${OMNI_MANAGEMENT_KEY:-}"
REMOTE_URL="${OMNI_REMOTE_URL:-https://my-omniroute.example.com}"
TOKEN=$(curl -s -X POST "${REMOTE_URL}/api/sync/tokens" \
-H "Authorization: Bearer ${MANAGEMENT_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-deploy-'$(date +%s)'",
"scope": ["v1/chat/completions","v1/messages"],
"ttl": 86400
}' | jq -r '.token')
echo "export OMNI_TOKEN=\"${TOKEN}\""
CLI Chat with Remote Instance
omniroute chat \
--remote https://my-omniroute.example.com \
--api-key "$OMNI_TOKEN" \
--model claude-3.5-sonnet \
"Review this code for race conditions: $(cat worker.ts)"
Electron Desktop App Connecting to Remote
The Electron UI can operate in remote mode by setting:
export OMNIROUTE_REMOTE_URL=https://my-omniroute.example.com
npm run start:electron
This bypasses local server spawning and connects directly to your VPS. See electron/README.md for full configuration options.
Key Implementation Files
| File | Purpose |
|---|---|
docs/guides/REMOTE-MODE.md |
Complete remote mode documentation and CLI flag reference |
src/app/api/sync/tokens/route.ts |
POST /api/sync/tokens — token creation endpoint |
src/app/api/sync/tokens/[id]/route.ts |
DELETE and per-token operations |
src/lib/db/syncTokens.ts |
SQLite schema and CRUD for sync_tokens table |
CHANGELOG.md |
Feature announcement: "remote mode — drive a remote OmniRoute with scoped access tokens" |
electron/README.md |
OMNIROUTE_REMOTE_URL environment variable for desktop UI |
Summary
- Install OmniRoute on your VPS with
REQUIRE_API_KEY=trueto enforce authentication - Create scoped tokens via
POST /api/sync/tokenswith restrictedscopearrays for least-privilege access - Connect locally with
omniroute --remote <url> --api-key <token>— all sub-commands respect remote mode - Verify restrictions by attempting out-of-scope calls; expect 401 responses for unauthorized routes
- Manage lifecycle through list/revoke API endpoints, with immediate effect on active sessions
Frequently Asked Questions
How do scoped tokens differ from global API keys in OmniRoute?
Scoped tokens are route-restricted and time-bound credentials, while global API keys grant unlimited access. As implemented in diegosouzapw/OmniRoute, scoped tokens let you grant a CI pipeline access only to v1/chat/completions for one hour, rather than exposing full administrative capabilities.
Can I use wildcards in token scopes?
Yes. The scope array accepts patterns like ["v1/*"] to permit all v1/ routes, or ["v1/chat/*","v1/models"] for selective access. Exact pattern matching rules are enforced in src/app/api/sync/tokens/route.ts based on the request path.
What happens when a token expires mid-session?
Expired tokens return 401 Unauthorized on the next API call. The CLI will prompt for re-authentication or fail with an error. For long-running operations, implement token refresh in your client or issue tokens with longer ttl values.
Is remote mode compatible with Cloudflare Workers and serverless platforms?
Yes. According to docs/guides/REMOTE-MODE.md【/docs/guides/REMOTE-MODE.md】, OmniRoute's remote mode architecture supports VPS, Docker containers, Cloudflare Workers, and other edge platforms. The HTTP interface and scoped token system are platform-agnostic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →