买了一台年付几十美元的 VPS,手上又有三四个域名,第一个念头通常是:能不能都塞进去?
能。一台 1 核 1G 的机器放两三个轻量站没问题,4 核 8G 放十个也不稀奇。但"能放"和"放得好"是两件事 —— 内存怎么分、一个站被刷爆了会不会连累其他站、备份怎么按站做,这些没想清楚,后面全是坑。
这篇讲一台 VPS 跑多个网站的完整做法:三种主流路线怎么选、域名和证书怎么配、资源和安全怎么隔离、以及什么时候该老老实实再加一台机器。
决定因素不是 CPU,也不是硬盘,是内存。硬盘几百 G 放几十个静态站都够,CPU 对静态站几乎无感,只有内存会先爆。
| 站点类型 | 单站常驻内存 | 1 核 1G 实际能放 |
|---|---|---|
| 纯静态 / Hugo / Astro | 几乎为 0(Nginx 直接返回文件) | 几十个 |
| 轻量 PHP(Typecho、Halo) | 60-120 MB | 4-6 个 |
| WordPress 带插件 | 150-300 MB | 2-3 个 |
| Node / Python 应用 | 80-250 MB | 2-3 个 |
| 每个独立数据库 | 再加 100-300 MB | 还得算数据库自己的开销 |
几个实测经验:
- MySQL 自己是吃内存大户。默认配置下光它就能占 300-400 MB,比你的网站还费。多站共用一个数据库实例是对的,但要把
innodb_buffer_pool_size调小。 - PHP-FPM 是隐形内存杀手。每个
pm.max_children就是一个进程,一个 WordPress 池开 10 个 child,2G 内存就没了。 - 面板自己也要吃 200-400 MB。1G 机器装完面板,留给网站的真不多了。
拿不准的话,对着 VPS 配置怎么选 那张表估一遍,再看下面三种路线选一条。
| 做法 | 适合谁 | 优点 | 代价 |
|---|---|---|---|
| 面板(宝塔 / 1Panel) | 不想碰命令行的 | 点鼠标建站,SSL 一键签 | 面板占内存,历史上出过安全事件 |
| 反向代理(Nginx / Caddy) | 会用命令行的 | 轻量、可控、配置能进 git | 要自己写配置 |
| 容器(Docker + 反代) | 多个异构项目 | 隔离最好,依赖不打架 | 学习成本,磁盘占用大 |
最常见的翻车方式是把前两种混着用:装了宝塔,又手写一套 Nginx 配置,结果两边的 web server 抢 80 端口,nginx -t 通过但站点打不开。选一条,走到底。
宝塔和 1Panel 的"新建站点"就是为多站点设计的 —— 每个站一个目录、一份配置、一张证书,互不干扰。
- 宝塔的安装和多站配置见 宝塔面板安装教程
- 1Panel 的做法见 VPS 搭建 1Panel
- 两者怎么选见 VPS 控制面板怎么选
用面板必须做三件事,否则很危险:
- 改掉默认面板端口,别让扫描器一找一个准。
- 限制面板访问 IP,只允许你自己的 IP 进。
- 开二次验证。
面板漏洞的历史记录不少,而面板一旦被拿下,等于整台机器上的所有站一起失守 —— 这是"一机多站"最典型的风险放大场景。
核心思路很简单:一个 web server 监听 80/443,按域名把请求分给不同站点。站点之间不需要知道彼此存在。
Caddy 的配置最短,而且自动签证书:
site-a.com {
root * /srv/site-a
file_server
}
site-b.com {
root * /srv/site-b
file_server
}
app-c.com {
reverse_proxy 127.0.0.1:3000
}
三个域名三张证书,Caddy 自己去申请和续期。更多写法见 Caddy 反向代理完全指南。
Nginx 就是每个站一个 server 块,用 server_name 区分:
server {
listen 80 default_server;
server_name _;
return 444; # 兜底:没匹配到域名就直接断开
}
server {
listen 80;
server_name site-a.com www.site-a.com;
root /srv/site-a;
index index.html index.php;
}
那个 default_server 兜底块千万别省。 没有它,别人用 IP 直接访问你的机器,会命中第一个配置的站点 —— 如果第一个站是内部管理后台,等于白送。返回 444(直接断开连接)比返回 404 更干净。
Nginx 写法嫌麻烦可以用面板化的 Nginx Proxy Manager,图形界面加域名和证书。
每个站一个独立的 compose 项目,容器只监听内部端口,由反向代理容器统一对外。
这套做法最大的价值是依赖能共存:A 站要 Node 18,B 站要 Node 24,C 站是 Python 3.12,互不影响。混装在同一台机器上的话,光版本管理就能折腾一整天。
代价也很实在:
- 磁盘:每个镜像几百 MB,几个站下来十几个 G 很正常。磁盘吃紧看 Docker 占满磁盘怎么办。
- 内存:容器本身有开销,1G 机器跑三四个容器就紧了。
- 排查链路变长:请求要穿过反代 → 容器网络 → 应用,出问题时比直连多几层要看。
生产环境的资源限制怎么配,见 VPS Docker Compose 生产环境怎么配。
域名解析:每个域名加一条 A 记录指向这台机器的 IP。同一台机器绑几个域名,技术上没有上限。
证书有三种做法,按站点数量选:
| 做法 | 命令 | 适合 |
|---|---|---|
| 每域名单独签 | certbot --nginx -d a.com -d www.a.com | 站点少、增删频繁 |
| 一张多域名证书 | certbot --nginx -d a.com -d b.com -d c.com | 站点固定、想少几张证书 |
| 通配符证书 | certbot certonly --dns-cloudflare -d '*.example.com' | 站点多、子域名经常加 |
通配符证书必须走 DNS-01 验证,因为它没法为"任意子域名"提供 HTTP 验证文件。用 Cloudflare 托管 DNS 的话,装个 certbot-dns-cloudflare 插件就行。
加了 Cloudflare 代理的话注意两点:源站要装证书(用 Cloudflare 的 Origin Certificate 或 Let's Encrypt 都行),以及 Nginx 里必须传 X-Forwarded-Proto $scheme。漏了这条,站点开了强制 HTTPS 之后会陷入无限重定向 —— 成因分析见 HTTPS 跳转循环怎么办。
续期是自动的,但要确认真的在跑,别等过期了才发现:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
失败排查见 Let's Encrypt 证书续期失败怎么办。
/srv/
├── site-a/ # 站点 A 的文件
├── site-b/
├── site-c/
└── shared/
└── backups/ # 各站备份,独立子目录
给每个站建独立系统用户,不要让所有站都用 www-data:
sudo useradd -r -s /usr/sbin/nologin sitea
sudo useradd -r -s /usr/sbin/nologin siteb
sudo chown -R sitea:sitea /srv/site-a
sudo chown -R siteb:siteb /srv/site-b
权限按目录 755、文件 644 走,只有上传目录需要写权限。
为什么必须分用户:Linux 的权限是按用户隔离的。如果所有站都跑在 www-data 下,A 站的一个任意文件读取漏洞就能直接读到 B 站的 wp-config.php,里面的数据库密码跟着一起丢。分了用户,越权读会被内核直接拒绝。
PHP 站再加一层 open_basedir,把每个站锁在自己的目录里:
; /etc/php/8.3/fpm/pool.d/site-a.conf
php_admin_value[open_basedir] = /srv/site-a:/tmp
这是"一机多站"最真实的痛点:三个站各跑各的都没事,一台机器上只要一个被爬虫刷,全都 502。
原因通常不是 CPU,是内存。80% 的"一机多站突然全挂"都是 OOM Killer 干的。
按站限制资源,几种可行手段:
# systemd 服务限内存和 CPU(应用类站点)
MemoryMax=512M
CPUQuota=50%
# Docker 容器限资源
docker run --memory=512m --cpus=1 ...
PHP 站则通过 FPM 池的 pm.max_children 控制 —— 每个池单独配,别让爬虫把整个机器的 PHP 进程额度吃光:
; 小站给 3-5 个就够
pm = dynamic
pm.max_children = 5
pm.max_requests = 500
还有两个容易被忽略的点:
- 数据库连接数。每个站的 PHP 池都能开一堆连接,几个站加起来能把 MySQL 的
max_connections打满,然后所有站一起报"Too many connections"。 - 磁盘 IO。一个站做全量备份或跑批量任务时,
iowait会拖慢其他站。备份放到低峰期。
内存确实不够的话,加 Swap 或 ZRAM 能兜住突发,但它治不了内存泄漏,只是把崩溃时间往后推 —— 方法见 低内存怎么用 ZRAM 和 Swap 优化。
分用户解决了"互相读文件",还有几件事要做:
数据库账号必须按站分开。 别所有站共用 root,也别共用同一个库。A 站被注入,攻击者只能拿到 A 站的数据。
CREATE DATABASE site_a;
CREATE USER 'site_a'@'127.0.0.1' IDENTIFIED BY '强密码';
GRANT ALL PRIVILEGES ON site_a.* TO 'site_a'@'127.0.0.1';
数据库只监听 127.0.0.1,不要为了图方便把 3306 开到公网。做法见 VPS 数据库不要直接暴露公网。
上传目录禁止执行脚本。 WordPress 被挂马最常见的方式就是往 uploads/ 传一个 PHP 文件然后访问它执行:
location ~* /wp-content/uploads/.*\.php$ {
return 403;
}
同一个 CMS 的多个站,漏洞会一起中招。 三个 WordPress 站,只要一个插件有漏洞没更新,另外两个用同款插件的话同样危险。这是"一机多站"绕不开的关联风险,唯一的解法是及时更新 —— 或者把站分到不同机器上。
服务器层面的加固清单见 VPS Nginx 安全加固。
最常见的错误备份方式是:tar czf all-sites.tar.gz /srv /etc/nginx /var/lib/mysql。问题在于恢复 —— 你只想恢复 C 站,却不得不把 A、B 站一起恢复到某个旧版本。
正确的做法是按站独立备份,每个包 = 网站文件 + 该站的数据库:
#!/usr/bin/env bash
set -euo pipefail
SITE=site-a
DATE=$(date +%F)
DEST=/srv/shared/backups/$SITE
mkdir -p "$DEST"
# 文件
tar czf "$DEST/${SITE}-files-${DATE}.tar.gz" -C /srv "$SITE"
# 该站单独的数据库
mysqldump --single-transaction "site_${SITE//-/}" \
| gzip > "$DEST/${SITE}-db-${DATE}.gz"
--single-transaction 保证 InnoDB 表在导出时不会被写操作撕裂,不用锁表。
三个要点:
- 备份要传到别的地方。留在同一台机器上等于没备份 —— 机器一坏全没。可以下载到本地,或传到对象存储,参考 VPS 需要对象存储吗。
- 保留多份。只留最新一份,中招勒索或误删时没有退路。
- 演练过恢复才算数。没验证过的备份只是心理安慰,流程见 VPS 备份恢复演练。
多站点最省事的做法是所有网站都走 80/443 交给反向代理,只有应用类站点才占内部端口(3000、8000 这些),而且一律只监听 127.0.0.1。
端口冲突时的排查:
sudo ss -lntp 'sport = :3000'
输出会直接告诉你是哪个进程占着。常见坑是上次部署的应用没停掉,新实例起不来但日志只报一句 EADDRINUSE。完整排查见 VPS 端口被占用怎么办。
不是"站点多了就该加",而是出现下面这些信号:
| 信号 | 说明 |
|---|---|
| 内存长期 > 80%,开始出现 OOM | 最先出现的信号,加 Swap 只是拖延 |
| 一个站的流量高峰影响其他站 | 资源竞争已经无法靠限流解决 |
| 站点之间需要强隔离 | 不同客户、不同合规要求,不能共处一机 |
| 需要故障隔离 | 一台挂了不能全挂 |
| 磁盘 IO 长期打满 | 备份、批量任务互相拖累 |
决定加机器之后,有两条路:
升配现有机器 —— 省事,配置迁移成本为零,但还是单点,一次故障全站下线。
再买一台便宜的机器把站分过去 —— 隔离效果好,成本往往比升配还低。比如把三个 WordPress 从一个 2 核 4G 升到 4 核 8G,可能比再买两台年付小机器更贵。
便宜的机器可以看 Racknerd,年付价格低,放几个轻量站够用;要按小时计费、随时升配或换机房,Vultr 更灵活;站点偏资源型(大内存、大硬盘),Contabo 单价低但磁盘 IO 一般。国内访问要求高的站,搬瓦工 的 CN2 GIA 线路稳,代价是贵。
怎么判断该拆哪一层(应用、数据库、对象存储),和"多站点"是两回事,见 单机 VPS 什么时候该拆分架构。站点量级到了要考虑前面加一层的时候,再看 小网站需要负载均衡吗 和 企业级 VPS 高可用架构。
一台 VPS 能绑几个域名?
技术上没有数量限制,加多少条 A 记录都行。真正的限制是内存和证书管理成本。
多个域名能共用一张证书吗?
能。用 SAN 证书(certbot -d a.com -d b.com)或通配符证书。注意 Let's Encrypt 的速率限制:同一组域名每周签发次数有限,调试时用 --dry-run,别把额度试没了。
一个站被 DDoS 会影响其他站吗?
会。带宽被占满时,同一台机器上的所有站都访问不了。这种场景要在前面套 CDN 或高防,而不是指望机器内部隔离。
面板和 Docker 能一起用吗?
能,但要避免端口打架。面板自带的 web server 占 80/443,Docker 里的反代就别再监听这两个端口,改成只监听 127.0.0.1 的高位端口,再由面板的 Nginx 转发过去。
多个站共用一台机器,SEO 会受影响吗?
不会。搜索引擎按域名判断站点,同一 IP 上有多个站是常态。但要注意:如果其中一个站因为作弊被惩罚,同一 IP 上的其他站被人工审查的概率会略高。正常做站不用担心。
- VPS 配置怎么选 — 按站点数量和类型估算配置
- VPS 用 Caddy 反向代理完全指南 — 多域名分流的完整写法
- 单机 VPS 什么时候该拆分架构 — 应用、数据库、对象存储怎么分层
- VPS 备份恢复演练怎么做 — 按站备份后要验证能恢复
- VPS Docker Compose 生产环境怎么配 — 容器路线的资源和日志配置
