A production-ready WebSocket server powered by Laravel Reverb. Designed for multi-tenant applications with dynamic app management, Prometheus metrics, and zero-downtime deployments.
- Multi-App Support - Manage multiple WebSocket applications via REST API
- Prometheus Metrics - Built-in
/metricsendpoint for monitoring - Health Checks - Docker/Kubernetes-ready
/healthendpoint - Hot Reload - Update app configurations without restart
- Database Storage - SQLite by default, supports MySQL/PostgreSQL
docker run -d \
-p 80:80 \
-p 8080:8080 \
-e APP_KEY=base64:your-key-here \
-e API_ADMIN_TOKEN=your-secret-token \
-v websocket-data:/var/www/html/database \
ghcr.io/cboxdk/websocket-server:latestservices:
websocket-server:
image: ghcr.io/cboxdk/websocket-server:latest
ports:
- "80:80" # HTTP API
- "8080:8080" # WebSocket
environment:
APP_KEY: "${APP_KEY}"
API_ADMIN_TOKEN: "${API_ADMIN_TOKEN}"
volumes:
- websocket-data:/var/www/html/database
volumes:
websocket-data:# Clone and install
git clone https://github.com/cboxdk/websocket-server.git
cd websocket-server
composer setup
# Start development server
composer devFor data to survive container restarts, mount the following:
| Path | Description | Required |
|---|---|---|
/var/www/html/database |
SQLite database (apps, sessions, cache) | Yes |
Example with bind mount:
docker run -d \
-v /path/on/host/database:/var/www/html/database \
ghcr.io/cboxdk/websocket-server:latestExample with named volume:
docker run -d \
-v websocket-data:/var/www/html/database \
ghcr.io/cboxdk/websocket-server:latest| Variable | Description |
|---|---|
APP_KEY |
Laravel encryption key (generate with php artisan key:generate --show) |
API_ADMIN_TOKEN |
Bearer token for API authentication |
| Variable | Description | Default |
|---|---|---|
REVERB_HOST |
WebSocket server bind address | 0.0.0.0 |
REVERB_PORT |
WebSocket server port | 8080 |
REVERB_SCALING_ENABLED |
Enable Redis-based horizontal scaling | false |
| Variable | Description | Default |
|---|---|---|
METRICS_ENABLED |
Enable Prometheus metrics endpoint | true |
METRICS_AUTH_TOKEN |
Bearer token for /metrics endpoint |
optional |
| Variable | Description | Default |
|---|---|---|
DB_CONNECTION |
Database driver (sqlite, mysql, pgsql) |
sqlite |
DB_HOST |
Database host | 127.0.0.1 |
DB_PORT |
Database port | 3306 |
DB_DATABASE |
Database name | laravel |
DB_USERNAME |
Database username | root |
DB_PASSWORD |
Database password | empty |
| Variable | Description | Default |
|---|---|---|
REDIS_HOST |
Redis host | 127.0.0.1 |
REDIS_PORT |
Redis port | 6379 |
REDIS_PASSWORD |
Redis password | null |
php artisan key:generate --show
# Or using Docker:
docker run --rm ghcr.io/cboxdk/websocket-server:latest php artisan key:generate --showAll API endpoints require the Authorization: Bearer {API_ADMIN_TOKEN} header.
curl -H "Authorization: Bearer $TOKEN" http://localhost/api/appscurl -X POST http://localhost/api/apps \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "my-app"}'Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "app-key-here",
"name": "my-app",
"allowed_origins": ["*"],
"max_connections": null
}
}curl -X PUT http://localhost/api/apps/{id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"allowed_origins": ["https://example.com"]}'curl -X DELETE http://localhost/api/apps/{id} \
-H "Authorization: Bearer $TOKEN"curl -X POST http://localhost/api/apps/{id}/regenerate-secret \
-H "Authorization: Bearer $TOKEN"curl -X POST http://localhost/api/reload \
-H "Authorization: Bearer $TOKEN"curl http://localhost/health{
"status": "healthy",
"timestamp": "2025-01-17T12:00:00+00:00",
"checks": {
"reverb": "up"
}
}curl http://localhost/metrics
# Or with authentication:
curl -H "Authorization: Bearer $METRICS_TOKEN" http://localhost/metricsConnect using any Pusher-compatible client:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-app-key',
wsHost: 'localhost',
wsPort: 8080,
forceTLS: false,
disableStats: true,
cluster: 'mt1',
});
Echo.channel('my-channel')
.listen('MyEvent', (e) => {
console.log(e);
});# Run tests
composer test
# Format code
vendor/bin/pint
# Start dev server with logs
composer devMIT