Files
timebank-cc-public/references/WEBSOCKET_SETUP.md
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

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:

  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:

# 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:

  1. Monitor active connections: Check application logs
  2. Set connection limits in config/reverb.php
  3. 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:

  1. Verify SSL certificate is valid
  2. Configure TLS options in config/reverb.php:
'options' => [
    'tls' => [
        'local_cert' => '/path/to/cert.pem',
        'local_pk' => '/path/to/key.pem',
        'verify_peer' => false,
    ],
],
  1. 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

  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):

# 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

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 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