一直想找个时间说说 Nginx Proxy Manager (以下简称NPM)这个自认为非常适合 self host使用的Reverse Proxy。但是最近也在使用中逐渐发现各种坑爹之处。这下好了,也不用推荐这个项目了,干脆讲讲最近一次修复吧。
官方网站上有这个项目的各种信息。然后Github Issue里面已经积攒了1300多个issue了。怎么说呢,虽然我没有真的用过JS,但是这个数量真的相当打击人。而且再想起来之前经历过的一些坑,想必过不了多久就切换到Caddy了吧。
无法更新证书
前两天,我发现无法用npm更新https证书。查看docker日志,发现 error log 说有另一个 Certbot 实例正在运行。但是我这个Certbot 是由 Ngix Proxy Manager 的 container 管理的,我自己肯定是没有闲的跑两个NPM的。Log中看到的Error如下:
[3/23/2024] [11:46:47 PM] [SSL ] › ℹ info Renewing SSL certs close to expiry...
[3/23/2024] [11:46:47 PM] [SSL ] › ✖ error Error: Command failed: certbot renew --non-interactive --quiet --config "/etc/letsencrypt.ini" --work-dir "/tmp/letsencrypt-lib" --logs-dir "/tmp/letsencrypt-log" --preferred-challenges "dns,http" --disable-hook-validation
Another instance of Certbot is already running.
at ChildProcess.exithandler (node:child_process:402:12)
at ChildProcess.emit (node:events:513:28)
at maybeClose (node:internal/child_process:1100:16)
at Process.ChildProcess._handle.onexit (node:internal/child_process:304:5)
结果 Google 一下果然有收获:
所以解决方案也很简单
sudo docker exec -it nginx_proxy_manager /bin/bash
# in nginx_proxy_manager container
find / -type f -name ".cert.lock"
# Output:
/etc/letsencrypt/.certbot.lock
现在我怀疑,Nginx Proxy Manager在遇到一些 SSL Certificate refresh 的错误的时候,可能会 panic,导致这个 lock 文件就被泄漏了。不删除的话,就会一直报 error log。但是这个container health status 不会有任何反应,在Nginx Proxy Manager的UI上面也不会有什么反应。只有你手动去 renew 你的 Certificate 的时候,才会悻悻给个 Internal Error
。然而除此之外就什么都没有了。逼着你去看 log。
这已经不是我第一次遇到这个问题了。现在我甚至怀疑,如果在renew的过程中,stop这个container,这个 lock 文件估计都不会被删除。
SSL 证书和 Proxy Hosts之间可能有Consistency的问题
因为有时候实验的缘故,有些SSL的证书我之后就不会再用了。所以SSL Certificates里面有不少是废弃的证书,而且因为之前的那个Bug,很多都是过期了我才发现。于是在修复了 Renew 的问题之后,我就顺手在 SSL Certificates tab 下面直接删除了几个不再用的证书。
谁知道删除了之后的结果是,在 Proxy Hosts 里面,如果尝试 Edit,或者删除 SSL Certificate 对应的 Proxy 记录,也会触发 Error。这个就也很无厘头。挺难想象这么个基础的 Consistency 问题都解决不好。注意啊,这里我是用 UI 删除 SSL Certificate的,可不是我在DB或者FS里面直接 bypass 所有code删除的。
更过分的事,如果只是这个Proxy Host从此不能用UI修改我也就认了。下次Container启动的时候直接就crash了,Nginx 拒绝启动了,所以一下子所有的 Reverse Proxy 就都挂了。令人崩溃。而且毫不意外的,Nginx Proxy Manager 的 Container Health Status 依旧显示 Healthy。很显然这个根本 container 就没有 health check。
Nginx start failure:
Starting nginx ...
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/npm-2/fullchain.pem": BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory:calling fopen(/etc/letsencrypt/live/npm-2/fullchain.pem, r) error:10000080:BIO routines::no such file)
Github上面也有不少相应的Issue report,比如这个:
解决方法也很无厘头。把找不到的Nginx pem文件结构补上。然后NPM会发现这个Certificate不对,然后就会再申请一个新的。至于之后再怎样去删除这个 Certificate,暂时就先放一边了。
# As it is complaining npm-2 missing in my case
# so I should re-make the npm-2/ directory
sudo docker exec -it nginx_proxy_manager /bin/bash
cd /etc/letsencrypt/live
# I do have npm-1/ dir.
cp -r npm-1 npm-2
# Then restart the container.
极慢的启动速度
Nginx本身是很快的。但是我也是万万没想到NPM启动速度可以慢至 5 分钟。从 Log 来看,应该是 ❯ Setting ownership ...
这一步花费了很长的时间。Github上面也是怨声载道:
我查了一下文件数量 find -type f | wc -l
:
/etc/letsencrypt/: 1815
/data/: 491
这个数量也不能算特别多吧。也不是很清楚为什么这么慢。不过鉴于我只有20几个hosts,我也看不太明白为什么 /etc/letsencrypt/ 下面有 1815个文件。keys/ 下面有718个,总觉得有点太多了。
这个问题目前我是没有看到有效的解决方案的。只能干等。呃,也许用 NVME 跑的会快?毕竟我这个是 HDD 而且还是远程挂载,所以可以说是我自己的锅…
最后
还是要感谢NPM的作者的。毕竟是用爱发电的开源项目,有的用已经很好了,而且对于一开始接触 Self Host 的朋友来说,NPM 的 UI 还是很友好的 (在不出Bug的情况下)。(不枉我在 [year-of-self-host-2023-summary] 总结里面还强烈推荐它 🤦)
但是如果有更严肃的需求,或者说有点点 Infra-as-code 的想法的,还是及早切换的好。SWAG, Traefik, Caddy,HAProxy 或者直接手撸 Nginx config (不过如果是直接用 Nginx,不如选择 SWAG,配置上面应该是一样的,但是大概可以开箱即用一堆安全插件)都是可以的。接下来如果有时间,本人肯定是要迁移的。