TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/outray-tunnel/outray/llms.txt
Use this file to discover all available pages before exploring further.
@outray/express plugin hooks into app.listen() and starts an OutRay tunnel as soon as your server begins accepting connections — including when you use port 0 for a dynamically assigned port.
The tunnel only activates when
NODE_ENV=development. It is a no-op otherwise.Setup
How it works
The plugin patchesapp.listen() to intercept the listening event on the underlying HTTP server. Once the server is bound to a port — even a dynamically assigned one — the plugin reads the actual port from server.address() and opens the tunnel. No polling, no guessing.
Configuration
Pass options as the second argument tooutray():
index.js
Options
| Option | Type | Default | Description |
|---|---|---|---|
subdomain | string | — | Request a specific subdomain. Requires authentication. |
customDomain | string | — | Use a custom domain configured in the OutRay dashboard. |
apiKey | string | process.env.OUTRAY_API_KEY | API key for authentication. |
serverUrl | string | wss://api.outray.dev/ | OutRay server WebSocket URL. Change this only for self-hosted instances. |
enabled | boolean | process.env.OUTRAY_ENABLED !== "false" | Enable or disable the tunnel. |
silent | boolean | false | Suppress all tunnel status logs. |
local | boolean | false | Enable LAN access via mDNS (.local domain) for devices on the same network. |
onTunnelReady | (url: string) => void | — | Called when the tunnel is established. |
onLocalReady | (info: LocalInfo) => void | — | Called when LAN access is available. |
onError | (error: Error) => void | — | Called when the tunnel encounters an error. |
onClose | () => void | — | Called when the tunnel connection closes. |
onReconnecting | () => void | — | Called when the tunnel is attempting to reconnect. |
Environment variables
| Variable | Description |
|---|---|
NODE_ENV | The tunnel only starts when this is development. |
OUTRAY_API_KEY | API key for authentication — fallback for the apiKey option. |
OUTRAY_SUBDOMAIN | Subdomain to request — fallback for the subdomain option. |
OUTRAY_SERVER_URL | Server WebSocket URL — fallback for the serverUrl option. |
OUTRAY_ENABLED | Set to "false" to disable the tunnel without removing the plugin. |
Examples
Custom subdomain
Reserve a consistent URL for your API:index.js
Custom domain
Use a domain you’ve configured in the OutRay dashboard:index.js
Dynamic port
Works with port0 — the plugin reads the actual assigned port from server.address():
index.js
Callbacks
React to tunnel lifecycle events:index.js
Silent mode
Suppress all console output and handle the URL yourself:index.js
Webhook testing
Expose a specific endpoint for receiving webhooks:index.js
TypeScript
The package exportsOutrayPluginOptions for typed configuration:
index.ts
OutrayPluginOptions interface:
Middleware placement
The plugin does not add any middleware to your request stack. You can calloutray(app) before or after registering routes and other middleware — it only patches app.listen().
index.js
Compatibility
- Express: 4.x and 5.x
- Servers: TCP ports only — Unix domain sockets are not supported.
Troubleshooting
Tunnel not starting- Confirm
NODE_ENVis set todevelopment. - Check that
OUTRAY_ENABLEDis not set to"false". - Make sure your server is listening on a TCP port, not a Unix socket.
NODE_ENV before running your server:
dev script to package.json:
- Run
outray loginto authenticate, or setOUTRAY_API_KEY.
- The plugin reconnects automatically on connection loss.
- Confirm the server URL is correct (default:
wss://api.outray.dev/).