如何在Amazon EC2部署Laravel Websockets并结合AWS ACM实现SSL?
Laravel Websockets + AWS ACM 部署解决方案
问题核心
本地用自签证书能正常运行的Laravel Websockets聊天应用,部署到EC2后因为使用AWS ACM证书(无法获取私钥和证书文件),导致Websockets服务无法正常连接。
解决方案:用ALB做SSL终止(无需在EC2配置SSL)
因为ACM证书不能导出私钥,我们让AWS Application Load Balancer(ALB)承担SSL加密/解密工作,ALB把解密后的HTTP请求转发给EC2上的Websockets服务,Laravel端不需要配置任何SSL证书。
步骤1:修改EC2上的Laravel配置
1.1 更新Supervisor的Websockets配置(/etc/supervisor.conf)
把Websockets服务的监听地址改为0.0.0.0(允许ALB访问,之前的127.0.0.1仅本地可访问):
[program:laravel-websockets] command=php /var/www/html/project/core/artisan websockets:serve --host=0.0.0.0 process_name=%(program_name)s numprocs=1 autostart=true autorestart=true startsecs=10 startretries=3 user=ec2-user redirect_stderr=true stdout_logfile=/var/www/html/project/core/laravel-websockets.log
1.2 更新broadcasting.php配置
去掉SSL相关配置,让服务使用HTTP:
'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' => '0.0.0.0', 'port' => env('LARAVEL_WEBSOCKETS_PORT'), 'scheme' => 'http', ], ],
1.3 更新websockets.php配置
保持SSL配置为空,不需要本地证书:
'ssl' => [ 'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null), 'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null), 'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null), ],
1.4 更新.env配置
确保SSL相关项为空,把前端端口改为ALB的HTTPS端口443:
PUSHER_APP_ID=12345 PUSHER_APP_KEY=ABCDEFG PUSHER_APP_SECRET=HIJKLMNOP PUSHER_APP_CLUSTER=mt1 LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT= LARAVEL_WEBSOCKETS_SSL_LOCAL_PK= LARAVEL_WEBSOCKETS_SSL_PASSPHRASE="" LARAVEL_WEBSOCKETS_PORT=6001 MIX_LARAVEL_WEBSOCKETS_PORT="443"
步骤2:配置AWS ALB
2.1 创建Websockets专用TCP目标组
- 目标类型:实例
- 协议:TCP
- 端口:6001
- 目标:选择你的EC2实例并启用注册
- 健康检查:协议选TCP,端口6001(或用HTTP,路径填
/laravel-websockets,根据服务实际调整)
2.2 配置ALB的HTTPS监听器
- 监听器端口:443,协议HTTPS
- SSL证书:选择你的ACM证书
- 添加两条规则:
- 匹配路径为
/app/*(Laravel Websockets默认请求路径),转发到刚才创建的TCP目标组 - 默认规则:转发到你的Web应用目标组(端口80,处理常规HTTP请求)
- 匹配路径为
步骤3:调整前端Echo配置
让前端通过ALB的443端口(HTTPS)连接Websockets:
const Echo = new initEcho({ broadcaster: "pusher", key: process.env.MIX_PUSHER_APP_KEY, cluster: process.env.MIX_PUSHER_APP_CLUSTER, wsHost: window.location.hostname, wssPort: process.env.MIX_LARAVEL_WEBSOCKETS_PORT, forceTLS: true, encrypted: true, enabledTransports: ["wss"], auth: { headers: { Authorization: "Bearer " + access_token, Accept: "application/json", }, }, }); // 保留原有事件监听代码 Echo.connector.pusher.connection.strategy.transports.wss.transport.manager.livesLeft = Infinity; Echo.connector.pusher.connection.bind("state_change", function (states) { // state change }); const channel = Echo.join("chat-message") .here(() => { console.log("chat channel"); }) .joining((event) => { // console.log({ event }, "joining"); }) .leaving((event) => { // console.log({ event }, "leaving"); }) .listenForWhisper("typing", (event) => { // console.log({ event }, "listenForWhisper"); }) .listen(".chat-message", (event) => { // console.log({ event }, "listen"); });
步骤4:安全组配置
- EC2安全组:允许来自ALB安全组的TCP 6001端口访问
- ALB安全组:允许外部访问HTTPS 443端口
最后验证
- 重启Websockets服务:
sudo supervisorctl restart laravel-websockets
- 重启Apache:
sudo systemctl restart httpd
- 检查服务状态:
sudo supervisorctl status laravel-websockets
- 打开前端应用,查看浏览器控制台连接日志,测试聊天功能。
内容的提问来源于stack exchange,提问作者Mr. Kenneth
相关产品推荐
相关产品推荐

