# 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 ```bash # 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`: ```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`: ```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`: ```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`: ```javascript 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: ```bash 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`: ```ini [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 ```bash 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 ```bash # 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 ```bash # 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 ```bash 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`): ```apache ServerName yourdomain.org DocumentRoot /home/r/Websites/timebank_cc_2/public # Regular Laravel application Options Indexes FollowSymLinks AllowOverride All Require all granted # 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 ``` ### 3. Update Environment Variables When using Apache proxy, update `.env`: ```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: ```bash npm run build ``` ### 5. Test and Reload Apache ```bash # Test configuration sudo apache2ctl configtest # Reload Apache sudo systemctl reload apache2 ``` ## Testing the WebSocket Connection ### 1. Check Server is Running ```bash # 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: ```bash # 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: ```javascript // 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**: 1. Verify Reverb is running: `ps aux | grep reverb` 2. Check port is listening: `ss -tlnp | grep 8080` 3. Verify firewall allows port 8080: `sudo ufw status` 4. Check `.env` variables match on server and client side 5. Rebuild frontend assets: `npm run build` ### WebSocket Closes Immediately **Problem**: Connection establishes but closes immediately **Solutions**: 1. Check Redis is running: `redis-cli ping` (should return `PONG`) 2. Verify Redis credentials in `.env` 3. Check Reverb logs: `sudo journalctl -u timebank-reverb.service -f` 4. Ensure `PUSHER_APP_KEY` matches in `.env` and frontend ### Port Already in Use **Problem**: `Address already in use` error on port 8080 **Solutions**: ```bash # Find process using port 8080 sudo lsof -i :8080 # Kill the process sudo kill -9 # Or restart the service sudo systemctl restart timebank-reverb.service ``` ### Permission Denied Errors **Problem**: Reverb cannot write to storage or logs **Solutions**: ```bash # 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**: 1. Monitor active connections: Check application logs 2. Set connection limits in `config/reverb.php` 3. Enable Redis scaling for multiple Reverb instances: ```env REVERB_SCALING_ENABLED=true REVERB_SCALING_CHANNEL=reverb ``` ### SSL/TLS Issues in Production **Problem**: `wss://` connections fail **Solutions**: 1. Verify SSL certificate is valid 2. Configure TLS options in `config/reverb.php`: ```php 'options' => [ 'tls' => [ 'local_cert' => '/path/to/cert.pem', 'local_pk' => '/path/to/key.pem', 'verify_peer' => false, ], ], ``` 3. 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 ```bash # 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: ```bash # 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 1. **Use strong credentials**: Generate secure random keys for `PUSHER_APP_KEY` and `PUSHER_APP_SECRET` 2. **Enable SSL**: Always use `wss://` in production 3. **Restrict origins**: Update `allowed_origins` in `config/reverb.php` 4. **Firewall rules**: Restrict port 8080 to localhost if using Apache proxy 5. **Rate limiting**: Implement rate limiting for WebSocket connections 6. **Monitor logs**: Regularly check for connection anomalies ### Firewall Configuration If running Reverb directly (not behind Apache proxy): ```bash # Allow WebSocket port sudo ufw allow 8080/tcp ``` If using Apache proxy: ```bash # 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 ```bash # 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 variables - `config/reverb.php` - Server configuration - `config/broadcasting.php` - Broadcasting driver - `resources/js/echo.js` - Client configuration - `/etc/systemd/system/timebank-reverb.service` - systemd service - `/etc/apache2/sites-available/000-default.conf` - Apache proxy