# How to Set Up OmniRoute Remote Mode with Scoped Tokens for VPS Deployments

> Set up OmniRoute remote mode on a VPS for secure routing control with scoped tokens. Avoid global API keys and manage your engine remotely with ease.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-10

---

**OmniRoute remote mode lets you run the routing engine on a VPS while controlling it from your local machine using short-lived, finely-scoped tokens instead of global API keys.**

This deployment pattern is ideal when you need centralized infrastructure—whether on a VPS, Docker container, or Cloudflare Worker—without giving every client full access to your OmniRoute instance. The **scoped sync token** system, implemented in [`src/app/api/sync/tokens/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/sync/tokens/route.ts), enforces route-level permissions at runtime.

## Why Use Remote Mode with Scoped Tokens

Running OmniRoute remotely solves several operational challenges:

- **Offload compute** — Heavy inference routing happens on infrastructure you control
- **Centralized configuration** — Single source of truth for provider keys and routing rules
- **Least-privilege access** — Each client gets tokens limited to specific endpoints and time windows

Unlike traditional API key authentication, scoped tokens in OmniRoute are **self-describing JWT-like strings** that carry their permission boundaries. The server validates these against the `sync_tokens` table managed in [`src/lib/db/syncTokens.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/syncTokens.ts).

## Install OmniRoute on Your VPS

### Prerequisites and Installation

1. **Node.js ≥ 22** required
2. Clone and prepare the release:

```bash
git clone https://github.com/diegosouzapw/OmniRoute.git
cd OmniRoute
git checkout release/v3.8.50
npm ci

```

3. Configure environment variables:

```bash
cp .env.example .env

```

Edit `.env` for remote-specific values:

```bash
PORT=20128
OMNIROUTE_PUBLIC_BASE_URL=https://my-omniroute.example.com
REQUIRE_API_KEY=true

```

4. Start the server via systemd, Docker, or `npm run dev`

The server now listens on your exposed VPS address. The **sync token authentication handler** resides in [`src/app/api/sync/tokens/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/sync/tokens/route.ts), which processes all token lifecycle requests.

## Create a Scoped Sync Token

Tokens are generated through the **Sync Token API** and stored persistently in SQLite. A token's `scope` array defines exactly which routes it may access.

### Token Creation Request

```bash
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
      }'

```

| Parameter | Purpose |
|-----------|---------|
| `name` | Human-readable identifier for audit logs |
| `scope` | Array of permitted route patterns (e.g., `v1/chat/completions`) |
| `ttl` | Time-to-live in seconds |

The response returns a `token` field—this is the **only time** the credential is visible. The underlying implementation in [`src/app/api/sync/tokens/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/sync/tokens/route.ts) hashes the token for storage while logging the creation event.

Token management endpoints also support retrieval and revocation in `src/app/api/sync/tokens/[id]/route.ts`, handling `DELETE` operations for immediate revocation.

## Configure the Local CLI for Remote Mode

The CLI detects remote mode through either the `--remote` flag or the `OMNIROUTE_REMOTE_URL` environment variable. The `--api-key` parameter accepts your scoped token.

### Launch with Remote Configuration

```bash
omniroute launch \
  --remote https://my-omniroute.example.com \
  --api-key <token-from-step-2> \
  --model claude-3.5-sonnet

```

All subsequent subcommands (`configure`, `setup`, `chat`) inherit these settings unless overridden. The **remote mode semantics** are fully documented in [`docs/guides/REMOTE-MODE.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/guides/REMOTE-MODE.md), which specifies behavior for connection falling, token refresh, and error propagation.

For Electron UI users, setting `OMNIROUTE_REMOTE_URL` in the environment attaches the interface to a remote server instead of spawning a local instance—documented in [`electron/README.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/electron/README.md).

## Verify Token Scope Enforcement

Scoped tokens correctly reject requests outside their permission boundary with HTTP 401.

### Scope Verification Test

```bash
curl -X GET https://my-omniroute.example.com/api/v1/models \
  -H "Authorization: Bearer <token-from-step-2>"

```

**Expected response:**

```json
{"error":{"message":"Unauthorized: token scope does not permit this route"}}

```

This confirms the token is **restricted to the chat endpoint** and cannot enumerate available models or access administrative functions.

## Manage Tokens Programmatically

### List Active Tokens

```bash
curl -H "Authorization: Bearer <management-API-key>" \
     https://my-omniroute.example.com/api/sync/tokens

```

### Revoke a Token Immediately

```bash
curl -X DELETE https://my-omniroute.example.com/api/sync/tokens/<id> \
  -H "Authorization: Bearer <management-API-key>"

```

The revocation handler in `src/app/api/sync/tokens/[id]/route.ts` purges the token from the `sync_tokens` table and propagates the invalidation to active connection pools.

## Complete Deployment Example

### Automate Token Creation (Bash)

```bash
#!/bin/bash
set -euo pipefail

MANAGEMENT_KEY="${OMNI_MANAGEMENT_KEY}"
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":"vps-cli","scope":["v1/chat/completions"],"ttl":86400}' |
  jq -r .token)

echo "export OMNI_TOKEN='${TOKEN}'"
echo "export OMNI_REMOTE_URL='${REMOTE_URL}'"

```

### Interactive Chat Session

```bash
omniroute chat \
  --remote "$OMNI_REMOTE_URL" \
  --api-key "$OMNI_TOKEN" \
  --model claude-3.5-sonnet \
  "Explain the difference between remote mode and local mode."

```

## Key Implementation Files

| Path | Responsibility |
|------|----------------|
| [`docs/guides/REMOTE-MODE.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/guides/REMOTE-MODE.md) | CLI flag reference and remote mode behavior specification |
| [`src/app/api/sync/tokens/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/sync/tokens/route.ts) | **POST** endpoint for token creation; core authentication logic |
| `src/app/api/sync/tokens/[id]/route.ts` | **DELETE** revocation and token-specific error responses |
| [`src/lib/db/syncTokens.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/syncTokens.ts) | SQLite schema and CRUD operations for `sync_tokens` table |
| [`CHANGELOG.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/CHANGELOG.md) | Feature announcement: "remote mode — drive a remote OmniRoute with scoped access tokens" |
| [`electron/README.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/electron/README.md) | `OMNIROUTE_REMOTE_URL` environment variable for UI attachment |

## Summary

- **Remote mode** decouples OmniRoute's routing engine from client machines, enabling VPS and serverless deployments
- **Scoped sync tokens** replace global API keys with route-restricted, time-bounded credentials
- Token lifecycle operations (create, list, revoke) are implemented in [`src/app/api/sync/tokens/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/sync/tokens/route.ts) and `src/app/api/sync/tokens/[id]/route.ts`
- The CLI switches to remote mode via `--remote` or `OMNIROUTE_REMOTE_URL`, with `--api-key` accepting scoped tokens
- Token scope enforcement returns explicit 401 errors for unauthorized routes, enabling clear permission debugging

## Frequently Asked Questions

### How long can scoped tokens remain valid?

Token lifetime is controlled by the `ttl` parameter in seconds. You may set any value, with typical deployments using 1–24 hours (3600–86400 seconds). The `sync_tokens` table automatically expires entries based on this field.

### Can a single token access multiple routes?

Yes. The `scope` array accepts multiple route patterns: `"scope": ["v1/chat/completions", "v1/images/generations"]`. Patterns are prefix-matched, so `v1/` grants access to all v1 endpoints—though narrower scopes are recommended for security.

### What happens if my remote server becomes unreachable?

The CLI attempts connection for 30 seconds, then surfaces a clear error: `Remote server at <url> unreachable`. Operations in flight are not automatically retried; the client must reconnect. The remote mode guide in [`docs/guides/REMOTE-MODE.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/guides/REMOTE-MODE.md) documents timeout and retry configuration.

### Do scoped tokens work with the Electron UI?

Yes. Export `OMNIROUTE_REMOTE_URL` before launching the Electron application, as documented in [`electron/README.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/electron/README.md). The UI will attach to the remote server instead of spawning a local OmniRoute process, using the same token-based authentication flow.