This guide runs the standalone server and connects a Laravel app (and its Echo client) to it. If you want to embed the server in an Elixir app instead, see the Embedding guide.
Laravel and Echo compatibility is by protocol: the server implements what the
pusherbroadcaster andpusher-jsuse. It has not yet been tested end to end against a real Laravel app. Treat the first run as a test.
1. Run the server
docker build -t pusher-server .
docker run -p 6001:6001 \
-e PUSHER_APP_ID=my-app-id \
-e PUSHER_APP_KEY=my-app-key \
-e PUSHER_APP_SECRET=a-long-random-secret \
pusher-server
Generate a real secret, for example with openssl rand -hex 32. If you leave
the secret unset the server falls back to a public default and logs a warning,
because anyone who knows it could sign requests and subscribe to private
channels.
Check it is up:
curl http://localhost:6001/
# ok
2. Point Laravel at it
Install the PHP SDK if you haven't:
composer require pusher/pusher-php-server
.env (use BROADCAST_DRIVER instead of BROADCAST_CONNECTION on Laravel 10
and older):
BROADCAST_CONNECTION=pusher
PUSHER_APP_ID=my-app-id
PUSHER_APP_KEY=my-app-key
PUSHER_APP_SECRET=a-long-random-secret
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"The three values (id, key, secret) must be identical on the server and in
Laravel. config/broadcasting.php:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'host' => env('PUSHER_HOST', '127.0.0.1'),
'port' => env('PUSHER_PORT', 6001),
'scheme' => env('PUSHER_SCHEME', 'http'),
'useTLS' => env('PUSHER_SCHEME', 'http') === 'https',
],
],If your app queues broadcasts, make sure a queue worker is running, or events will never be sent.
3. Point the browser at it
npm install --save-dev laravel-echo pusher-js
// resources/js/echo.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST,
wsPort: import.meta.env.VITE_PUSHER_PORT,
wssPort: import.meta.env.VITE_PUSHER_PORT,
forceTLS: false,
enabledTransports: ['ws', 'wss'],
cluster: 'mt1', // required by pusher-js, ignored by this server
});Private and presence channels need Laravel's /broadcasting/auth route, as with
any Pusher setup. That route signs the subscription with the same secret the
server checks.
4. Try it
Subscribe from the browser console:
Echo.channel('orders').listen('.test', (e) => console.log(e));Then send an event from Laravel (php artisan tinker):
broadcast(new class implements Illuminate\Contracts\Broadcasting\ShouldBroadcastNow {
public function broadcastOn() { return new Illuminate\Broadcasting\Channel('orders'); }
public function broadcastAs() { return 'test'; }
});The browser should log the event. If nothing arrives, see Troubleshooting.
Next
- Configuration for webhooks and client events
- Deployment for TLS and proxies
- Multi-server to run more than one node