群晖 NAS 自定义 Nginx 配置:绕开模板,优雅加反代
群晖 NAS 自定义 Nginx 配置:绕开模板,优雅加反代
dong4j前言
在群晖上整点”高级”的网络配置 —— 比如加个反向代理、换个监听端口、写条 URL Rewrite —— 我第一反应都是:
直接去改
/etc/nginx/nginx.conf不就好了?
然后就被坑了。具体坑法是:配置当场生效,重启一次就没了。
我当时还以为是自己改错了文件权限或者 reload 命令不对,反复核对了好几次,最后才反应过来 —— 群晖的 Nginx 配置根本不是一个”手写”的文件,而是开机时用模板生成出来的。你改得再仔细,系统一重启就用模板重新写一份,你的改动被原样冲掉。
这篇把整个机制说清楚,再给一个我自己一直在用的”不碰模板、不丢配置“的做法。
群晖 Nginx 的配置是怎么来的
先 SSH 上群晖看一眼:
1 | sudo -i |
能看到一堆 .mustache 文件:
1 | WWWService.mustache |
这就是群晖 Nginx 配置的”源头”。DSM 每次启动(或者你在 WebStation、控制面板里动配置)的时候,它会读取这些模板、结合当前设置生成最终的 /etc/nginx/nginx.conf 和一堆 conf.d/*.conf。
所以有个很重要的结论:
凡是模板能生成出来的东西,你手动改的都会被冲掉。
这个”默认跳转 80 → 5000”的逻辑就是典型,它是在 WWWService.mustache 里写死的。如果你真的非要动它(比如把 80 换成别的端口、或者干掉那个自动 rewrite),那只能改模板本身:
1 | # 示例:改 WWWService.mustache 里的 80 端口 |
改完重启 nginx 或者直接重启 NAS:
1 | synoservice --restart nginx |
但说真的,我非常不建议动这两个文件。DSM 升级的时候会覆盖它们,WebStation 重装或者打补丁的时候也会把你的改动吃掉。改一次以为搞定,半年后升一次系统又打回原形,还很难 debug。
除非你确实要改”群晖本体监听的端口”这种事,否则有更好的办法。
不碰模板的正确姿势
翻 nginx.conf 会看到最后这几行:
1 | http { |
这三行就是给用户留的”后门”。模板每次重新生成 nginx.conf 都会把它们保留着,只要我们在这三个目录里放自己的 .conf 文件,无论是 DSM 重启、WebStation 重装还是系统升级,都不会把我们的配置干掉。
三个目录分别用来干什么
| 目录 | 文件名规则 | 位于 nginx.conf 中的位置 | 适合放什么 |
|---|---|---|---|
/etc/nginx/conf.d/ | http.*.conf | http {} 段 | 全局指令:map、upstream、limit_req_zone 等 |
/etc/nginx/app.d/ | server.*.conf | http {} 段 | 群晖自家应用(DSM、套件)的附加 server 配置 |
/etc/nginx/sites-enabled/ | 随意 | http {} 段末尾 | 用户自己的 vhost / 反代,首选放这里 |
我的建议:
sites-enabled/是你应该优先用的目录,文件名没有规则限制,可读性高,管理方便;app.d/最好别碰,那是群晖套件自己在用的;conf.d/只有在你要写map/upstream这种”全局级”指令时才用,比如写跨域的 Origin 白名单。
/usr/local/etc/nginx/ 和 /etc/nginx/ 是什么关系
如果你到处翻系统,会发现还有一个 /usr/local/etc/nginx/ 目录,里面也有 conf.d、sites-enabled。那是什么东西?
实测下来,它们其实是软链到 /etc/nginx/ 的:
1 | ls -la /usr/local/etc/nginx/ |
所以改哪边都一样。我一般直接在 /etc/nginx/sites-enabled/ 下操作,路径更短。
一个完整的实例:反代 Home Assistant
我家 Home Assistant 跑在群晖的 Docker 里,占着 8123 端口。我想让它能通过 ha.dong4j.site 这个域名直接访问,而不是每次都要记 IP + 端口。
在 /etc/nginx/sites-enabled/ 下新建一个文件:
1 | vim /etc/nginx/sites-enabled/home-assistant.conf |
内容:
1 | server { |
测试一下配置:
1 | nginx -t |
没报错就 reload:
1 | nginx -s reload |
搞定。浏览器直接访问 http://ha.dong4j.site 就能进 Home Assistant 了,DSM 完全不知道发生了什么,它还以为自己在好好跑 WebStation。
同样的思路能干的事
这套路几乎能覆盖所有”我想让群晖 Nginx 帮我干点事”的场景:
- 反向代理 Docker 里的任意服务:Portainer、Grafana、Vaultwarden、Homepage …
- URL Rewrite:把静态 HTML 改成伪静态路由;
- 限流 / IP 白名单:
limit_req_zone(放conf.d/http.xxx.conf)+limit_req; - 统一 CORS 头:
map $http_origin $cors_header+add_header。
踩坑记录
顺手记几个我自己踩过的点。
坑 1:文件名不符合规则,include 不到
conf.d/ 和 app.d/ 这两个目录的 include 语句是 带 glob 的:
1 | include conf.d/http.*.conf; |
意味着如果你在 conf.d/ 下建了个 myvhost.conf(不是 http.myvhost.conf),永远不会被加载,还找不到原因。我第一次就在这儿翻过车,查了半天以为是语法不对。
sites-enabled/ 的 include 是 *,没有这个限制,所以首选放这里。
坑 2:改完没 reload 看起来没生效
群晖上 reload 用这两个命令都可以:
1 | nginx -s reload |
前者是 nginx 标准做法,不会断开已有连接;后者会重启整个 nginx 服务(会有几秒的短暂 502)。我一般 reload 够用就用前者。
坑 3:DSM 升级会不会丢?
我亲身经历过从 DSM 7.1 升到 7.2,以及 7.2 的几次小版本更新。结论:
/etc/nginx/sites-enabled/里的自定义文件 —— 没丢;/etc/nginx/conf.d/http.xxx.conf—— 没丢;- 手动改过的
nginx.conf或mustache模板 —— 被覆盖; - WebStation 卸载重装之后,
sites-enabled/也依然在。
所以只要你坚持”往 include 目录里加文件”这条原则,升级基本无忧。
坑 4:端口被 DSM 占了
群晖默认把 80 跳转到 5000、443 跳转到 5001,这两个端口是被 DSM 占用的。如果你的 server 想监听 80(像我上面那个例子那样),要么:
- 让家里的路由器把公网的 80 端口映射到群晖的 80,交给我们自己的
sites-enabled里的 server 处理; - 或者直接用非标端口,比如
8080/8443,避开冲突。
我自己是让 Cloudflare 回源端口走非标端口的,这样群晖自带的 DSM 跳转一点都不受影响。这部分可以看 [[6b13f395|另一篇关于 Cloudflare CDN 的改造]]。
最后聊两句
写完这篇发现一个挺有意思的事:群晖的 Nginx 其实已经把该留的后门都留好了,只是文档里没人强调。
如果你也在群晖上折腾反向代理,希望这篇能让你少走两段弯路 —— 不要改 nginx.conf,也不要改 .mustache 模板,找 include 的目录、建自己的 .conf 文件,这条路最稳。
参考:

















