Laravel Websockets + Cloudflare + Digital Ocean won't work!
Hello everyone, did anyone here ever got laravel websockets + cloudflare + do to work? Recently migratet my dns and proxy to cloudflare for the protection but since then my websockets don't work anymore, they where working fine for over a year prior. So here is what I got and what I tried. (I really have no idea anymore). Im really thankfull for help, a config that worked for some of you with that combination or more ideas to troubleshoot this whole thing ...
The error message :)
app-jicTCnNS.js:39 WebSocket connection to 'wss://demo.com:2053/app/demo?protocol=7&client=js&version=8.3.0&flash=false' failed: WebSocket is closed before the connection is established.
Laravel Websockets & pusher config:
// bootstrap.js
window.Echo = new Echo({
broadcaster: "pusher",
key: "demo",
cluster: "mt1",
wsHost: window.location.hostname,
wssHost: window.location.hostname,
wsPort: 2053,
wssPort: 2053,
encrypted: true,
disableStats: false,
forceTLS: true,
enabledTransports: ["ws", "wss"],
});
<?php
// websockets.php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
return [
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
],
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
'allowed_origins' => [],
'max_request_size_in_kb' => 250,
'path' => 'laravel-websockets',
'middleware' => [
'web',
Authorize::class,
],
'statistics' => [
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,
'interval_in_seconds' => 300,
'delete_statistics_older_than_days' => 60,
'perform_dns_lookup' => false,
],
'ssl' => [
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', '/etc/letsencrypt/live/mykey/fullchain.pem'),
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', '/etc/letsencrypt/live/mykey/privkey.pem'),
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
<?php
return [
'default' => env('BROADCAST_DRIVER', 'null'),
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'encrypted' => env('LARAVEL_WEBSOCKETS_ENCRYPTED', TRUE),
'useTLS' => env('LARAVEL_WEBSOCKETS_USETLS', TRUE),
'cluster' => env('PUSHER_APP_CLUSTER'),
'host' => env('LARAVEL_WEBSOCKETS_HOST', 'demo'),
'port' => env('LARAVEL_PUSHER_PORT', 443),
'scheme' => env('LARAVEL_PUSHER_SCHEME', "https"),
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
],
],
],
....
],
];
// composer.json
"pusher/pusher-php-server": "^7.2.4",
"beyondcode/laravel-websockets": "^1.14.1",
// package.json
"laravel-echo": "^1.16.1",
"pusher-js": "^8.3.0",
On the Digital Ocean Droplet
nginx
server {
server_name www.demo.com;
return 301 $scheme://demo.com$request_uri;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/demo.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/demo.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
listen 80;
server_name demo www.demo.com;
return 301 https://demo.com$request_uri;
}
server {
server_name demo.com;
root /var/www/demo/public;
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;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.css {
add_header Content-Type text/css;
}
location ~ \.js {
add_header Content-Type application/x-javascript;
}
location ~ .php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# WebSocket Location Block - Ensure it's above the `location /` block
location /app {
proxy_pass http://127.0.0.1:2053;
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;
proxy_read_timeout 600;
proxy_connect_timeout 600;
proxy_redirect off;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
listen 443 ssl; # managed by Certbot
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/demo/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/demo/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
.env
PUSHER_APP_ID=demo
PUSHER_APP_KEY=demo
PUSHER_APP_SECRET=demo
PUSHER_APP_CLUSTER=mt1
LARAVEL_WEBSOCKETS_PORT=2053
LARAVEL_PUSHER_PORT=2053
LARAVEL_WEBSOCKETS_HOST="demo.com"
LARAVEL_WEBSOCKETS_USETLS=true
LARAVEL_WEBSOCKETS_ENCRYPTED=true
LARAVEL_PUSHER_SCHEME="https"
The port is allowed in the firewall and listening:
2053 (v6) ALLOW Anywhere (v6)
2053/tcp (v6) ALLOW Anywhere (v6)
php 41313 root 5u IPv4 455135 0t0 TCP *:2053 (LISTEN)
supervisor
[program:websockets]
directory=/var/www/demo
command=sudo php artisan websockets:serve --port=2053
numprocs=1
autostart=true
autorestart=true
user=root
stderr_logfile=/var/www/demo/storage/logs/websockets.err.log
stdout_logfile=/var/www/demo/storage/logs/websockets.out.log
Cloudflare
I switched from 6001 to 2053 because its a supported port from them.
I enabled the websocket settings in the "Network" tab.
Am I missing the obvious?
Please or to participate in this conversation.