Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Laravel Reverb in Production Server #107

Closed
amypo-tech opened this issue Mar 20, 2024 · 33 comments
Closed

Laravel Reverb in Production Server #107

amypo-tech opened this issue Mar 20, 2024 · 33 comments
Assignees

Comments

@amypo-tech
Copy link

amypo-tech commented Mar 20, 2024

Reverb Version

1.0

Laravel Version

11

PHP Version

8.2

Description

I have created a sample laravel 11 project and in which I have configured all the requirements for the laravel reverb.

In local machine/setup reverb is working fine. when I deployed in production server for testing I am getting the bellow error.
Screenshot 2024-03-20 at 11 15 08 PM

Steps To Reproduce

  • Defined SSL cert and ket path correctly
  • port 8080 is not blocked which can be accessed from any machine
  • tried with and without https for reverb hosting server
  • tried with localhost as reverb host

None of the above helped me. Kindly help me on this.

.env

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:8aOIIcWglqC0snCZJgA33uCG68BQ2riXec7qLR2M8pg=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=https://reverb.amypo.com

APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

APP_MAINTENANCE_DRIVER=file
APP_MAINTENANCE_STORE=database

BCRYPT_ROUNDS=12

LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=reverb
DB_USERNAME=root
DB_PASSWORD='0birj@4hMatA*RM}'

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null

BROADCAST_CONNECTION=reverb
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

CACHE_STORE=database
CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"

REVERB_APP_ID=864321
REVERB_APP_KEY=xypigyotzowvifsmqzuw
REVERB_APP_SECRET=owz65aaetqlxgjqvd8s3
REVERB_HOST="websockets.amypo.com"
REVERB_PORT=8080
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}"

config/reverb.php

  'servers' => [

       'reverb' => [
           'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
           'port' => env('REVERB_SERVER_PORT', 8080),
           'hostname' => env('REVERB_HOST'),
           'options' => [
                'tls' => [
               'local_cert' => '/etc/letsencrypt/live/websockets.amypo.com/fullchain.pem',
               'local_pk' => '/etc/letsencrypt/live/websockets.amypo.com/privkey.pem',
           ],
           ],
           'max_request_size' => env('REVERB_MAX_REQUEST_SIZE', 10_000),
           'scaling' => [
               'enabled' => env('REVERB_SCALING_ENABLED', false),
               'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
           ],
           'pulse_ingest_interval' => env('REVERB_PULSE_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),
               'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000),
           ],
       ],

   ],
@joedixon
Copy link
Collaborator

What happens if you try https://websockets.amypo.com:8080 in the browser?

@amypo-tech
Copy link
Author

amypo-tech commented Mar 21, 2024

What happens if you try https://websockets.amypo.com:8080 in the browser?

When I visit this URL it gives me "Not Found" error in a blank page 404

@iqbalhasandev
Copy link

do you use cyberpanel ?

@amypo-tech
Copy link
Author

do you use cyberpanel ?

No

@HelixForge
Copy link

image
I have the same sort of problem with reverb/pusher I get a 404 (screenshot from pusher)

It works fine for me on local but I get this error on the server.

The server is with DO and Laravel Forge with the switch turned on. I'm using the same settings as amypo-tech OP for Reverb

@iqbalhasandev
Copy link

iqbalhasandev commented Mar 24, 2024

Setting Up Subdomain for Reverb Server

To integrate Reverb with your Laravel application, follow these steps:

Create a Subdomain: Begin by creating a subdomain for your Reverb server. This can typically be done through your domain registrar or hosting provider's control panel. Let's say your subdomain is reverb.example.com.

Configure Proxy Settings: Set up your web server to proxy requests from your subdomain to the Reverb server's IP and port. Assuming the Reverb server's default IP is 0.0.0.0 and port is 8080, configure the proxy settings to forward requests from reverb.example.com to 0.0.0.0:8080.

Configure Laravel Echo: Update your Laravel Echo configuration to use the newly created subdomain reverb.example.com and the default HTTP port 80. This ensures that Laravel Echo can communicate with your Reverb server through the designated subdomain.

VITE_REVERB_HOST='reverb.example.com'
VITE_REVERB_PORT=80
VITE_REVERB_SCHEME=http

Adjust Reverb Configuration: In your Laravel application's configuration file (typically .env), specify the Reverb host and port. Update the REVERB_HOST to "localhost" and REVERB_PORT to 8080.

Your .env file should look like this:

Copy code
REVERB_HOST="localhost"
REVERB_PORT=8080

Test Connection: After making these configurations, test the connection by sending an event to Reverb. If everything is set up correctly, your Laravel application should be able to communicate with the Reverb server via the configured subdomain and port.

By following these steps, you should have successfully integrated Reverb with your Laravel application using a subdomain-based approach.

@shazeedul
Copy link

Setting Up Subdomain for Reverb Server

To integrate Reverb with your Laravel application, follow these steps:

Create a Subdomain: Begin by creating a subdomain for your Reverb server. This can typically be done through your domain registrar or hosting provider's control panel. Let's say your subdomain is reverb.example.com.

Configure Proxy Settings: Set up your web server to proxy requests from your subdomain to the Reverb server's IP and port. Assuming the Reverb server's default IP is 0.0.0.0 and port is 8080, configure the proxy settings to forward requests from reverb.example.com to 0.0.0.0:8080.

Configure Laravel Echo: Update your Laravel Echo configuration to use the newly created subdomain reverb.example.com and the default HTTP port 80. This ensures that Laravel Echo can communicate with your Reverb server through the designated subdomain.

VITE_REVERB_APP_KEY=b0cybxxzafpfjakf6ril
VITE_REVERB_HOST='reverb.example.com'
VITE_REVERB_PORT=80
VITE_REVERB_SCHEME=http

Adjust Reverb Configuration: In your Laravel application's configuration file (typically .env), specify the Reverb host and port. Update the REVERB_HOST to "localhost" and REVERB_PORT to 8080.

Your .env file should look like this:

Copy code
REVERB_HOST="localhost"
REVERB_PORT=8080

Test Connection: After making these configurations, test the connection by sending an event to Reverb. If everything is set up correctly, your Laravel application should be able to communicate with the Reverb server via the configured subdomain and port.

By following these steps, you should have successfully integrated Reverb with your Laravel application using a subdomain-based approach.

it works great.

@adrum
Copy link

adrum commented Mar 26, 2024

We were able to configure ours to use the same domain name as our app by using the following setup:

# NGINX config
...
    location /ws/ {
        proxy_pass                          http://127.0.0.1:6050/;
        
        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";
    }
# .env
...
REVERB_SERVER_HOST=127.0.0.1
REVERB_SERVER_PORT=6050

REVERB_APP_ID=1234
REVERB_APP_KEY=key
REVERB_APP_SECRET=secret
REVERB_HOST=127.0.0.1
REVERB_PORT=6050
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="example.com"
VITE_REVERB_PORT="443"
VITE_REVERB_SCHEME="https"
VITE_REVERB_PATH="/ws"
# echo.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,
  wsPath: import.meta.env.VITE_REVERB_PATH ?? "/",
  forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https",
  enabledTransports: ["ws", "wss"],
});

@joedixon
Copy link
Collaborator

@adrum, I'm pretty sure that configuration will result in a 404 when attempting to broadcast a message from the server as the server routes must all be prefixed with /apps.

@amypo-tech, can you share your Nginx (or equivalent) configuration?

@amypo-tech
Copy link
Author

@adrum, I'm pretty sure that configuration will result in a 404 when attempting to broadcast a message from the server as the server routes must all be prefixed with /apps.

@amypo-tech, can you share your Nginx (or equivalent) configuration?

```

<VirtualHost *:80>
ServerAdmin [email protected]
ServerName websockets.amypo.com
ServerAlias www.websockets.amypo.com
DocumentRoot /var/www/reverb.amypo.com

<Directory /var/www/reverb.amypo.com>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Require all granted
</Directory>

<IfModule mod_proxy.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/app
RewriteRule ^(.*)$ http://0.0.0.0:8080/$1 [P]

<Proxy http://0.0.0.0:8080>
    ProxyPreserveHost On
    ProxyPassReverse /
    ProxyPassReverseCookiePath / /app
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/websockets.amypo.com_error.log
CustomLog ${APACHE_LOG_DIR}/websockets.amypo.com_access.log combined

RewriteEngine on
RewriteCond %{SERVER_NAME} =www.websockets.amypo.com [OR]
RewriteCond %{SERVER_NAME} =websockets.amypo.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

@amypo-tech
Copy link
Author

I have the same type of issue. nothing was helpful.

implementing web-sockets in production is like finding water in mars.

All the possible ways i have tried.

  1. all the possible .env configurations
  2. nginx reverse proxy configuration
  3. config/reverb.php config changes with and without certs and different ports

if some one gives a proper setup or guide from start to end would help for production.

in local it took only few minutes to implement. this is the same thing happened before launch of reverb. waiting nearly 6 months to implement in production

@dominik-eller
Copy link

dominik-eller commented Mar 27, 2024

Having the same error using Laravel Forge.
I am getting "invalid message format" when subscribing to a channel
Bildschirmfoto 2024-03-27 um 03 00 29

and when I notify a user via broadcast I am getting a internal server error:

production.ERROR: Pusher error: Internal server error.. {"exception":"[object] (Illuminate\\Broadcasting\\BroadcastException(code: 0): Pusher error: Internal server error.. at /home/***/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php:164)

EDIT:
I deactivated and activated Laravel Reverb in die Laravel Forge Application Panel and restarted nginx and it is working now. Maybe the nginx config for the reverse proxy was not set correctly or nginx was not reloaded automatically.

The working configuration in my .env. file:

REVERB_APP_ID=***
REVERB_APP_KEY=***
REVERB_APP_SECRET=***
REVERB_HOST=127.0.0.1
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST=ws.domain.tld
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https

@joedixon
Copy link
Collaborator

@amypo-tech It's the same issue. You are only serving the /app route and not the /apps route. Also, configuring your server in this way will prevent other routes being accessed:

protected static function pusherRoutes(): RouteCollection
{
$routes = new RouteCollection;
$routes->add('sockets', Route::get('/app/{appKey}', new PusherController(app(PusherServer::class), app(ApplicationProvider::class))));
$routes->add('events', Route::post('/apps/{appId}/events', new EventsController));
$routes->add('events_batch', Route::post('/apps/{appId}/batch_events', new EventsBatchController));
$routes->add('connections', Route::get('/apps/{appId}/connections', new ConnectionsController));
$routes->add('channels', Route::get('/apps/{appId}/channels', new ChannelsController));
$routes->add('channel', Route::get('/apps/{appId}/channels/{channel}', new ChannelController));
$routes->add('channel_users', Route::get('/apps/{appId}/channels/{channel}/users', new ChannelUsersController));
$routes->add('users_terminate', Route::post('/apps/{appId}/users/{userId}/terminate_connections', new UsersTerminateController));
return $routes;
}

We recommed setting up your server to serve all paths.

@adrum
Copy link

adrum commented Mar 27, 2024

@adrum, I'm pretty sure that configuration will result in a 404 when attempting to broadcast a message from the server as the server routes must all be prefixed with /apps.

@amypo-tech, can you share your Nginx (or equivalent) configuration?

@joedixon that setup I provided is actively working for us. The slash at the end of the proxy_pass directive apparently chops off the /ws from the path before sending it upstream.

The server is bypassing NGINX when broadcasting, so it sends it with the correct path.

I more or less just wanted to provide another working example.

@starter-dev
Copy link

starter-dev commented Apr 30, 2024

We were able to configure ours to use the same domain name as our app by using the following setup:

# NGINX config
...
    location /ws/ {
        proxy_pass                          http://127.0.0.1:6050/;
        
        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";
    }
# .env
...
REVERB_SERVER_HOST=127.0.0.1
REVERB_SERVER_PORT=6050

REVERB_APP_ID=1234
REVERB_APP_KEY=key
REVERB_APP_SECRET=secret
REVERB_HOST=127.0.0.1
REVERB_PORT=6050
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="example.com"
VITE_REVERB_PORT="443"
VITE_REVERB_SCHEME="https"
VITE_REVERB_PATH="/ws"
# echo.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,
  wsPath: import.meta.env.VITE_REVERB_PATH ?? "/",
  forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https",
  enabledTransports: ["ws", "wss"],
});

Can I view the changes you made to the config/reverb.php and config/broadcasting.php files, if you have any? Thanks.

@antoninmasek
Copy link

Hello,

yesterday I was also struggling a bit to make Reverb work with Forge, but in the end, I figured out a way to make it work. For me, the issue was that I did not have an SSL certificate for the subdomain (Public Hostname) that you set when toggling on Reverb in Forge.

I wrote an article about it so maybe it can help someone. You can jump to the end of the article for TLDR so you don't have to read the entire thing. Probably not the best solution, but for now it solved the issue for me.

https://tonymasek.com/blog/how-to-make-laravel-reverb-work-on-laravel-forge

@dominik-eller
Copy link

Hello,

yesterday I was also struggling a bit to make Reverb work with Forge, but in the end, I figured out a way to make it work. For me, the issue was that I did not have an SSL certificate for the subdomain (Public Hostname) that you set when toggling on Reverb in Forge.

I wrote an article about it so maybe it can help someone. You can jump to the end of the article for TLDR so you don't have to read the entire thing. Probably not the best solution, but for now it solved the issue for me.

https://tonymasek.com/blog/how-to-make-laravel-reverb-work-on-laravel-forge

Thanks for your time and for sharing your results. Great. I will give it a try the next time I have to deploy a Reverb server to Laravel Forge.

@antoninmasek
Copy link

Thanks for your time and for sharing your results. Great. I will give it a try the next time I have to deploy a Reverb server to Laravel Forge.

No problem, hopefully, it will help you as well 😊

@gamboitaygb
Copy link

This isssue is closed, but I share my solution here https://github.com/laravel/framework/discussions/50675

@aftabkhaliq86
Copy link

aftabkhaliq86 commented Jun 9, 2024

if anyone struggling to make it work on apache cpanel follow this

make sub domain with SSL installed on that domain

env should be like this
REVERB_HOST="localhost" REVERB_PORT=8080 REVERB_SCHEME=http

VITE_REVERB_HOST="socket.ecample.com" VITE_REVERB_PORT=8080 VITE_REVERB_SCHEME="${REVERB_SCHEME}"

for SSL files
For both purchased and free WHM/cPanel made it easy, Certificate and Private key placed in SSL/TSL status >view Certificates >select your subdomain and copy
copy both private and public key and paste them in file with extension.pem

and in reverb config file add this

'options' => [ 'tls' => [ 'local_cert' => '/path/to/file_you_just_created_with_pem_extension.pem' ], ],

happy coding

@sgms-top
Copy link

do you use cyberpanel ?

i have same problem and i'm using CyberPanel

@jhalarde
Copy link

@amypo-tech It's the same issue. You are only serving the /app route and not the /apps route. Also, configuring your server in this way will prevent other routes being accessed:

protected static function pusherRoutes(): RouteCollection
{
$routes = new RouteCollection;
$routes->add('sockets', Route::get('/app/{appKey}', new PusherController(app(PusherServer::class), app(ApplicationProvider::class))));
$routes->add('events', Route::post('/apps/{appId}/events', new EventsController));
$routes->add('events_batch', Route::post('/apps/{appId}/batch_events', new EventsBatchController));
$routes->add('connections', Route::get('/apps/{appId}/connections', new ConnectionsController));
$routes->add('channels', Route::get('/apps/{appId}/channels', new ChannelsController));
$routes->add('channel', Route::get('/apps/{appId}/channels/{channel}', new ChannelController));
$routes->add('channel_users', Route::get('/apps/{appId}/channels/{channel}/users', new ChannelUsersController));
$routes->add('users_terminate', Route::post('/apps/{appId}/users/{userId}/terminate_connections', new UsersTerminateController));
return $routes;
}

We recommed setting up your server to serve all paths.

thanks for this man, but why in the world is this not in the docs, ive been struggling to fix the issue for a week.

@joedixon
Copy link
Collaborator

@jhalarde thanks for the feedback. The docs do suggest to use / as the location, but I understand that's not always possible so I will get the docs updated to call this out.

@abrhamsw
Copy link

abrhamsw commented Jun 27, 2024

Setting Up Subdomain for Reverb Server

To integrate Reverb with your Laravel application, follow these steps:

Create a Subdomain: Begin by creating a subdomain for your Reverb server. This can typically be done through your domain registrar or hosting provider's control panel. Let's say your subdomain is reverb.example.com.

Configure Proxy Settings: Set up your web server to proxy requests from your subdomain to the Reverb server's IP and port. Assuming the Reverb server's default IP is 0.0.0.0 and port is 8080, configure the proxy settings to forward requests from reverb.example.com to 0.0.0.0:8080.

Configure Laravel Echo: Update your Laravel Echo configuration to use the newly created subdomain reverb.example.com and the default HTTP port 80. This ensures that Laravel Echo can communicate with your Reverb server through the designated subdomain.

VITE_REVERB_HOST='reverb.example.com'
VITE_REVERB_PORT=80
VITE_REVERB_SCHEME=http

Adjust Reverb Configuration: In your Laravel application's configuration file (typically .env), specify the Reverb host and port. Update the REVERB_HOST to "localhost" and REVERB_PORT to 8080.

Your .env file should look like this:

Copy code
REVERB_HOST="localhost"
REVERB_PORT=8080

Test Connection: After making these configurations, test the connection by sending an event to Reverb. If everything is set up correctly, your Laravel application should be able to communicate with the Reverb server via the configured subdomain and port.

By following these steps, you should have successfully integrated Reverb with your Laravel application using a subdomain-based approach.

Can you share your Proxy Configuration? It is not working on my side

  • Share hosting/ cPanel Apache Server The only allowed configuration is .htaccess file
  • domain: reverb.mydomain.com

@iandk
Copy link

iandk commented Jul 2, 2024

In case anyone is having issues getting it to work with Caddy

# Caddyfile
yourdomain.tld {
    root * /home/web/public/public
    file_server
    encode gzip
    php_fastcgi unix//run/php/php8.2-web-fpm.sock {
        split .php
        index index.php
    }
    header {
        Strict-Transport-Security max-age=31536000
        Permissions-Policy interest-cohort=()
        X-Content-Type-Options nosniff
        X-Frame-Options SAMEORIGIN
        Referrer-Policy no-referrer
        X-XSS-Protection "1; mode=block"
        X-Permitted-Cross-Domain-Policies none
        X-Robots-Tag "noindex, nofollow"
        -X-Powered-By
    }
    handle_path /.well-known/acme-challenge/* {
        try_files {path} {path}/
        file_server
    }
    handle_path /.well-known/pki-validation/* {
        try_files {path} {path}/
        file_server
    }
    redir /.well-known/* /index.php{uri} 301

}


ws.yourdomain.tld {
    reverse_proxy 127.0.0.1:8080
}
# .env
VITE_APP_NAME="${APP_NAME}"

REVERB_APP_ID= XXXXXXXXX
REVERB_APP_KEY=XXXXXXXXX
REVERB_APP_SECRET= XXXXXXXXX
REVERB_HOST="ws.yourdomain.tld"
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}"

@usamaJ17
Copy link

usamaJ17 commented Sep 6, 2024

if anyone struggling to make it work on apache cpanel follow this

make sub domain with SSL installed on that domain

env should be like this REVERB_HOST="localhost" REVERB_PORT=8080 REVERB_SCHEME=http

VITE_REVERB_HOST="socket.ecample.com" VITE_REVERB_PORT=8080 VITE_REVERB_SCHEME="${REVERB_SCHEME}"

for SSL files For both purchased and free WHM/cPanel made it easy, Certificate and Private key placed in SSL/TSL status >view Certificates >select your subdomain and copy copy both private and public key and paste them in file with extension.pem

and in reverb config file add this

'options' => [ 'tls' => [ 'local_cert' => '/path/to/file_you_just_created_with_pem_extension.pem' ], ],

happy coding

@aftabkhaliq86 can you please explain your solution a bit more, I am on Cpanel, and apache, and struggling to implement it on production.

@xlcrr
Copy link

xlcrr commented Sep 15, 2024

Hi, it took about 2 weeks but I finally got reverb working on a pre-production staging environment and wanted to share my tips

  1. In your DNS add a CNAME record for "ws.mysite.com"
  2. In forge, go to your site -> settings -> add an alias to your main site for "ws.mysite.com"
  3. In forge, delete your SSL cert and create a new one with 2 values "mysite.com, ws.mysite.com"
  4. In forge, turn on Reverb with the default settings
  5. In forge, open the default Nginx config for your site and remove the "ws.mysite.com" so it looks like this
  6. Add these values to your .env
REVERB_HOST=ws.mysite.com
REVERB_PORT=443
REVERB_SCHEME="https"
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/olmdev.online/before/*;

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name mysite.com; # ws.mysite.com removed
  1. Add npm run build and reverb:restart to your deployment script so it looks like this
...

npm run build

$FORGE_PHP artisan reverb:restart

My config if it helps:

reverb.php

    'servers' => [
        'reverb' => [
            'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
            'port' => env('REVERB_SERVER_PORT', 8080),
            '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),
        ],
    ],

broadcasting.php

        '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',
            ],
        ],

@MohitNN
Copy link

MohitNN commented Sep 16, 2024

do you use cyberpanel ?

I have use cyberpanle so can give me step for setup reverb

@jihad28
Copy link

jihad28 commented Sep 16, 2024

Here is my solution for Secure Application (SSL)

System info:

apache2
ssl certificate (letsencrypt)

First update the .env file like this

REVERB_HOST=0.0.0.0
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_HOST="yourdomain.com" // Replace it with your domain
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https

Then run these commands

php artisan config:cache
npm run build

Now to update the apache configuration file to allow the WebSocket

First enable apache proxy module using these commands

sudo a2enmod proxy
sudo a2enmod proxy_wstunnel
sudo a2enmod proxy_http

This is my site config

<VirtualHost *:80>
	ServerName yourdomain.com
	ServerAdmin [email protected]

	DocumentRoot /srv/your-path/public

	<Directory /srv/your-path/public/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
		Require all granted
	</Directory>

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =yourdomain.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

  

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerName yourdomain.com
	ServerAdmin [email protected]
  
	DocumentRoot /srv/your-path/public

	<Directory /srv/your-path/public/>
	Options Indexes FollowSymLinks MultiViews
	AllowOverride All
	Order allow,deny
	allow from all
	Require all granted
	</Directory>

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
	Include /etc/letsencrypt/options-ssl-apache.conf

	# WebSocket proxying
	ProxyPreserveHost On
	ProxyPass /app/ ws://0.0.0.0:8080/app/
	ProxyPassReverse /app/ ws://0.0.0.0:8080/app/
</VirtualHost>
</IfModule>

Replace

  • yourdomain.com with your domain

  • /srv/your-path/public with your path

  • [email protected] with your email (optional)

Or you can just add this code inside the <VirtualHost *:443> tag

ProxyPreserveHost On
ProxyPass /app/ ws://0.0.0.0:8080/app/
ProxyPassReverse /app/ ws://0.0.0.0:8080/app/

Then run this command to load the new configuration
sudo systemctl reload apache2

And remember don't forget to start reverb

php artisan reverb:start

And you are good to go.
Hope this helps

@usamaJ17
Copy link

Here is my solution for Secure Application (SSL)

System info:

apache2 ssl certificate (letsencrypt)

First update the .env file like this

REVERB_HOST=0.0.0.0
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_HOST="yourdomain.com" // Replace it with your domain
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https

Then run these commands

php artisan config:cache
npm run build

Now to update the apache configuration file to allow the WebSocket

First enable apache proxy module using these commands

sudo a2enmod proxy
sudo a2enmod proxy_wstunnel
sudo a2enmod proxy_http

This is my site config

<VirtualHost *:80>
	ServerName yourdomain.com
	ServerAdmin [email protected]

	DocumentRoot /srv/your-path/public

	<Directory /srv/your-path/public/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
		Require all granted
	</Directory>

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =yourdomain.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

  

<IfModule mod_ssl.c>
<VirtualHost *:443>
	ServerName yourdomain.com
	ServerAdmin [email protected]
  
	DocumentRoot /srv/your-path/public

	<Directory /srv/your-path/public/>
	Options Indexes FollowSymLinks MultiViews
	AllowOverride All
	Order allow,deny
	allow from all
	Require all granted
	</Directory>

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
	Include /etc/letsencrypt/options-ssl-apache.conf

	# WebSocket proxying
	ProxyPreserveHost On
	ProxyPass /app/ ws://0.0.0.0:8080/app/
	ProxyPassReverse /app/ ws://0.0.0.0:8080/app/
</VirtualHost>
</IfModule>

Replace

  • yourdomain.com with your domain
  • /srv/your-path/public with your path
  • [email protected] with your email (optional)

Or you can just add this code inside the <VirtualHost *:443> tag

ProxyPreserveHost On
ProxyPass /app/ ws://0.0.0.0:8080/app/
ProxyPassReverse /app/ ws://0.0.0.0:8080/app/

Then run this command to load the new configuration sudo systemctl reload apache2

And remember don't forget to start reverb

php artisan reverb:start

And you are good to go. Hope this helps

@jihad28 thank you so much for your efforts.. it makes easier for me.. BTW i set it up on azure.. and created a rabbitmq container for queue .. and now thinking of creating a seprate container for reverb.. although I am not sure if we can do that.. but will try that..

@Dinesh-loma
Copy link

Dinesh-loma commented Oct 19, 2024

@joedixon I have different issue(can say weird issue).

I have same configuration like you. Only difference is that I using Nginx server. In my case, I deployed code to test server. when check on my personal machine reverb work.(auth api fired and ping-pong happend). When check on other systems reverb not works. Auth api(/broadcasting/auth) not fired and socket connection shows finished.
I am also stuck. Somebody please help @taylorotwell @JeffreyWay @joedixon

Vuejs .env

VITE_PORT = 3200
VITE_REVERB_APP_KEY=**********
VITE_REVERB_PORT=9080
VITE_REVERB_SCHEME=https

vuejs config.js

var BASE_URL = 'https://domain.com/api';
var REVERB_HOST = 'domain.com';

Note: REVERB_HOST value is same as domain name.

Reverb.php
`<?php

return [

/*
|--------------------------------------------------------------------------
| Default Reverb Server
|--------------------------------------------------------------------------
|
| This option controls the default server used by Reverb to handle
| incoming messages as well as broadcasting message to all your
| connected clients. At this time only "reverb" is supported.
|
*/

'default' => env('REVERB_SERVER', 'reverb'),

/*
|--------------------------------------------------------------------------
| Reverb Servers
|--------------------------------------------------------------------------
|
| Here you may define details for each of the supported Reverb servers.
| Each server has its own configuration options that are defined in
| the array below. You should ensure all the options are present.
|
*/

'servers' => [

    'reverb' => [
        'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
        'port' => env('REVERB_SERVER_PORT', 8080),
        'hostname' => env('REVERB_HOST'),
        'options' => [
            'tls' => [
                'local_cert' => env('CERT_URL'),
                'local_pk' => env('PK_URL'),
            ],
        ],
        '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', '******'),
                'port' => env('REDIS_PORT', '****'),
                '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),
    ],

],

/*
|--------------------------------------------------------------------------
| Reverb Applications
|--------------------------------------------------------------------------
|
| Here you may define how Reverb applications are managed. If you choose
| to use the "config" provider, you may define an array of apps which
| your server will support, including their connection credentials.
|
*/

'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),
            'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000),
        ],
    ],

],

];
`

laravel .env

REVERB_APP_ID=*******
REVERB_APP_KEY=*****
REVERB_APP_SECRET=*****
REVERB_HOST='domain.com'
REVERB_PORT=9080
REVERB_SCHEME=https
CERT_URL='{path_to_project}/fullchain.pem'
PK_URL='{path_to_project}/privkey.pem'

vuejs echo connection code


export default function useEchoConnection() {
    const userStore = useUserStore();
    const echoInstance = ref<Echo | null>(null);

    const initializeEcho = () => {
        window.Pusher = Pusher;
        echoInstance.value = new Echo({
            broadcaster: 'reverb',
            key: import.meta.env.VITE_REVERB_APP_KEY,
            wsHost: window.REVERB_HOST,
            wsPort: import.meta.env.VITE_REVERB_PORT,
            wssPort: import.meta.env.VITE_REVERB_PORT,
            forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
            enabledTransports: ['ws', 'wss'],
            authorizer: (channel, options) => {
                return {
                    authorize: (socketId, callback) => {
                        axios
                            .post(
                                `${window.BASE_URL}/broadcasting/auth`,
                                {
                                    socket_id: socketId,
                                    channel_name: channel.name,
                                },
                                {
                                    headers: {
                                        Authorization: `Bearer ${userStore.JWT}`,
                                    },
                                },
                            )
                            .then(response => {
                                callback(false, response.data);
                            })
                            .catch(error => {
                                callback(true, error);
                            });
                    },
                };
            },
        });
    };

Apache configuration.

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName abc.com
        ServerAdmin [email protected]
        DocumentRoot {path_to_project}
        <Directory {path_to_project} >
                Options FollowSymLinks MultiViews
            AllowOverride All
            Order allow,deny
            allow from all
            Require all granted
        </Directory>

SSLCertificateFile                        path_url/fullchain.pem
SSLCertificateKeyFile            path_url/privkey.pem
Include                     path_url/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Update:
websocket connected and ping-pong happened , messages also received in all other systems but only in firefox browser.
on Chrome web-socket not working on other systems . But on my system it's working in chrome.

@Dinesh-loma
Copy link

Dinesh-loma commented Nov 12, 2024

I found the solution.
When move from local to dev or production, use sub-domain for web-socket.

.env file code will be like this

REVERB_HOST=subdomain
REVERB_PORT=443
REVERB_SCHEME=https

In vuejs

VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https
VITE_REVERB_HOST=subdomain 

And in last add proxy setting for web-socket
for example in nginx-

location / {
        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://0.0.0.0:8080;
    }

@francoism90
Copy link

francoism90 commented Dec 17, 2024

So in case anyone have this issue with Podman (or Docker):

  1. Make sure if you proxy, they are both attached to the same network(s). e.g. you may have network=internal.network and network=frontoffice.network. You need to attach both to your Laravel (FrankenPHP) container.

  2. This is what I'm using in my .env with Caddy as proxy to a Laravel container:

REVERB_APP_ID=app-id
REVERB_APP_KEY=app-key
REVERB_APP_SECRET=app-secret
REVERB_HOST=localhost
REVERB_PORT=8080 # Make sure this value is also used for REVERB_SERVER_PORT
REVERB_SCHEME=http

VITE_APP_NAME="${APP_NAME}"
VITE_APP_URL="${APP_URL}"
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="ws.example.com"
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https
  1. I'm using Caddy and Podman Quadlet:
ws.example.com {
	tls internal
	reverse_proxy systemd-laravel:8080
}
  1. Your echo.js should look something like this:
import Echo from "laravel-echo";
import Pusher from "pusher-js";

window.Pusher = Pusher;

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"],
});

Mixing http/https is not supported. You cannot force ws on https for example. Make sure both your app and reverb are on the same scheme.

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

No branches or pull requests