写在前面
如果你手头有一台云服务器,域名却有好几个——AI 工具站、即时通讯、博客、论坛、公司官网……你会怎么办?每站一台服务器?钱包受不了。全堆一起?怕性能扛不住。
这篇文章就是我的实战记录:如何用一台 2核4G 的轻量云服务器,通过 Nginx 反向代理 + 端口隔离,稳稳跑起多个完全不同的站点。全程分享技术思路,配置可复用。
为何要这么做
事情是这样的——我手头有一台 2核4G 的服务器,结果域名越搞越多:AI 服务、聊天工具、论坛、博客……眼看着站点列表越来越长,总不能每个都单独买一台吧?
于是就有了这个执念:能不能把多个站点全塞进这一台机器里,而且还要跑得稳?答案是可以,关键在架构设计。
核心思路:Nginx 反向代理 + 端口隔离
一台服务器上运行多个 Web 服务,最朴素也最可靠的方案就是:每个服务监听不同的本地端口,由 Nginx 作为统一入口,根据请求的域名转发到对应的服务端口。
这样做有几个好处:
- 服务之间完全隔离,一个挂了不影响其他
- 各自独立部署、独立升级,互不干扰
- Nginx 层面统一管理 SSL、限流、日志
- 资源按需分配,非核心服务可以按需启停
架构示意图如下(以假设的 6 个服务为例):
| 服务类型 | 推荐技术栈 | 端口范围 | 备注 |
|---|---|---|---|
| 个人博客/内容站 | Node.js / PHP | 8081~8089 | 可静态化加速 |
| AI 工具/API 服务 | Node.js / Python | 8090~8099 | 可能需要 WebSocket |
| 即时通讯/IM | Node.js + WebSocket | 8100~8109 | 需配置 Upgrade 头 |
| 论坛/社区 | PHP (Discuz/WordPress) | 8110~8119 | 数据库可复用 |
| 流量/监控面板 | 自建/Python | 8120~8129 | 可定时任务按需启动 |
| 公司官网/落地页 | 静态/PHP | 8130~8139 | 静态资源 Nginx 直出 |
Nginx 反向代理配置模板
每个站点的 Nginx 配置大同小异,核心就是 server_name 和 proxy_pass。下面是一个通用模板:
server {
listen 443 ssl http2;
server_name your-domain.com; # 替换为你的域名
ssl_certificate /etc/nginx/ssl/your-domain/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/your-domain/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8081; # 替换为你的服务端口
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;
}
# 如果服务需要 WebSocket(如 IM、AI 流式输出)
location /ws {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}每个站复制一份,改 server_name 和 proxy_pass 端口即可。需要 WebSocket 的服务单独配一个 location。
部署中的三个典型坑
理想很丰满,现实很骨感。部署过程中踩了三个大坑,也是多站点部署最容易遇到的问题。
坑①:WebSocket 连接失败
IM、AI 流式输出等服务依赖 WebSocket 维持长连接。如果 Nginx 没配 Upgrade 头,握手请求会被当成普通 HTTP 处理,导致 400 错误。
# 核心修复:在 location 中显式声明 Upgrade
location /ws {
proxy_pass http://127.0.0.1:服务端口;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400; # 24h 超时
}要点:每个需要 WebSocket 的服务都要单独配 location,且 proxy_read_timeout 必须设长(至少 86400 秒),否则 Nginx 会自动掐断连接。
坑②:SSL 证书太多难管理
站点一多,证书管理就成了噩梦。每个域名单独申请、手动续期,迟早会漏。
解决方案:用泛域名证书(Let's Encrypt 免费),一张证书覆盖所有子域名。如果有不同根域的域名,单独再申请一张就好。
# 使用 acme.sh 一键申请泛域名证书
curl https://get.acme.sh | sh
acme.sh --issue -d example.com -d '*.example.com' \
--dns dns_cf # Cloudflare DNS API 验证
# 安装到 Nginx
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com/privkey.pem \
--fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \
--reloadcmd "nginx -s reload"acme.sh 会自动续期(60 天自动续),一次配置终身无忧。不同 DNS 服务商(阿里云、腾讯云、Cloudflare 等)都有对应的 API 插件。
坑③:内存不够用
多个服务同时运行,内存消耗不容小觑。Node.js 服务尤其占内存,PHP 也不省心。
我的解决三板斧:
- 加 Swap:分配 2~4GB Swap 空间,物理内存不够时系统自动换出,防止 OOM 杀进程
- 限制单进程内存:Node.js 启动时加 --max-old-space-size=512,PHP-FPM 调低 pm.max_children
- 非核心服务按需启动:低频率服务(如日志分析、监控面板)做成定时任务或手动启停,不常驻
# 创建 Swap 文件
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
# PM2 限制 Node 内存(ecosystem.config.js)
module.exports = {
apps: [{
name: 'my-app',
script: 'app.js',
node_args: '--max-old-space-size=512',
}]
}
# PHP-FPM 调优(www.conf)
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3优化之后,多服务稳定运行,内存控制在合理范围,再也没炸过。
多站点部署的几个建议
- 端口避开常见端口(3000、8080、9090),减少被扫描猜中的概率
- 非必需的服务用 Docker 运行,方便隔离和迁移,出问题直接删容器重建
- MySQL / Redis / Nginx 等中间件全局共用一份即可,没必要每个服务单独装
- 日志一定要做轮转(logrotate),多个服务的日志很容易写满磁盘
- 部署前简单压测一下(ab / wrk),找找瓶颈在哪,心中有数
- 敏感信息(端口、域名、路径)不要在公开文章里贴原始配置,脱敏处理
总结
折腾的乐趣不在于结果多牛,而在于过程——遇到问题、查资料、试错、最终搞定。一台 2核4G 的服务器跑多个站点,不是什么了不起的架构,但对个人站长来说,这就是把每一份资源都用到极致。
本文分享的是思路和方法论,配置模板拿过去改改就能用。如果你也有一台小服务器和一堆域名,不妨试试这个方案。
有任何问题欢迎评论交流。