单机多项目共存:一台 nginx 如何伺候多个站点

站点架构nginx反向代理部署路由
2026-10-11 · 931 字 · 约 3 分钟
本文目录(7 节)

这台服务器上跑着三个入口:项目导航页(域名根路径)、影像从心(/photo)、pycamp 训练营(/pycamp),外加本博客(/blog)。全部共用一个域名、一张证书、一个 nginx。

💡 一句话定位: 按「URL 路径分区 + 本地端口分服务」做多租户——静态项目直挂目录,动态服务剥离前缀反代,AI 外呼统一走网关。
  • 入口层 — nginx 80/443 · 单域名单证书,按 location 前缀把流量分发给 4 个入口(/ 、/photo、/pycamp、/blog)
  • 静态站 ×3 — root + try_files 直挂 · 导航页(/www/wwwroot/samememory.life)、训练营前端(/www/wwwroot/pycamp)、博客(/www/wwwroot/blog)
  • 动态服务 — systemd + 本地端口 · 影像站 :8010(前缀剥离反代 + 绝对路径透传)、pycamp 沙箱 :8021、AI 学习服务 :8022(仅 127.0.0.1 监听)
  • 外呼代理 — nginx 反代出站 · 智谱(密钥托管+限流)、DeepSeek / Zen(Key 透传),解决浏览器 CORS 与密钥安全两个问题
图 1 · 一台 nginx 的路由分区(四类 location 各司其职)
图 1 · 一台 nginx 的路由分区(四类 location 各司其职)nginx 路由静态直挂 ^~ 前缀/pycamp/ 训练营/blog/ 技术博客前缀剥离反代/photo/ 影像站页面/api/ 影像站接口密钥托管代理/pycamp/api/ai/zhipu/本地微服务/pycamp/api/ → 8021 沙箱/pycamp/api/learn/ → 8022/blog/api/ → 8023 问答

路由总览#

text
samememory.life/
  ├── /            静态导航页   /www/wwwroot/samememory.life
  ├── /photo/      影像从心     → 127.0.0.1:8010 (剥离前缀反代)
  ├── /pycamp/     训练营静态站 /www/wwwroot/pycamp
  │   └── /pycamp/api/…         → 8021 沙箱 / 8022 学习 / 外部 AI 反代
  └── /blog/       技术博客     /www/wwwroot/blog

模式一:静态目录直挂(pycamp / blog)#

最简单的一类——纯静态文件,用 root + try_files 直接伺候:

nginx
location ^~ /pycamp/ {
    root /www/wwwroot;
    index index.html;
    try_files $uri $uri/ =404;
}

目录名和 URL 路径同名,所以 root /www/wwwroot 就行,不用 rewrite。

模式二:前缀剥离反代 + 绝对路径透传(影像站)#

影像站是一个有自己路由的动态服务(/api、/uploads、/admin……内部全是根绝对路径)。要把它塞进 /photo 子路径,直接 proxy_pass 会全站断链。方案是两步:

① 页面本体:剥离前缀#

nginx
location ^~ /photo/ {
    proxy_pass http://127.0.0.1:8010/;   # 末尾的 / 负责剥掉 /photo
}

② 页面引用的绝对路径:透传给同一后端#

nginx
location ^~ /api/       { proxy_pass http://127.0.0.1:8010; }
location ^~ /uploads/   { proxy_pass http://127.0.0.1:8010; }
location ^~ /admin      { proxy_pass http://127.0.0.1:8010; }
location ~* \.geojson$  { proxy_pass http://127.0.0.1:8010; }

这样前端代码一行不用改。代价是这些路径在根路径下也被影像站占用——导航页、博客都是纯静态,不碰这些路径,互不冲突。

location 优先级的实战教训#

  • 正则吃掉前缀:站点里有一条静态资源缓存规则 location ~* \.(css|js|png…)$。它优先于普通前缀匹配,会把 /pycamp/api/… 里的沙箱请求也抢走。解决办法:业务前缀一律加 ^~(禁止再走正则)。
  • 最长前缀优先:AI 反代有 /pycamp/api/ai/zhipu/、/pycamp/api/ai/zen/、/pycamp/api/ai/ 三条规则,nginx 按最长前缀命中,把最具体的放前面写,代码可读性更好。
  • 精确匹配最优先:导航页用 location = /,无论其他规则怎么写,根路径永远先命中它。

改配置的纪律#

  • 每次改动前先 cp xxx.conf xxx.conf.bak-$(date +%Y%m%d),出问题秒回滚;
  • 先 nginx -t 再 nginx -s reload,语法错误绝不上线;
  • 改完用 curl -o /dev/null -w "%{http_code}" 逐条冒烟,别只看首页。
一台 2 核小机 + 一个域名,用「路径分区 + 端口分服务」就够撑起整个产品矩阵。真正要克制的不是资源,而是路由规则之间的优先级冲突——把 ^~、=、最长前缀这三件事想清楚,nginx 就是最好的多租户网关。
🏷 nginx🏷 反向代理🏷 部署🏷 路由
💬 问我 只依据站内资料作答
可以问这个站点的技术内容,例如「pycamp 的代码沙箱怎么做的」「为什么不直接用向量检索」。