# 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
