Reverb is a practical alternative to Pusher for real-time event broadcasting in Laravel. This guide focuses on configuring Reverb in Laravel 11 for a live production system hosted behind Cloudflare with Flexible SSL.
Prerequisites
Before diving into the setup, ensure you have the following:
- Laravel 11 installed: You can set up a fresh Laravel 11 application using Composer.
- Apache web server: Ensure Apache is installed and running.
- Cloudflare account: Your application should be set up behind Cloudflare with Flexible SSL enabled.
Install Reverb
To start, you need to install Reverb in your Laravel project. Run the following Composer command:
composer require laravel/reverb
After installation, publish the configuration file:
php artisan vendor:publish --provider="Laravel\Reverb\ReverbServiceProvider"
This will create a config/reverb.php
file where you can adjust Reverb’s settings.
Reverb Configuration Example
The following is an example configuration for Reverb:
<?php
return [
'default' => env('REVERB_SERVER', 'reverb'),
'servers' => [
'reverb' => [
'host' => env('REVERB_HOST', '0.0.0.0'),
'port' => env('REVERB_PORT', 6001),
'hostname' => env('REVERB_HOST'),
'options' => [
'tls' => [],
],
'max_request_size' => env('REVERB_MAX_REQUEST_SIZE', 10_000),
'scaling' => [
'enabled' => env('REVERB_SCALING_ENABLED', false),
'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
'server' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'port' => env('REDIS_PORT', '6379'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'database' => env('REDIS_DB', '0'),
],
],
'pulse_ingest_interval' => env('REVERB_PULSE_INGEST_INTERVAL', 15),
'telescope_ingest_interval' => env('REVERB_TELESCOPE_INGEST_INTERVAL', 15),
],
],
'apps' => [
'provider' => 'config',
'apps' => [
[
'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',
],
'allowed_origins' => ['*'],
'ping_interval' => env('REVERB_APP_PING_INTERVAL', 60),
'activity_timeout' => env('REVERB_APP_ACTIVITY_TIMEOUT', 30),
'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000),
],
],
],
];
.env
Settings
Ensure the following environment variables are correctly configured in your .env
file:
BROADCAST_CONNECTION=reverb
QUEUE_CONNECTION=database
REVERB_HOST=127.0.0.1
REVERB_PORT=6001
REVERB_APP_ID=<app-id>
REVERB_APP_KEY=<app-key>
REVERB_APP_SECRET=<app-secret>
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="example.com"
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https
Creating an Event
Use the following Artisan command to generate a new event class:
php artisan make:event MessageSent
Here is an example implementation of the MessageSent
event:
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\Channel;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct($message)
{
$this->message = $message;
}
public function broadcastOn(): Channel
{
return new Channel('chat-channel');
}
public function broadcastAs(): string
{
return 'message-sent';
}
}
Laravel Blade Example
Create a simple Blade template to test Reverb functionality (welcome.blade.php
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel Reverb WebSocket Test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pusher/8.3.0/pusher.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/laravel-echo/1.17.1/echo.iife.min.js"></script>
</head>
<body>
<h1>Laravel Reverb WebSocket Test</h1>
<p>Open the console to see WebSocket messages.</p>
<button id="sendMessage">Send Test Message</button>
<script>
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('sendMessage').addEventListener('click', async () => {
const response = await fetch('/send-message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
},
body: JSON.stringify({ message: 'Hello, Reverb!' }),
});
const result = await response.json();
console.log('Message sent:', result);
});
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: '{{ env('REVERB_APP_KEY') }}',
wsHost: '{{ env('VITE_REVERB_HOST', request()->getHost()) }}',
wsPort: 6001,
wssPort: 443,
forceTLS: true,
enabledTransports: ['ws', 'wss'],
cluster: 'mt1',
});
window.Echo.channel('chat-channel')
.listen('.message-sent', (data) => {
console.log('Received event:', data.message);
});
});
</script>
</body>
</html>
Defining Routes
Below is the code to define the required routes:
<?php
use Illuminate\Support\Facades\Route;
use App\Events\MessageSent;
Route::post('/send-message', function (\Illuminate\Http\Request $request) {
event(new MessageSent($request->input('message')));
return response()->json(['success' => true]);
});
Route::get('/', function () { return view('welcome'); });
Apache Configuration
Run the following commands to enable the necessary Apache modules:
sudo a2enmod proxy
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
Below is an example configuration for your Apache VirtualHost setup:
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName example.com
DocumentRoot /var/www/example.com/public
ProxyPreserveHost On
ProxyRequests Off
ProxyPass /app ws://127.0.0.1:6001/app
ProxyPassReverse /app ws://127.0.0.1:6001/app
SetEnvIf X-Forwarded-Proto https HTTPS=on
ErrorLog /var/www/logs/example.com_error.log
CustomLog /var/www/logs/example.com_access.log combined
</VirtualHost>
<Directory /var/www/example.com>
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
Running Services
To start the services, you'll need to launch the event worker and the Rebel server.
Run the following command to initiate the event worker:
php artisan queue:work
Use the command below to start the Rebel server on the specified port and host:
php artisan reverb:start --port=6001 --host=0.0.0.0
Conclusion
If you do not use the CDN for Laravel Echo and Pusher, you will need to install the required npm libraries (pusher-js
and laravel-echo
) to integrate real-time event broadcasting into your application. This setup requires a frontend build process to manage and bundle the libraries within your project.
For applications hosted behind Cloudflare with Full SSL, a separate VirtualHost must be configured with properly defined SSL certificates. This ensures secure WebSocket communication and avoids issues with SSL/TLS mismatches, which can prevent WebSocket connections from functioning correctly.
Top comments (0)