EC2上Httpd反向代理Node.js(Express+PM2)配置问题排查
问题与解决方案:Httpd反向代理配置到Node.js Express后端
问题背景
需要在Amazon Linux 2 AMI的EC2实例上配置Httpd反向代理,将mywebsite.com的流量转发至PM2管理的Node.js Express后端(例如mywebsite.com/test对应后端的/test接口)。
后端路径:/home/ec2-user/mywebsite/mywebsite_backend/dist
当前Httpd配置文件/etc/httpd/conf.d/mywebsite.com.conf内容:
<VirtualHost *:80> ServerName mywebsite.com ServerAlias www.mywebsite.com ProxyPreserveHost On ProxyPass /home/ec2-user/mywebsite/mywebsite_backend/dist http://localhost:8055/ ProxyPassReverse /home/ec2-user/mywebsite/mywebsite_backend/dist http://localhost:8055/ ErrorLog /etc/httpd/conf.d/error.log CustomLog /etc/httpd/conf.d/custom.log combined DocumentRoot /home/ec2-user/mywebsite/mywebsite_backend/dist </VirtualHost>
遇到的问题
- 访问
https://mywebsite.com显示Apache测试页;访问https://mywebsite.com/test返回“Not Found”,推测缺少443端口虚拟主机配置。 - 访问
http://mywebsite.com返回“Forbidden”。
后续测试发现
- Edit1:Apache默认指向
/var/www/html,添加index.html后可正常访问该页面。 - Edit2:服务器执行
curl http://localhost:8055/test返回curl: (52) Empty reply from server;执行curl https://localhost:8055/test返回SSL证书不匹配错误。已用Let's Encrypt为Express服务生成SSL证书,本地正常但Apache存在SSL问题。 - Edit3:
curl -k http://localhost:8055/test失败;curl -k https://localhost:8055/test成功。 - Edit4:查看
/etc/httpd/conf.d/error.log发现代码位于/home目录存在权限问题,计划将其移至/var/www/html/。
解决方案步骤
1. 修正反向代理配置逻辑
当前ProxyPass/ProxyPassReverse的参数完全错误,这两个指令的格式是ProxyPass [前端请求路径] [后端服务地址]。结合测试结果,后端仅监听HTTPS端口,因此调整配置如下:
80端口虚拟主机(HTTP转HTTPS)
将所有HTTP请求重定向到HTTPS,避免直接处理HTTP流量:
<VirtualHost *:80> ServerName mywebsite.com ServerAlias www.mywebsite.com # 强制跳转至HTTPS Redirect permanent / https://mywebsite.com/ ErrorLog /etc/httpd/conf.d/error.log CustomLog /etc/httpd/conf.d/custom.log combined </VirtualHost>
443端口虚拟主机(SSL+反向代理)
添加HTTPS虚拟主机,配置SSL证书并将所有请求转发到后端HTTPS服务:
<VirtualHost *:443> ServerName mywebsite.com ServerAlias www.mywebsite.com ProxyPreserveHost On # 将所有前端请求转发至后端HTTPS服务 ProxyPass / https://localhost:8055/ ProxyPassReverse / https://localhost:8055/ # 配置Let's Encrypt证书路径(替换为你的实际路径) SSLEngine on SSLCertificateFile /etc/letsencrypt/live/mywebsite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/mywebsite.com/privkey.pem ErrorLog /etc/httpd/conf.d/error.log CustomLog /etc/httpd/conf.d/custom.log combined </VirtualHost>
2. 解决目录权限问题
方案A:迁移项目到/var/www/html(推荐)
将项目移动到Apache默认允许访问的目录,并设置正确权限:
# 迁移项目目录 mv /home/ec2-user/mywebsite/mywebsite_backend/dist /var/www/html/mywebsite_backend # 设置Apache用户为目录所有者 chown -R apache:apache /var/www/html/mywebsite_backend # 配置目录/文件权限 chmod -R 755 /var/www/html/mywebsite_backend chmod -R 644 /var/www/html/mywebsite_backend/*
方案B:调整/home目录权限(不推荐)
如果不想迁移目录,修改/home相关目录的权限让Apache可以访问:
# 开放目录访问权限给Apache用户 chmod o+x /home/ec2-user chmod o+x /home/ec2-user/mywebsite chmod o+x /home/ec2-user/mywebsite/mywebsite_backend chmod o+x /home/ec2-user/mywebsite/mywebsite_backend/dist # 设置文件权限 chmod -R 644 /home/ec2-user/mywebsite/mywebsite_backend/dist chmod -R 755 /home/ec2-user/mywebsite/mywebsite_backend/dist
3. 确认后端服务配置
确保Express服务正确加载SSL证书并监听8055端口,示例代码:
const https = require('https'); const fs = require('fs'); const express = require('express'); const app = express(); // 加载Let's Encrypt证书 const sslOptions = { key: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/privkey.pem'), cert: fs.readFileSync('/etc/letsencrypt/live/mywebsite.com/fullchain.pem') }; // 测试接口 app.get('/test', (req, res) => { res.send('Test endpoint is working'); }); // 启动HTTPS服务 https.createServer(sslOptions, app).listen(8055, () => { console.log('Backend running on https://localhost:8055'); });
4. 启用Httpd必要模块并重启服务
# 启用代理、HTTP代理、SSL模块 sudo a2enmod proxy proxy_http ssl # 检查配置语法 sudo apachectl configtest # 重启Httpd服务 sudo systemctl restart httpd # 重启PM2管理的Express服务 pm2 restart [你的应用名称]
内容的提问来源于stack exchange,提问作者sander
相关产品推荐
相关产品推荐

