Skip to content

Instantly share code, notes, and snippets.

@acip
Last active October 27, 2025 08:51
Show Gist options
  • Select an option

  • Save acip/4e26a0de16a93aed05599586f09fe1b2 to your computer and use it in GitHub Desktop.

Select an option

Save acip/4e26a0de16a93aed05599586f09fe1b2 to your computer and use it in GitHub Desktop.
Laravel Reverb WebSocket Setup with Nginx Proxy, JWT Authentication, and /ws Path Prefix

Laravel Reverb WebSocket Setup with Nginx Proxy, JWT Authentication, and /ws/ Path Prefix

This guide explains how to configure Laravel Reverb to work behind Nginx with a /ws/ WebSocket path prefix. Using a custom path helps prevent conflicts with other routes and ensures WebSocket traffic is correctly proxied. This allows to run the WebSocket traffic on the same domain as the Web Server. Oprtional: It also demonstrates how to authenticate connections using JWT tokens.

Nginx Configuration for WebSocket Proxying via /ws/

The following Nginx block forwards all /ws/ requests to the Reverb WebSocket server running locally on port 8080:

    location /ws/ {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";

        proxy_pass http://127.0.0.1:8080;
        proxy_read_timeout 86400;
    }

echo.js Setup

Use the following echo.js configuration to connect your frontend to Laravel Reverb with JWT-based authentication (optional):

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

// if using JWT based auth
const currentUserToken = JSON.parse(localStorage.getItem('auth.token'));

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,
    wsPath: import.meta.env.VITE_REVERB_PATH ?? '',
    forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
    auth: {
        headers: {
            Authorization: 'Bearer ' + currentUserToken,
        },
    },
});

.env Configuration

Update your environment variables to match your setup:

BROADCAST_CONNECTION=reverb
REVERB_APP_ID=<your_app_id>
REVERB_APP_KEY=<your_app_key> # generate with ` openssl rand -hex 32`
REVERB_APP_SECRET=<your_app_secret> # generate with ` openssl rand -hex 32`

REVERB_SERVER_HOST=127.0.0.1
REVERB_SERVER_PORT=8080
REVERB_SERVER_PATH=/ws

REVERB_HOST=<your_domain>
REVERB_PORT=443
REVERB_SCHEME=https

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
VITE_REVERB_PATH=/ws

broadcasting.php Configuration Adjustment

Finally, update your Reverb connection configuration to include the base path:

connections.reverb.options.base_path = env('VITE_REVERB_PATH', '').'/apps/'.env('REVERB_APP_ID')

Running Reverb as a service using Linux systemd

sudo nano /etc/systemd/system/reverb.service
[Unit]
Description=Laravel Reverb WebSocket Server
After=network.target

[Service]
ExecStart=/usr/bin/php /var/www/example.test/artisan reverb:start --port=6001 --host=0.0.0.0
Restart=always
User=www-data
Group=www-data
WorkingDirectory=/var/www/example.test

[Install]
WantedBy=multi-user.target

Reference - https://dev.to/edgaras/running-laravel-reverb-in-the-background-using-systemd-3732

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment