Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Shyamalp16/CloudGaming/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The signaling server coordinates WebRTC connections between Windows hosts and browser clients. It uses WebSocket for real-time communication and Redis pub/sub for multi-instance coordination. Key features:- WebSocket signaling for SDP and ICE candidate exchange
- Redis pub/sub for scaling across multiple instances
- Rate limiting and circuit breakers
- Health checks and Prometheus metrics
- JWT authentication (optional)
Requirements
- Node.js 16+ and npm
- Redis 6+ (required for production, single instance OK for development)
- 1-2 GB RAM per instance
- WebSocket-capable hosting (Railway, Heroku, AWS, GCP, etc.)
Installation
Configuration
Environment Variables
Create a.env file in the Server/ directory:
Configuration Reference
Core Settings
| Variable | Type | Description | Default |
|---|---|---|---|
NODE_ENV | string | Environment mode | development |
WS_PORT | number | WebSocket port (local dev only) | 3002 |
PORT | number | HTTP/WS port (auto-set by hosting platforms) | - |
HEALTH_PORT | number | Health check endpoint port | 8080 |
REDIS_URL | string | Redis connection URL | redis://127.0.0.1:6379 |
Railway, Heroku, and similar platforms automatically inject the
PORT environment variable. The server listens on PORT if available, falling back to WS_PORT.Room Settings
| Variable | Type | Description | Default |
|---|---|---|---|
ROOM_CAPACITY | number | Max clients per room | 2 |
ROOM_TTL_SECONDS | number | Room expiration time after last member leaves | 120 |
ROOM_ID_MAX_LENGTH | number | Maximum room ID length | 64 |
WebSocket Settings
| Variable | Type | Description | Default |
|---|---|---|---|
MESSAGE_MAX_BYTES | number | Max message size (bytes) | 262144 (256 KB) |
BACKPRESSURE_CLOSE_THRESHOLD_BYTES | number | Close connection if buffer exceeds this | 5242880 (5 MB) |
HEARTBEAT_INTERVAL_MS | number | Ping interval to detect dead connections | 30000 (30s) |
Rate Limiting
| Variable | Type | Description | Default |
|---|---|---|---|
RATE_LIMIT_CONN_PER_10S | number | Max new connections per IP per 10s | 20 |
RATE_LIMIT_MESSAGES_PER_10S | number | Max messages per client per 10s | 200 |
RATE_LIMIT_IP_MSGS_PER_10S | number | Max messages per IP per 10s | 400 |
RATE_LIMIT_ROOM_MSGS_PER_10S | number | Max messages per room per 10s | 800 |
Security
| Variable | Type | Description | Default |
|---|---|---|---|
REQUIRE_WSS | boolean | Reject non-WSS connections in production | false |
ALLOWED_ORIGINS | string | Comma-separated list of allowed origins | “ (all) |
SUBPROTOCOL | string | Required WebSocket subprotocol | - |
Running Locally
Start the signaling server
PORT env var).Testing WebSocket Connection
Test the WebSocket endpoint:Deploying to Production
Railway Deployment
Add Redis service
In the Railway dashboard:Railway will automatically inject
REDIS_URL as an environment variable.Deploy
- Detect the Node.js application
- Run
npm install - Execute
npm start - Expose the service on a public URL
Docker Deployment
Create aDockerfile in the Server/ directory:
Kubernetes / Docker Compose
- Docker Compose
- Kubernetes
Horizontal Scaling
The signaling server supports horizontal scaling via Redis pub/sub:- Each instance maintains local WebSocket connections
- Messages are published to Redis channel
room:{roomId} - All instances subscribed to that channel receive and forward messages
- Local room state is synchronized via Redis atomic operations
No sticky sessions required. Clients can connect to any instance.
Load Balancing
For multiple instances, use a load balancer with WebSocket support:- NGINX: Enable
proxy_http_version 1.1and upgrade headers - HAProxy: Use
option http-server-close - AWS ALB: Enable WebSocket support in target group
- Railway: Automatically load balances with 0 configuration
Monitoring
Prometheus Metrics
The server exposes metrics at/metrics:
Health Checks
- Liveness:
GET /healthz- Always returns 200 if server is running - Readiness:
GET /readyz- Returns 200 only if Redis is connected and not draining
Logging
The server uses structured JSON logging (Pino):PRETTY_LOGS=true for human-readable output during development.
Troubleshooting
Error: Redis connection failed
Error: Redis connection failed
Symptoms: Server crashes or readiness check failsSolutions:
- Verify Redis is running:
redis-cli ping - Check
REDIS_URLformat:redis://[user:password@]host:port[/db] - Verify network connectivity (firewall, security groups)
- For Railway: Ensure Redis service is in the same project
Error: EADDRINUSE (port already in use)
Error: EADDRINUSE (port already in use)
Solution: Change the port or kill the process using it
WebSocket connection fails with 426 Upgrade Required
WebSocket connection fails with 426 Upgrade Required
Cause: Client is making HTTP request instead of WebSocket upgradeSolution: Ensure client uses
ws:// or wss:// protocol:Connection rejected: Origin not allowed
Connection rejected: Origin not allowed
Cause:
ALLOWED_ORIGINS is configured but client origin doesn’t matchSolution: Add client origin to allowed list:High memory usage with many connections
High memory usage with many connections
Solutions:
- Lower
BACKPRESSURE_CLOSE_THRESHOLD_BYTESto close slow clients faster - Enable rate limiting with stricter limits
- Scale horizontally with more instances
- Monitor and close inactive connections
Messages not reaching clients on different instances
Messages not reaching clients on different instances
Cause: Redis pub/sub not workingDiagnosis:Solutions:
- Verify all instances use the same
REDIS_URL - Check Redis logs for errors
- Ensure Redis allows pub/sub (not in cluster mode with restrictions)
Security Best Practices
Next Steps
- Matchmaker Deployment - Set up host registration and matching
- Host Setup - Configure Windows hosts to connect to this signaling server
- Client Deployment - Deploy the browser client