前言
很早之前就看到大佬的文章安利NPM和ddns-go了,只是我一直不理解它们的作用,原先我一直使用的是宝塔面板进行反向代理,用久了宝塔之后发现申请的SSL证书只有90天有效期,过期之后没有自动续签,具体就不知道哪个环节出错了,所以寻求新的解决方案,这就绕回到NPM,当然如果仅仅是为了自动续签,还是有其他方案的,比如:certbot、allssl等。
之所以选择NPM,主要是它既有反向代理,又能实现证书的自动续签,其次它比宝塔更轻量级,使用范围更广,在内网搭建什么系统,都能用到NPM。我希望一个系统能做到所有需求,而不是东平西凑。
NPM(
nginx-proxy-manager):Nginx反向代理神器之一,自动管理nginx代理配置、Let’s Encrypt的ssl证书自动申请和续期
ddns-go:非常好用的动态域名解析服务,家用NAS必备神器。因为我用的是云服务器,有固定的公网IP,可以不用。
NPM
DockerHub镜像:jc21/nginx-proxy-manager – Docker Image | Docker Hub
创建工作目录
对于一个喜欢整洁的人,在任何方面都希望是有条理的,将文件放在它该在的位置,创建NPM目录
mkdir /DockerFile/npm
依旧使用最简单高效的Docker compose创建项目,新建docker.compose.yml配置文件:
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '<NPM-后台端口>:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
修改nginx默认端口
如果你之前没有使用nginx或者准备完全弃用nginx,这里可以跳过,直接启动项目即可。
经过我的测试,我发现只有使用了反向代理的网站才能从宝塔面板里面剥离出来,添加到npm可以正常访问,可能是我的博客结构性问题,有两个网站没有使用反向代理,导致我没办法从宝塔面板迁移过来,所以我要nginx和npm并行。
我觉得应该是有完美的解决办法的,只是我还没有找到,关键在于npm怎么去关联项目的配置文件,以后修改博客架构的时候再看看。
nginx和npm都是监听的80和443端口,所以我需要把nginx的默认端口改成其他的,
修改nginx默认端口80→8080,443→444
# 这是宝塔面板中nginx的配置文件路径,安装方式不同路径有差异
sed -i 's/listen 80;/listen 8080;/g' /www/server/panel/vhost/nginx/*.conf
sed -i 's/listen 443 ssl http2;/listen 444 ssl http2;/g' /www/server/panel/vhost/nginx/*.conf
验证一下端口的占用情况
netstat -tulnp | grep nginx
netstat -tulnp | grep -E "80|443"

nginx:master指的是nginx,docker-proxy指的是npm。
如果原先启用了SSL证书,还需要注释掉这段代码:
# 注释或删除这一段
# if ($server_port !~ 443){
# rewrite ^(/.*)$ https://$host$1 permanent;
# }
这段会让任何访问 8080(HTTP)端口的请求都跳转到 HTTPS(443),
结果:NPM 请求 → 被重定向回自己 → 再请求 → 无限循环 → 浏览器打不开,重定向次数过多。
以上修改仅作用于需要保留在宝塔面板上运行的网站,迁移到npm上的网站可以直接停用。
启动项目
# 上线服务
docker-compose up -d
# 下线服务
docker-compose down
# 更新服务(新学一条更新命令,不知道有没有效)
docker-compose pull
docker-compose up -d
查看服务状态

在浏览器输入http://<ip>:<NPM-后台端口>进入NPM管理页面,初始账号密码如下:
默认帐户:admin@example.com
默认密码:changeme
验证通过后修改用户名和密码。

申请SSL证书
在我的原有的认知里,每个网站都有自己对应的一个SSL证书,接触到npm才知道,原来可以使用通配符证书,例如:*.xmhweb.cn、xmhweb.cn,这需要使用DNS Challenge的方式。下面以腾讯云为例讲解一下,如果你是其他服务商,可以看看链接中大佬们的文章。
在npm后台,添加Let's Encrypt证书:

按下图模版填写信息,DNS Provider选择DNSPod,获取id和key需要去腾讯云官网:API 密钥 – DNSPod

创建秘钥,填入npm,保存,证书就申请好了。

添加反向代理
这里以ddns-go为例,参考下表AI的解释,按需填写参数
| 字段 | 说明 | 示例值 | 建议 |
|---|---|---|---|
| Domain Names* | 域名(访问入口) | ddns.xmhweb.cn | ✅ 必填,支持多个域名(可用逗号分隔) |
| Scheme* | 协议类型 | http / https | ✅ 一般用 http(除非后端程序自带 HTTPS) |
| Forward Hostname / IP* | 后端目标服务器的 IP | 127.0.0.1 | ✅ 本地转发可填 127.0.0.1;也可填内网 IP(如 10.26.1.10) |
| Forward Port* | 后端端口号 | 9876 | ✅ 要与你要代理的程序监听端口一致 |
| Cache Assets | 是否缓存静态文件 | ❌ 关闭 | ⚠️ 不建议开启(会导致后台或动态页面更新延迟) |
| Block Common Exploits | 阻止常见攻击 | ✅ 开启 | ✅ 推荐打开,可防 SQL 注入、XSS、路径穿越等基础攻击 |
| Websockets Support | 支持 WebSocket 连接 | 根据应用决定 | 如果你的后端是 实时通信/聊天/监控 应用,要打开;普通网站可关 |
| Access List | 访问控制列表 | Publicly Accessible | ✅ 保持默认(如果你要限制 IP 可在这里配置白名单) |

前面说过我有两个网站需要保留在宝塔上运行,前面已经将nginx默认端口改成了8080和444,在npm里面还需要添加方向代理记录,指向8080端口,Forward Hostname / IP要填docker的默认主机IP地址:172.17.0.1;
# 测试npm是否能访问127.0.0.1的8080端口
docker exec -it 19 curl -I http://127.0.0.1:8080
# 查看docker的默认主机IP
ip addr show docker0 | grep inet
# 输出
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

SSL证书就选择我们前面添加的通配符证书即可,不用一个一个去重新申请了,就是不知道到期后是否会自动续期,需要实践才知道。
| 选项 | 含义 | 建议 |
|---|---|---|
| Force SSL | 强制所有 HTTP 请求(80端口)自动跳转到 HTTPS(443端口) | ✅ 推荐打开(让访问统一使用 HTTPS) |
| HTTP/2 Support | 启用 HTTP/2 协议(更快、更高效的 HTTPS 连接) | ✅ 推荐打开(速度明显提升) |
| HSTS Enabled | 启用 HSTS(HTTP Strict Transport Security),告诉浏览器“只能用 HTTPS 访问此域名” | ⚠️ 慎用:一旦启用,浏览器将强制用 HTTPS 访问,关闭后也要等缓存过期 |
| HSTS Subdomains | 对所有子域名也应用 HSTS(如 blog.xmhweb.cn、api.xmhweb.cn) | ⚠️ 慎用,仅在你确认所有子域名都支持 HTTPS 时再开启 |

设置了这些我的大部分网站都能访问了,这时我发现我的wordpress后台进不去了,问了AI给出的解释是:
访问 → https://blog.xmhweb.cn
↓
Nginx Proxy Manager(监听 443)
↓
转发到 WordPress(http://172.17.0.1:8080)
↓
WordPress 发现自己不是 https → 强制跳转到 https://blog.xmhweb.cn
↓
又回到 NPM → 又转 http → 又跳 https …
(循环)
解决方法是打开你的 WordPress 网站根目录,找到wp-config.php,在这一行的上面加上
// 识别反向代理的 HTTPS
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
define('WP_HOME', 'https://blog.xmhweb.cn');
define('WP_SITEURL', 'https://blog.xmhweb.cn');
/* That's all, stop editing! Happy publishing. */

加上反向代理(Nginx Proxy Manager,NPM)+ HTTPS 后,响应路径比原来多了一层,刚开始肉眼可见的感觉到速度慢了一拍,过了一会不知道为什么感觉变正常了。浏览器 → NPM (443) → BT Nginx (8080) → PHP → WordPress,多了一层Nginx反向代理,所有流量都要经过两次解析、两次TLS(加解密)。
DDNS-GO
ddns-go 是一个开源的动态域名解析 (Dynamic DNS, DDNS) 客户端。当你的公网 IP 经常变化(比如家庭宽带、动态 IP 服务器、NAS、或者云主机重启后 IP 变化),ddns-go 能自动检测当前公网 IP,并将它**实时更新到 DNS 服务商(如阿里云、腾讯云、Cloudflare 等),这样你就能一直通过固定域名(如 ddns.xmhweb.cn)访问你的设备,即使 IP 变了也不怕。
对于有固定公网IP的用户来说,ddns-go的作用好像就不怎么明显了,唯一的好处就是与域名服务商进行关联后不需要去后台添加解析记录。ddns-go会自动添加。
ddns-go的工作原理
1.定期检测当前公网 IP
- ddns-go 会每隔一段时间(默认 5 分钟)检测当前主机的公网 IP(IPv4 或 IPv6)。
2.对比上次记录
- 如果 IP 没变 → 不操作
- 如果 IP 变了 → 自动调用 DNS API 更新记录
3.自动更新 DNS 记录
- 通过 API 调用 DNS 服务商(如阿里云、腾讯云、Cloudflare、NameSilo 等)
- 更新 A 记录(IPv4)或 AAAA 记录(IPv6)
4.结果写入日志
- 可以在 Web 控制台查看更新时间、状态、IP 变化历史等。
DockerHub镜像地址:jeessy/ddns-go – Docker Image | Docker Hub
创建容器
mkdir /DockerFile/ddns-go
# 启动容器
docker run -d \
--restart=unless-stopped \
--name ddns-go \
-e PUID=1000 \
-e PGID=100 \
-p <端口>:9876 \
-v /DockerFile/ddns-go:/root \
jeessy/ddns-go \
-f 60
在浏览器输入http://<ip>:<端口>进入ddns-go管理页面,设置用户名和密码。
绑定DNS服务商
根据你的实际情况选择DNS服务商,如腾讯云,点击下方链接创建腾讯云API秘钥,其实就是通过这个秘钥赋予ddns-go解析授权。创建API秘钥:

将SecretId和SecretKey复制到ddns-go对应的位置,Domains填上需要解析的域名,保存。

可以看到日志里面一直在检测IPv4是否变化。











