# 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