13 KiB
WebSocket Server Setup Guide
This guide documents the Laravel Reverb WebSocket server setup for real-time features (messaging, presence, notifications).
Overview
The application uses Laravel Reverb v1.5.1 as its WebSocket server, which provides a Pusher-compatible API for real-time broadcasting. Reverb runs as a standalone PHP process that handles WebSocket connections for:
- Real-time messaging (WireChat)
- User presence tracking
- Live notifications
- Event broadcasting
Prerequisites
- PHP 8.3+ with required extensions
- Redis server (for scaling and channel management)
- Apache2 with proxy modules (for production)
- Composer packages already installed via
composer install
Required PHP Extensions
# Check if required extensions are installed
php -m | grep -E "sockets|pcntl|posix"
# Install if missing (Ubuntu/Debian)
sudo apt-get install php8.3-redis
Configuration
1. Environment Variables
The WebSocket configuration is in .env:
# Broadcasting driver
BROADCAST_DRIVER=reverb
# Pusher-compatible API credentials (used by client and server)
PUSHER_APP_ID=114955
PUSHER_APP_KEY=example_key
PUSHER_APP_SECRET=example_secret
PUSHER_APP_CLUSTER=mt1
PUSHER_HOST=localhost
PUSHER_PORT=8080
PUSHER_SCHEME=http
# Reverb server configuration
REVERB_APP_ID="${PUSHER_APP_ID}"
REVERB_APP_KEY="${PUSHER_APP_KEY}"
REVERB_APP_SECRET="${PUSHER_APP_SECRET}"
REVERB_HOST="${PUSHER_HOST}"
REVERB_PORT="${PUSHER_PORT}"
REVERB_SCHEME="${PUSHER_SCHEME}"
# Vite build-time variables for frontend
VITE_REVERB_APP_KEY="${PUSHER_APP_KEY}"
VITE_REVERB_HOST="${PUSHER_HOST}"
VITE_REVERB_PORT="${PUSHER_PORT}"
VITE_REVERB_SCHEME="${PUSHER_SCHEME}"
Important: Do NOT use variable references for PUSHER_APP_KEY, PUSHER_APP_SECRET, etc. in production. Hard-code these values as they're used by external services that don't expand variables.
2. Server Configuration
The Reverb server configuration is in config/reverb.php:
'servers' => [
'reverb' => [
'host' => env('REVERB_SERVER_HOST', '0.0.0.0'), // Listen on all interfaces
'port' => env('REVERB_SERVER_PORT', 8080), // WebSocket port
'hostname' => env('REVERB_HOST'), // Public hostname
'options' => [
'tls' => [], // TLS config for wss:// in production
],
],
],
3. Broadcasting Configuration
The broadcasting driver is configured in config/broadcasting.php:
'default' => env('BROADCAST_DRIVER', 'null'),
'connections' => [
'reverb' => [
'driver' => 'reverb',
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT', 443),
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
],
],
4. Client Configuration
The frontend WebSocket client is configured in resources/js/echo.js:
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https",
enabledTransports: ['ws', 'wss'],
});
Running the WebSocket Server
Development Mode
For local development, run the server manually in a terminal:
php artisan reverb:start
This starts the server on 0.0.0.0:8080 (accessible from any network interface).
Output:
INFO Starting server on 0.0.0.0:8080.
INFO Reverb server started successfully.
Production Mode: systemd Service
For production, run Reverb as a systemd service to ensure it starts automatically and restarts on failure.
1. Create Service File
Create /etc/systemd/system/timebank-reverb.service:
[Unit]
Description=Laravel Reverb WebSocket Server
After=network.target redis-server.service mysql.service
Requires=redis-server.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/home/r/Websites/timebank_cc_2
ExecStart=/usr/bin/php artisan reverb:start
Restart=always
RestartSec=10
StandardOutput=append:/var/log/timebank-reverb.log
StandardError=append:/var/log/timebank-reverb-error.log
# Security settings
NoNewPrivileges=true
PrivateTmp=true
# Environment
Environment="PATH=/usr/bin:/usr/local/bin"
[Install]
WantedBy=multi-user.target
2. Create Log Files
sudo touch /var/log/timebank-reverb.log
sudo touch /var/log/timebank-reverb-error.log
sudo chown www-data:www-data /var/log/timebank-reverb*.log
3. Enable and Start Service
# Reload systemd configuration
sudo systemctl daemon-reload
# Enable service to start on boot
sudo systemctl enable timebank-reverb.service
# Start service
sudo systemctl start timebank-reverb.service
# Check status
sudo systemctl status timebank-reverb.service
4. Service Management
# View logs
sudo journalctl -u timebank-reverb.service -f
# Restart service
sudo systemctl restart timebank-reverb.service
# Stop service
sudo systemctl stop timebank-reverb.service
# Disable service
sudo systemctl disable timebank-reverb.service
Apache Proxy Configuration (Optional)
For production deployments, you may want to proxy WebSocket connections through Apache. This allows you to:
- Serve WebSockets on port 80/443 instead of 8080
- Add SSL termination
- Implement additional security controls
1. Enable Apache Modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo systemctl restart apache2
2. Add Proxy Configuration
Add to your Apache VirtualHost configuration (e.g., /etc/apache2/sites-available/000-default.conf):
<VirtualHost *:80>
ServerName yourdomain.org
DocumentRoot /home/r/Websites/timebank_cc_2/public
# Regular Laravel application
<Directory /home/r/Websites/timebank_cc_2/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# WebSocket proxy for Reverb
# Proxy WebSocket connections to /app/* to Reverb server
ProxyPass /app/ ws://127.0.0.1:8080/app/
ProxyPassReverse /app/ ws://127.0.0.1:8080/app/
# Regular HTTP proxy for Reverb API endpoints
ProxyPass /apps/ http://127.0.0.1:8080/apps/
ProxyPassReverse /apps/ http://127.0.0.1:8080/apps/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
3. Update Environment Variables
When using Apache proxy, update .env:
PUSHER_HOST=yourdomain.org
PUSHER_PORT=80
PUSHER_SCHEME=http
# Or for SSL:
PUSHER_PORT=443
PUSHER_SCHEME=https
4. Rebuild Frontend Assets
After changing environment variables, rebuild assets:
npm run build
5. Test and Reload Apache
# Test configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2
Testing the WebSocket Connection
1. Check Server is Running
# Check process
ps aux | grep reverb
# Check port is listening
ss -tlnp | grep 8080
# Or using netstat
netstat -tlnp | grep 8080
Expected output:
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 12345/php
2. Test WebSocket Connection
Use wscat to test the WebSocket connection:
# Install wscat
npm install -g wscat
# Test connection
wscat -c "ws://localhost:8080/app/aj7hptmqiercfnc5cpwu?protocol=7&client=js&version=7.0.0&flash=false"
Successful connection shows:
Connected (press CTRL+C to quit)
< {"event":"pusher:connection_established","data":"{...}"}
3. Test from Browser Console
Open your application in a browser and check the console:
// Check if Echo is initialized
console.log(window.Echo);
// Test connection
Echo.connector.pusher.connection.bind('connected', () => {
console.log('WebSocket connected!');
});
Echo.connector.pusher.connection.bind('error', (err) => {
console.error('WebSocket error:', err);
});
Troubleshooting
Connection Refused / Cannot Connect
Problem: Client cannot connect to WebSocket server
Solutions:
- Verify Reverb is running:
ps aux | grep reverb - Check port is listening:
ss -tlnp | grep 8080 - Verify firewall allows port 8080:
sudo ufw status - Check
.envvariables match on server and client side - Rebuild frontend assets:
npm run build
WebSocket Closes Immediately
Problem: Connection establishes but closes immediately
Solutions:
- Check Redis is running:
redis-cli ping(should returnPONG) - Verify Redis credentials in
.env - Check Reverb logs:
sudo journalctl -u timebank-reverb.service -f - Ensure
PUSHER_APP_KEYmatches in.envand frontend
Port Already in Use
Problem: Address already in use error on port 8080
Solutions:
# Find process using port 8080
sudo lsof -i :8080
# Kill the process
sudo kill -9 <PID>
# Or restart the service
sudo systemctl restart timebank-reverb.service
Permission Denied Errors
Problem: Reverb cannot write to storage or logs
Solutions:
# Fix storage permissions
sudo chown -R www-data:www-data /home/r/Websites/timebank_cc_2/storage
sudo chmod -R 775 /home/r/Websites/timebank_cc_2/storage
# Fix log permissions
sudo chown www-data:www-data /var/log/timebank-reverb*.log
High Memory Usage
Problem: Reverb consuming excessive memory
Solutions:
- Monitor active connections: Check application logs
- Set connection limits in
config/reverb.php - Enable Redis scaling for multiple Reverb instances:
REVERB_SCALING_ENABLED=true
REVERB_SCALING_CHANNEL=reverb
SSL/TLS Issues in Production
Problem: wss:// connections fail
Solutions:
- Verify SSL certificate is valid
- Configure TLS options in
config/reverb.php:
'options' => [
'tls' => [
'local_cert' => '/path/to/cert.pem',
'local_pk' => '/path/to/key.pem',
'verify_peer' => false,
],
],
- Or use Apache proxy with SSL termination (recommended)
Monitoring and Maintenance
Log Locations
- Reverb service logs:
/var/log/timebank-reverb.log - Reverb errors:
/var/log/timebank-reverb-error.log - systemd logs:
sudo journalctl -u timebank-reverb.service - Apache logs:
/var/log/apache2/error.log
Performance Monitoring
# Monitor WebSocket connections
watch -n 1 'ss -t | grep :8080 | wc -l'
# Check memory usage
ps aux | grep reverb
# View live logs
sudo journalctl -u timebank-reverb.service -f
Restart After Configuration Changes
After changing any configuration:
# 1. Rebuild Laravel config cache
php artisan config:clear
php artisan config:cache
# 2. Rebuild frontend assets
npm run build
# 3. Restart Reverb
sudo systemctl restart timebank-reverb.service
# 4. Restart queue workers (if using queue for broadcasts)
php artisan queue:restart
Security Considerations
Production Recommendations
- Use strong credentials: Generate secure random keys for
PUSHER_APP_KEYandPUSHER_APP_SECRET - Enable SSL: Always use
wss://in production - Restrict origins: Update
allowed_originsinconfig/reverb.php - Firewall rules: Restrict port 8080 to localhost if using Apache proxy
- Rate limiting: Implement rate limiting for WebSocket connections
- Monitor logs: Regularly check for connection anomalies
Firewall Configuration
If running Reverb directly (not behind Apache proxy):
# Allow WebSocket port
sudo ufw allow 8080/tcp
If using Apache proxy:
# Block direct access to Reverb, only allow from localhost
sudo ufw deny 8080/tcp
sudo ufw allow from 127.0.0.1 to any port 8080
Additional Resources
- Laravel Reverb Documentation: https://laravel.com/docs/11.x/reverb
- Laravel Broadcasting: https://laravel.com/docs/11.x/broadcasting
- Laravel Echo: https://laravel.com/docs/11.x/broadcasting#client-side-installation
- Pusher Protocol: https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/
Quick Reference
Essential Commands
# Start development server
php artisan reverb:start
# Start production service
sudo systemctl start timebank-reverb.service
# View logs
sudo journalctl -u timebank-reverb.service -f
# Check status
sudo systemctl status timebank-reverb.service
# Restart after changes
sudo systemctl restart timebank-reverb.service
# Test connection
ss -tlnp | grep 8080
Configuration Files
.env- Environment variablesconfig/reverb.php- Server configurationconfig/broadcasting.php- Broadcasting driverresources/js/echo.js- Client configuration/etc/systemd/system/timebank-reverb.service- systemd service/etc/apache2/sites-available/000-default.conf- Apache proxy