2 核 2G 的服务器能跑什么
先说结论:能跑,但前提是把重活挪到构建期。
这台机器是 2 vCPU / 1.8 GiB 内存 / 40G 磁盘,已经跑着一套容器化的 AI 网关和一组无头浏览器。 实测可用内存只剩 1.0 GiB 左右。这个数字直接决定了架构选择。
内存预算是唯一的约束
常见的"个人网站"方案是 Next.js SSR + PostgreSQL + Redis。先算一下这套在 1.8 GiB 上的账:
| 组件 | 典型 RSS |
|---|---|
| Node SSR 应用 | 150–300 MB |
| PostgreSQL | 100–200 MB |
| Redis | 30–50 MB |
| 合计 | 300–550 MB |
再加上已有的 AI 网关(204 MB)和浏览器进程(~180 MB),直接 OOM。 而且 swap 只有 4G,一旦开始换页,响应会卡到不可用。
所以换一条路:
| 组件 | 内存 |
|---|---|
| 静态站点(Caddy 直接吐文件) | 0 |
| SQLite | ~5 MB |
| 反向代理 | ~20 MB |
| 新增合计 | ≈ 5 MB |
差了两个数量级。
关键在于"构建期做重活"
站点内容用 Markdown 写、存在 git 里,在本地构建成静态 HTML,再推到服务器。 服务器只负责发文件,一个 PHP 进程都不需要。
这不是为了省内存而省内存。真正的收益是:
- 故障面极小 —— 站点挂了只可能是磁盘满或 Caddy 挂了,不会有数据库连接池耗尽这类玄学问题。
- 迁移成本几乎为零 —— 换个 ECS,拷一个目录就完事。
- 版本管理天然内建 —— 内容变更就是 git 提交,有 diff 有回滚。
代价是"发一篇要跑一次构建"。对个人博客来说,这个代价比反向代理的复杂度小得多。
反向代理的结构
vhiccup.cn {
handle /chat* {
reverse_proxy host.docker.internal:18789
}
handle /life* {
basic_auth {
shengyuan $2a$14$...
}
root * /srv/site/current/private
file_server
}
handle {
root * /srv/site/current/public
file_server
}
}
用 handle 而不是 route,因为 handle 是互斥的 —— 第一个匹配的块赢,顺序即优先级。
认证、路径、文件服务三件事在各自的块里各自完成,不会互相干扰。
部署用符号链接原子切换:
/srv/site/releases/20261020-213000/
/srv/site/current -> releases/20261020-213000
推新的 release 目录,然后 ln -sfn 一下就切换了。没有"删掉旧文件再复制新文件"的窗口期,
也不需要清理逻辑 —— 旧 release 攒着,想删的时候再删。
一个差点踩进去的坑
AI 网关的 Web UI 是 SPA,静态资源用的是相对路径(./assets/xxx.js),
但 API 和 WebSocket 用的是绝对路径(/api/...、/ws)。
如果直接用反向代理把它挂到 /chat 下,页面能打开,但所有 API 请求会打到主站上,
聊天直接哑掉。
好在它原生支持配置前缀:
{
"gateway": {
"controlUi": { "enabled": true, "basePath": "/chat" }
}
}
设成 /chat 之后,网关自己接管这个前缀下的资源、API 和 WS,反向代理原样透传路径、不做剥离就行。
教训:挂 SPA 到子路径之前,先确认它的 API 用的是相对还是绝对路径。
这个差别决定了配置里要不要写 handle_path。