550 lines
13 KiB
Markdown
550 lines
13 KiB
Markdown
# 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
|
|
<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`:
|
|
|
|
```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 <PID>
|
|
|
|
# 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
|