Wormkey uses environment variables to configure the CLI, control plane, and gateway. This page documents all available variables and their defaults.
CLI Environment Variables
These variables configure the Wormkey CLI when opening tunnels.
Variable Default Description WORMKEY_ENV(none) Set to local to use localhost defaults for control plane and edge WORMKEY_CONTROL_PLANE_URLProduction: https://wormkey-control-plane.onrender.com Local: http://localhost:3001 Control plane API endpoint for session creation WORMKEY_EDGE_URLProduction: wss://t.wormkey.run/tunnel Local: ws://localhost:3002/tunnel Gateway WebSocket endpoint for tunnel connections
CLI Examples
Local Development
Production
Custom Domain
WORMKEY_CONTROL_PLANE_URL = http://localhost:3001
WORMKEY_EDGE_URL = ws://localhost:3002/tunnel
Use ws:// for local development and wss:// (secure WebSocket) for production deployments.
Control Plane Environment Variables
The control plane manages session lifecycle and slug allocation.
Variable Default Description PORT3001HTTP server port for control plane API WORMKEY_PUBLIC_BASE_URLhttp://localhost:3002Public-facing base URL for wormhole links (used in session creation response) WORMKEY_EDGE_BASE_URLws://localhost:3002Gateway WebSocket base URL (returned to CLI for tunnel connection)
Control Plane Configuration Details
PORT
The HTTP port where the control plane listens. The server binds to 0.0.0.0 to accept connections from any interface.
Source reference : packages/control-plane/src/index.ts:252
const port = parseInt ( process . env . PORT ?? "3001" , 10 );
await fastify . listen ({ port , host: "0.0.0.0" });
WORMKEY_PUBLIC_BASE_URL
This is the canonical public origin that users will visit to access wormholes. It’s used to construct:
Public URLs: ${WORMKEY_PUBLIC_BASE_URL}/s/${slug}
Owner URLs: ${WORMKEY_PUBLIC_BASE_URL}/.wormkey/owner?slug=${slug}&token=${token}
Overlay script URLs: ${WORMKEY_PUBLIC_BASE_URL}/.wormkey/overlay.js?slug=${slug}
Source reference : packages/control-plane/src/index.ts:34-37
const PUBLIC_BASE_URL =
process . env . WORMKEY_PUBLIC_BASE_URL ?? "http://localhost:3002" ;
WORMKEY_EDGE_BASE_URL
The WebSocket base URL where the gateway accepts tunnel connections. The control plane returns this to the CLI during session creation.
Source reference : packages/control-plane/src/index.ts:36-37
const EDGE_BASE_URL =
process . env . WORMKEY_EDGE_BASE_URL ?? "ws://localhost:3002" ;
Control Plane Examples
Local Development
Production (Single Domain)
Production (Separate Domains)
PORT = 3001
WORMKEY_PUBLIC_BASE_URL = http://localhost:3002
WORMKEY_EDGE_BASE_URL = ws://localhost:3002
Gateway Environment Variables
The gateway handles TLS termination, routing, and stream forwarding.
Variable Default Description PORT3002HTTP/WebSocket server port WORMKEY_CONTROL_PLANEhttps://wormkey-control-plane.onrender.comControl plane URL for session validation and state sync WORMKEY_PUBLIC_BASE_URLhttp://localhost:3002Public base URL (fallback for URL generation) WORMKEY_PUBLIC_BASEhttp://localhost:3002Legacy alias for WORMKEY_PUBLIC_BASE_URL
Gateway Configuration Details
PORT
The server listens on this port for both HTTP traffic and WebSocket tunnel connections. Binds to 0.0.0.0.
Source reference : packages/gateway/main.go:717-720
port := os . Getenv ( "PORT" )
if port == "" {
port = "3002" // local fallback only
}
WORMKEY_CONTROL_PLANE
The gateway queries the control plane to:
Validate sessions and tokens
Fetch session policies (public/private, max viewers, blocked paths)
Sync viewer state and kicked viewer lists
Check if sessions are closed
Source reference : packages/gateway/main.go:480
controlPlaneURL := getEnv ( "WORMKEY_CONTROL_PLANE" , "https://wormkey-control-plane.onrender.com" )
The gateway requires access to the control plane for production deployments. If the control plane is unreachable, session validation and state synchronization will fail, but existing tunnel connections will continue to work.
Gateway Examples
Local Development
Production
PORT = 3002
WORMKEY_CONTROL_PLANE = http://localhost:3001
WORMKEY_PUBLIC_BASE_URL = http://localhost:3002
Session Configuration
These values are hardcoded in the control plane but can be modified in the source code.
Setting Default Location Default expiration 24hCan be overridden via CLI --expires flag Max concurrent viewers 20packages/control-plane/src/index.ts:122Session policy defaults { public: true, maxConcurrentViewers: 20, blockPaths: [], password: "" }packages/control-plane/src/index.ts:120-125Slug format {adjective}-{noun}-{number}Generated from predefined word lists Token length 32 characters Lowercase alphanumeric Basic auth username wormWhen using --auth flag Basic auth password length 8 characters Random alphanumeric
Modifying Session Defaults
To change default session behavior, edit packages/control-plane/src/index.ts:
const session : Session = {
// ... other fields
policy: {
public: true , // Change to false to require owner approval
maxConcurrentViewers: 20 , // Increase/decrease viewer limit
blockPaths: [], // Add default blocked paths
password: "" , // Set default password
},
// ...
};
Slug Generation
Slugs follow the pattern {adjective}-{noun}-{number} (e.g., quiet-lime-82).
Word Lists (packages/control-plane/src/index.ts:9-16):
const ADJECTIVES = [
"quiet" , "bold" , "swift" , "calm" , "bright" , "soft" , "warm" , "cool" ,
"deep" , "flat" , "wild" , "mild" , "dark" , "pale" , "pure" , "rare" , "max"
];
const NOUNS = [
"lime" , "mint" , "sage" , "rose" , "sky" , "sea" , "sand" , "snow" ,
"mist" , "dawn" , "dusk" , "flame" , "storm" , "wave" , "wind" , "frost" , "tooth"
];
Numbers range from 1-99.
Protocol Configuration
The gateway and CLI use a binary protocol over WebSocket. Frame types are hardcoded:
Source reference : packages/gateway/main.go:32-44
const (
FrameOpenStream = 0x 01
FrameStreamData = 0x 02
FrameStreamEnd = 0x 03
FrameStreamCancel = 0x 04
FrameResponseHdrs = 0x 05
FrameWSUpgrade = 0x 06
FrameWSData = 0x 07
FrameWSClose = 0x 08
FramePing = 0x 09
FramePong = 0x 0a
ControlStreamID = 0
)
See the Protocol Documentation for details.
Complete .env Example
Here’s a complete .env file for local development:
# ============================================
# Wormkey Environment Configuration
# ============================================
# --------------------------------------------
# CLI Configuration
# --------------------------------------------
WORMKEY_CONTROL_PLANE_URL = http://localhost:3001
WORMKEY_EDGE_URL = ws://localhost:3002/tunnel
# --------------------------------------------
# Control Plane Configuration
# --------------------------------------------
# PORT=3001 # Uncomment to change from default
WORMKEY_PUBLIC_BASE_URL = http://localhost:3002
WORMKEY_EDGE_BASE_URL = ws://localhost:3002
# --------------------------------------------
# Gateway Configuration
# --------------------------------------------
# PORT=3002 # Uncomment to change from default
WORMKEY_CONTROL_PLANE = http://localhost:3001
WORMKEY_PUBLIC_BASE_URL = http://localhost:3002
Production Considerations
Security : In production, always use HTTPS (https://) and secure WebSockets (wss://). Never expose unencrypted endpoints to the public internet.
Recommended Production Setup
Use a reverse proxy (nginx, Caddy) for TLS termination
Set secure WebSocket URLs with wss:// protocol
Configure CORS if control plane and gateway are on different domains
Use a process manager (PM2, systemd) to keep services running
Set up monitoring for all three components
Consider rate limiting at the reverse proxy level
See Deployment for detailed production setup instructions.