I can make the laravel-websocket works local and on forge without SSL. I want to make it work when it with SSL on Forge as well. I read some articles and the officeal documnet to make it work. The follwoing is my sernario.This take me a long to make it work. Thank Alex Bouma's article finaly make my case work.
- One stand alone Weksocket Server
- One Backend Server
- One Client System Server
- Website Servers
All the examples I saw online are all make all the service stay on one sever. So it confunse me. and it turns out with some litte tweek I can make it work.
composer create-project laravel/laravel laravel-websocket-server
Create a Laravel Projectcomposer require beyondcode/laravel-websockets
Install the Laravel Websocket packeage and following the documents to publish the necessary file and setting.
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
- Update the
.env
file. You can whatever you want if you are not going back to use Pusher . It been used inwebsockets.php
andbroadcasting.php
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=[YOUR APP ID]
PUSHER_APP_KEY=[YOU APP KEY]
PUSHER_APP_SECRET=[YOUR APP SECRET]
- Edit the
websocket.php
for the stand alone websocket sever.broadcasting.php
won't matters. edit the following section to limit the connection origins and since we are using NGINX to help us to do the SSL heavy work for us. We can leave the SSL section unchange
/*
* This array contains the hosts of which you want to allow incoming requests.
* Leave this empty if you want to accept requests from all hosts.
*/
'allowed_origins' => [
'test-website.com'
],
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => null,//'/etc/nginx/ssl/ws.thebcr.com/527710/server.crt',
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => null,//'/etc/nginx/ssl/ws.thebcr.com/527710/server.key',
/*
* Passphrase for your local_cert file.
*/
'passphrase' => null,
// 'verify_peer' =>false,
],
I am going to use separate domain. The websocket will stay on it own domain and own server. After deployed your server to Forge then added a Let's Encrypts cettificate. All can done on Forge interface and you good to go(Forge is awesome)
Since I am using normal 443 port to moniter the traffic provide by the package. You just to need to
copy and paste the follow NGINX config after the to make it work. replace
laravel-websockets.example.com
to your own domain name. and make sure the
ssl_certificate
ssl_certificate_key
are matched with the port 443 part
section The content will be different case by case
/etc/nginx/ssl/laravel-websockets.example.com/473558/server.crt
/etc/nginx/ssl/laravel-websockets.example.com/473558/server.key
please update it according to your case.
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/laravel-websockets.example.com/before/*;
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name laravel-websockets.example.com;
root /home/forge/laravel-websockets.example.com/public;
# FORGE SSL (DO NOT REMOVE!)
ssl_certificate /etc/nginx/ssl/laravel-websockets.example.com/473558/server.crt;
ssl_certificate_key /etc/nginx/ssl/laravel-websockets.example.com/473558/server.key;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/laravel-websockets-example.alexbouma.me/server/*;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/laravel-websockets-example.alexbouma.me-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
server {
listen 6002 ssl;
listen [::]:6002 ssl;
server_name laravel-websockets.example.com;
root /home/forge/laravel-websockets.example.com/public;
# FORGE SSL (DO NOT REMOVE!)
ssl_certificate /etc/nginx/ssl/laravel-websockets-example.alexbouma.me/473558/server.crt;
ssl_certificate_key /etc/nginx/ssl/laravel-websockets-example.alexbouma.me/473558/server.key;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/laravel-websockets-example.alexbouma.me/server/*;
location / {
proxy_pass http://127.0.0.1:6001;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/laravel-websockets-example.alexbouma.me-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Plase be note that we are using port 6002
you can pick what everyever you want, just make sure
you open that port on you forge server. after that make sure your server reload or runing
php artisan websockets:serve
On December 2019, I migrated my web socket server to another region, and it didn't work. I can not find out why at beginning. By the end I figure it out. I was using Clouldflare to do proxy , so it can not work at begining. You just simply switch the DNS setting from Proxy to DNS ONLY should resolve the issue.
The following is the orignal Text from Alex Bouma article talk about port. I think it is important
I hear ya! Let me explain a bit, it will hopefully all make sense afterwards.
Here is the thing, opening an port on your server can only be done by only one
application at a time (technically that is not true, but let's keep it simple here)
. So if we would let NGINX listen on port 6001 we cannot start our websockets
server also on port 6001
since it will conflict with NGINX and the other way
around, therefore we let NGINX listen on port 6002
and let it proxy
(NGINX is a reverse proxy after all) all that traffic to port 6001
(the websockets server) over plain http. Stripping away the SSL so the websockets
server has no need to know how to handle SSL.
So NGINX will handle all the SSL magic and forward the traffic in plain http to
port 6001
on your server where the websockets server is listening for requests.
The reason we are not configuring any SSL in the websockets.php config and we define
the scheme in our broadcasting.php as http and use port 6001
is to bypass NGINX and
directly communicate with the websockets server locally without needing SSL which
faster (and easier to configure and maintain).
Websockets are not allowed to connect on any port you can think of...
as Stack Overflow found out a lot of them are blocked (by browsers) and while
testing I used port 6000
, which also seems blocked, that why I used
port 6002
which works just fine.
I had a hard time figuring out what was going on since no visible errors are thrown when you use a port that is blocked by the browser :( But looking at the pusher events I saw the error which mumbled about the port I choose not being allowed for a websockets connection.
You can see the events of the Pusher client by running
window.Echo.connector.pusher.connection.timeline.events
in the developer console and inspecting the entries.
- install the require package to make it work
composer require pusher/pusher-php-server "~3.0"
BROADCAST_DRIVER=pusher
update the.env
file
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'host' => 'laravel-websockets.example.com',
'port' => 6002,
'scheme' => 'https'
],
],
- that is all you need to do here
- install Laravel Echo and pusher
npm install --save laravel-echo pusher-js
- update
app.js
and thennpm run production
window.Echo = new Echo({
broadcaster: "pusher",
key: "b12fcbcf3175a9c80082",
cluster: "mt1",
encrypted: true,
wsHost: "laravel-websockets.example.com",
wsPort: 6002,
wssPort: 6002,
disableStats: true,
enabledTransports: ['ws', 'wss'],
});
Dude you saved my life 😒 Thanks! After 12 hours of struggle..
6002 -> 6001 proxy <3