tol64
@tol64

Laravel + Nuxt + Nginx: WebSocket is closed before the connection is established?

Общая схема и файлы конфигурации проекта

Проект состоит из двух частей:
  • Серверная часть - Laravel (api)
  • Клиентская часть - NuxtJs (client)


Для теста была подготовлена минимальная конфигурация проекта.

Laravel

Установлены пакеты для работы с веб-сокетами:


Файл composer.json:
...
    "require": {
        "php": "^7.3",
        "beyondcode/laravel-websockets": "^1.8",
        "fideloper/proxy": "^4.2",
        "fruitcake/laravel-cors": "^2.0",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/framework": "^8.0",
        "laravel/tinker": "^2.0",
        "pusher/pusher-php-server": "^4.1"
    },
    "require-dev": {
        "facade/ignition": "^2.3.6",
        "fzaninotto/faker": "^1.9.1",
        "mockery/mockery": "^1.3.1",
        "nunomaduro/collision": "^5.0",
        "phpunit/phpunit": "^9.3"
    },
...


Nuxt

Установлены пакеты для работы с веб-сокетами:


Файл package.json:
...
  "dependencies": {
    "@nuxtjs/axios": "^5.12.2",
    "@nuxtjs/dotenv": "^1.4.1",
    "@nuxtjs/laravel-echo": "^1.1.0",
    "@nuxtjs/proxy": "^2.0.1",
    "nuxt": "^2.13.0",
    "pusher-js": "^7.0.0"
  },
...


//---

Все файлы уже загружены на VPS (Ubuntu 18.04 LTS) и получен сертификат (https://certbot.eff.org/):

5f9047746d3a3314117831.png

Сервер веб-сокетов запущен на постоянную работу по этому описанию: https://beyondco.de/docs/laravel-websockets/basic-...

Проверка:

supervisorctl status

5f904e57d82ae148020652.png

Для автоматического запуска и перезагрузки клиентской части, глобально установлен и запущен на постоянную работу менеджер процессов pm2: https://pm2.keymetrics.io

Проверка:

pm2 list

5f904e9796e01163828440.png

Список занятых портов:

netstat -ntlp | grep LISTEN

5f904ef0363e9041645358.png

lsof -i -P -n | grep LISTEN

5f904f0d8ff57108340234.png

Текущий статус сетевой защиты:

ufw status

5f904f3667e1e890440572.png

//---

Ответ от серверной части, при запросах из клиентской, приходит:

5f904f699f319834915643.png

С веб-сокетами получается ошибка:

5f904fb70b9fe375398259.png
5f904fc0b916b472485083.png

Файлы для настройки веб-сокетов

Laravel

Файл .env:

vim /var/www/api/.env

APP_NAME=Laranuxt
APP_ENV=production
APP_KEY=base64:cSTA4y9lIjmQDQ9b3+J2X+iSif8jqu6u3Oj9UNXdzIs=
APP_DEBUG=false
APP_SCHEME=https://
APP_HOST=larastart.site
APP_URL="${APP_SCHEME}larastart.site"
CLIENT_URL="${APP_SCHEME}larastart.site"
...
PUSHER_APP_ID=123
PUSHER_APP_KEY=456
PUSHER_APP_SECRET=789
PUSHER_APP_CLUSTER=test

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"


Файл websockets.php:

vim /var/www/api/config/websockets.php

...
    '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' => true,
            'enable_statistics' => false,
        ],
    ],
...


Файл broadcasting.php:

vim /var/www/api/config/broadcasting.php

...
    'connections' => [
        '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'),
                'useTLS' => false,
                'encrypted' => false,
                'host' => env('APP_HOST'),
                'port' => 6001,
                'scheme' => 'http',
                'curl_options' => [
                        CURLOPT_SSL_VERIFYHOST => 0,
                        CURLOPT_SSL_VERIFYPEER => 0,
                ]
            ],
        ],
	...
    ],
...


Nuxt

cd /var/www/client

Файл .env:

vim /var/www/client/.env

SCHEME     = https://
BASE_URL   = "${SCHEME}larastart.site"
API_DOMAIN = "${SCHEME}larastart.site"
API_URL    = "${SCHEME}larastart.site/api"

BROADCAST_DRIVER   = pusher
PUSHER_APP_ID      = 123
PUSHER_APP_KEY     = 456
PUSHER_APP_SECRET  = 789
PUSHER_APP_CLUSTER = test


Файл echo.js:

vim /var/www/client/plugins/echo.js

import Echo from 'laravel-echo';

export default (app) => {
    window.Pusher = require('pusher-js');

    window.Echo = new Echo({
        broadcaster: process.env.BROADCAST_DRIVER,
        key: process.env.PUSHER_APP_KEY,
        cluster: process.env.PUSHER_APP_CLUSTER,

        forceTLS: false,
        encrypted: false,
        wsHost: window.location.hostname,
        wsPort: 6001,
        wssPort: 6001,
        disableStats: false,
        enabledTransports: ['ws', 'wss']
    });
}


Файл nuxt.config.js:

vim /var/www/client/nuxt.config.js

...
  plugins: [
    { src: '~/plugins/echo.js', ssr: false }
  ],
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy',
    '@nuxtjs/dotenv'
  ],
  axios: {
    baseURL: process.env.API_DOMAIN,
    credentials: true
  },
  proxy: {
    "/api": {
      target: process.env.API_DOMAIN,
      pathRewrite: { "^/api" : "/" }
    }
  },
...


Nginx

Конфигурационный файл для работы сайта на веб-сервере Nginx создан и подключен:

5f90522321826692222900.png

vim /etc/nginx/sites-available/larastart.site

server {
        server_name     larastart.site;
        root            /var/www/api/public;

        add_header X-Frame-Options              "SAMEORIGIN";
        add_header X-XSS-Protection             "1; mode=block";
        add_header X-Content-Type-Options       "nosniff";

        # Priority file extensions
        index index.php index.html index.htm index.nginx-debian.html;

        charset utf-8;

        # Check for the existence of files matching a provided url, forward to 404 if not found
        location /api {
                try_files $uri $uri/ /index.php?$query_string;
        }

        # Serve static files directly
        location ~* ^/storage/(.*)\.(jpg|jpeg|gif|bmp|png|ico)$ {
                access_log off;
        }

        location / {
                proxy_pass                          http://127.0.0.1:3000;
                proxy_set_header Host               $host;
                proxy_set_header X-Real-IP          $remote_addr;

                proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto  $scheme;
                proxy_set_header X-VerifiedViaNginx yes;
                proxy_read_timeout                  300;
                proxy_connect_timeout               300;
        }

        location /app {
                proxy_pass                          http://127.0.0.1:6001;
                proxy_set_header Host               $host;
                proxy_set_header X-Real-IP          $remote_addr;

                proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto  $scheme;
                proxy_set_header X-VerifiedViaNginx yes;
                proxy_read_timeout                  300;
                proxy_connect_timeout               300;

                # Specific for websockets: force the use of HTTP/1.1 and set the Upgrade header
                proxy_http_version      1.1;
                proxy_set_header        Host            $host;
                proxy_set_header        Upgrade         $http_upgrade;
                proxy_set_header        Connection      'upgrade';
                proxy_cache_bypass      $http_upgrade;
        }

        error_page 404 /index.php;

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
                fastcgi_pass  unix:/var/run/php/php7.4-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
                include fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root concurs with nginx's one
        location ~ /\.(?!well-known).* {
               deny all;
        }

listen 443 ssl; # managed by Certbot
	
ssl_certificate     /etc/letsencrypt/live/larastart.site/fullchain.pem;     # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/larastart.site/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 {
if ($host = larastart.site) {
         return 301 https://$host$request_uri;
} # managed by Certbot

listen 80;
server_name larastart.site;
return 404; # managed by Certbot
}
  • Вопрос задан
  • 1651 просмотр
Пригласить эксперта
Ответы на вопрос 1
5f907bab94045940607443.png
В ufw, если ничего не путаю, разрешено соединение только с SSH и nginx. Порт 6001 прослушивается php, поэтому подключение не разрешается. 2 варианта решения:
1) Пробросить 6001 порт через nginx (как тут)
2) Разрешить в ufw обращение к php
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы