laravel / reverb

Laravel Reverb provides a real-time WebSocket communication backend for Laravel applications.
https://reverb.laravel.com
MIT License
1.05k stars 76 forks source link

Laravel Reverb in Production Server #107

Closed amypo-tech closed 5 months ago

amypo-tech commented 5 months ago

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

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="hello@example.com"
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 commented 5 months ago

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

amypo-tech commented 5 months ago

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 commented 5 months ago

do you use cyberpanel ?

amypo-tech commented 5 months ago

do you use cyberpanel ?

No

Crazzz0ne commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

@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 commented 5 months ago

@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 webmaster@websockets.amypo.com 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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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

https://github.com/laravel/reverb/blob/9e2bd2a37761d906719b31416d6d5291949812de/src/Servers/Reverb/Factory.php#L97-L111

We recommed setting up your server to serve all paths.

adrum commented 5 months ago

@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 commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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

aftabkhaliq86 commented 3 months ago

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 commented 2 months ago

do you use cyberpanel ?

i have same problem and i'm using CyberPanel

jhalarde commented 2 months ago

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

https://github.com/laravel/reverb/blob/9e2bd2a37761d906719b31416d6d5291949812de/src/Servers/Reverb/Factory.php#L97-L111

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 commented 2 months ago

@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 commented 2 months ago

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

iandk commented 2 months ago

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 commented 6 days ago

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.