You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 10 搭配Soketi在VPS上遇WebSocket连接建立前关闭问题

问题:Laravel 10 + Soketi WebSocket 连接失败(Ubuntu 20.04 VPS部署)

我在Ubuntu 20.04的VPS上部署Laravel 10项目,用Soketi实现WebSocket,卡了好几天。目前Soketi容器正常运行,访问http://127.0.0.1:6001和http://xx.xxx.xx.xxx:6001都返回OK,但前端一直报WebSocket连接失败的错误。

已配置信息

Soketi容器配置

soketi:
       image: 'quay.io/soketi/soketi:latest-16-alpine'
       environment:
         SOKETI_METRICS_ENABLED: 1
       ports:
         - '6001:6001'
         - '9601:9601'
       networks:
         - network_forms
       restart: always

.env配置

PUSHER_APP_ID=application id
PUSHER_APP_KEY=application key
PUSHER_APP_SECRET=application secret
PUSHER_HOST=localhost
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1

config/broadcasting.php配置

'pusher' => [
               'driver' => 'pusher',
               'key' => env('PUSHER_APP_KEY'),
               'secret' => env('PUSHER_APP_SECRET'),
               'app_id' => env('PUSHER_APP_ID'),
               'options' => [
                   'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
                   'port' => env('PUSHER_PORT', 443),
                   'schema' => env('PUSHER_SCHEME', 'https'),
                   'encrypted' => true,
                   'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
               ],
               'customer_options' => [
                   // Guzzle client options
               ],
           ],

bootstrap.js配置

import echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new echo({
       broadcaster: 'pusher',
       key: import.meta.env.VITE_PUSHER_APP_KEY,
       cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
       wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
       wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
       wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
       forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
       encrypted: true,
       disableStats: true,
       enabledTransports: ['ws', 'wss'],
});

已配置反向代理

ProxyPass/http://localhost:6001/
    ProxyPassReverse / http://localhost:6001/

错误信息

WebSocket connection to 'wss://localhost:6001/app/app-key?protocol=7&client=js&version=7.6.0&flash=false' failed: WebSocket is closed before the connection is established.


解决思路
  • 修正前端WebSocket主机配置:前端代码里wsHost用了localhost,会导致浏览器从客户端环境访问本地6001端口,而非VPS的公网IP/域名。需在.env中添加VITE前缀的环境变量:

    VITE_PUSHER_HOST=xx.xxx.xx.xxx # 你的VPS公网IP或域名
    VITE_PUSHER_PORT=6001
    VITE_PUSHER_SCHEME=http
    

    同时调整bootstrap.js的forceTLS为false(当前用http协议),避免强制用wss连接http端口。

  • 修复反向代理配置:当前代理格式错误,正确的Apache配置需启用WebSocket代理模块并调整规则:

    1. 执行a2enmod proxy_wstunnel启用模块,重启Apache
    2. 修改代理规则:
    ProxyPass /ws http://localhost:6001
    ProxyPassReverse /ws http://localhost:6001
    ProxyPass /api http://localhost:6001
    ProxyPassReverse /api http://localhost:6001
    

    前端可通过wss://你的域名/ws连接,既避免暴露端口,也解决跨域问题。

  • 添加Soketi跨域允许:在Soketi容器环境变量中配置允许的前端域名,生产环境建议指定具体域名而非通配符:

    environment:
      SOKETI_METRICS_ENABLED: 1
      SOKETI_ALLOWED_ORIGINS: "https://yourdomain.com" # 替换为你的前端域名
    
  • 修正后端加密配置:.env中PUSHER_SCHEME为http,但broadcasting.php里encrypted设为true,会导致后端用https连接Soketi的http端口。修改为:

    'encrypted' => env('PUSHER_SCHEME', 'https') === 'https',
    
  • 验证端口连通性:确保VPS防火墙和云服务商安全组放行6001端口,执行ufw allow 6001/tcp开放端口。

内容的提问来源于stack exchange,提问作者Lucas Nascimento

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:43:21