Nginx Proxy Manager 日常运维手册

Nginx Proxy Manager(NPM)v2.16.0 日常运维手册:巡检与健康检查、数据备份与迁移恢复实测、版本升级回滚、证书续期机制与六类故障排查实录,均已在 Ubuntu 22.04 实测通过

Nginx Proxy ManagerNginx Proxy Manager2026/10/18

Nginx Proxy Manager 日常运维手册

目标:面向已按部署篇完成 Nginx Proxy Manager(NPM)v2.16.0 部署的运维人员,覆盖日常巡检、数据备份与迁移恢复、版本升级与回滚、证书续期机制、日志管理与典型故障排查六大场景,全部命令与回显均已在 Ubuntu 22.04 实测通过,故障案例均为真实发生并记录的排障实录。

一、环境信息

本章为全文实测基准,所有巡检、备份、升级、排障操作都在同一套 v2.16.0 实例上完成。

  • 操作系统:Ubuntu 22.04(NPM v2.16.0 运行实例,部署基线见《Nginx Proxy Manager Docker Compose 部署指南》)
  • 实例形态:编排部署于 /opt/npm(主服务与演示后端两个服务实例),数据挂载 /opt/npm/data 与 /opt/npm/letsencrypt,端口映射 8093/8094/8095/8096
  • 实例数据:2 条代理主机(demo.local 挂自定义证书与强制 HTTPS、acl.local 挂访问控制)、1 条 404 主机、1 条 Stream、1 张自签证书、1 条 ACL
  • 管理账号:admin@example.com(API 令牌已保存在本地 /opt/npm/token.txt,1 天有效期)

二、日常巡检与健康检查

日常巡检围绕四个层面:管理面是否存活、数据面配置是否合法、服务状态与资源占用、主机是否可正常转发。

2.1 管理面健康检查

无需认证的管理接口是最轻量的探活命令,可直接纳入监控拨测:

curl -s http://127.0.0.1:8094/api/

实测回显:

{"status":"OK","setup":true,"version":{"major":2,"minor":16,"revision":0}}

status:OK 即管理面存活;setup:true 表示元数据库完好;version 与预期版本一致说明没有意外升级。

2.2 数据面配置合法性检查

管理面存活不代表 Nginx 数据面配置合法,进入 NPM 服务实例执行标准检查命令:

nginx -t

实测回显:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

test is successful 即当前全部生成配置可正常加载。若此命令报错,优先按第六章 Q1 排查。

2.3 服务监听与资源基准

确认 NPM 的四个业务/管理端口都在宿主机正常监听:

ss -ltn | grep -E ':(8093|8094|8095|8096)\b'

实测回显(4 个端口各有 IPv4/IPv6 两条监听记录):

LISTEN 0      4096         0.0.0.0:8093       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8094       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8095       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8096       0.0.0.0:*
LISTEN 0      4096            [::]:8093          [::]:*
LISTEN 0      4096            [::]:8094          [::]:*
LISTEN 0      4096            [::]:8095          [::]:*
LISTEN 0      4096            [::]:8096          [::]:*

资源基准(本实例实测):近空载时主服务常驻内存约 77 MiB、演示后端约 10 MiB,CPU 趋近 0。巡检时若内存持续增长或 CPU 长期高位,结合 6.1 节日志确认是否有异常流量或攻击特征。

2.4 业务转发抽检

抽查代表性主机是否仍正常转发(HTTP 主机 + HTTPS 主机各一条):

curl -s -o /dev/null -w 'acl.local HTTP=%{http_code}\n' -u admin:q1w2e3r4 -H "Host: acl.local" http://127.0.0.1:8093/
curl -sk -o /dev/null -w 'demo.local HTTPS=%{http_code}\n' --resolve demo.local:8095:127.0.0.1 https://demo.local:8095/

实测回显:

acl.local HTTP=200
demo.local HTTPS=200

两个 200 即全链路(Nginx → 转发模板 → 上游)健康;出现 401/502/404 时按第六章对应条目处理。

三、数据备份与恢复

NPM 的全部状态在 /data 与 /etc/letsencrypt 两个挂载目录(内容构成详见《Nginx Proxy Manager 2.16.0 配置参数详解》),本章给出可实际执行的备份与恢复流程,恢复流程已做完整的迁移实测。

3.1 备份:打包数据目录

最简单可靠的备份就是停机打包两个挂载目录(在线打包同样可行——SQLite 单文件在写入间隙拷贝一般一致,但生产环境建议低峰执行或先停止主服务实例):

mkdir -p /opt/backup
tar -czf /opt/backup/npm-data-$(date +%Y%m%d).tar.gz -C /opt/npm data letsencrypt
ls -lh /opt/backup/ && tar -tzf /opt/backup/npm-data-*.tar.gz | wc -l

实测回显(本实例全量数据,含全部主机/证书/日志):

total 20K
-rw-r--r-- 1 root root 19K 10月 18 15:25 npm-data-20261018.tar.gz
48

实测全量备份仅 19K、48 个对象——NPM 的状态极轻量,备份成本几乎可以忽略。必须保留的关键文件:database.sqlite(元数据)、keys.json(令牌签名密钥,实测权限 600,丢失后旧令牌全部失效)、custom_ssl/ 与 letsencrypt/(证书)。

3.2 恢复与迁移实测

以下演示「备份 → 在新位置恢复 → 用恢复的数据启动一套全新实例 → 全链路验证」的完整迁移流程(等价于迁移到新服务器的过程,仅需把备份包传到新服务器后执行相同步骤)。

第一步,解包备份到新目录:

mkdir -p /opt/restore && cd /opt/restore
tar -xzf /opt/backup/npm-data-20261018.tar.gz
ls -d data letsencrypt && ls data/database.sqlite data/keys.json

实测回显:

data
letsencrypt
data/database.sqlite
data/keys.json

第二步,用恢复出的数据启动实例。启动方式与全新部署完全一致(编排写法见《Nginx Proxy Manager Docker Compose 部署指南》),仅两处差异:数据目录挂载指向 /opt/restore/data 与 /opt/restore/letsencrypt(而不是 /opt/npm 下的原目录);实例需接入与上游后端互通的网络(本实测接入了原编排网络,使 demo 上游可达;跨主机迁移时使用目标机网络并把上游地址指向目标机的后端)。本实测实例监听 18093/18094/18095 三个临时端口以避免与原实例冲突。

第三步,全链路验证恢复效果(等 30 秒让服务完成初始化):

sleep 30 && curl -s http://127.0.0.1:18094/api/
TOKEN=$(cat /opt/npm/token.txt) && curl -s "http://127.0.0.1:18094/api/nginx/proxy-hosts" \
  -H "Authorization: Bearer $TOKEN" \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print('restored_hosts:', [(h['id'], h['domain_names']) for h in d])"
curl -s -o /dev/null -w 'RESTORED_PROXY=%{http_code}\n' -H "Host: demo.local" http://127.0.0.1:18093/
curl -sk -o /dev/null -w 'RESTORED_HTTPS=%{http_code}\n' --resolve demo.local:18095:127.0.0.1 https://demo.local:18095/

实测回显:

{"status":"OK","setup":true,"version":{"major":2,"minor":16,"revision":0}}
restored_hosts: [(2, ['acl.local']), (1, ['demo.local'])]
RESTORED_PROXY=301
RESTORED_HTTPS=200

四项验证全部通过的结论:管理员与全部主机配置完整恢复(setup:true + 两条主机);旧 API 令牌继续有效(keys.json 随备份恢复);HTTP 强跳 301 与 HTTPS 200 说明证书绑定关系也完整还原。这正是日常演练迁移的标准动作:每次备份后可定期抽检一次恢复流程,确保备份真的可用。

3.3 备份自动化建议

将 3.1 节命令写入计划任务即可实现每日备份(示例:每天 02:30 备份并保留 14 天,写入 root 的 crontab):

30 2 * * * tar -czf /opt/backup/npm-data-$(date +\%Y\%m\%d).tar.gz -C /opt/npm data letsencrypt && find /opt/backup -name 'npm-data-*.tar.gz' -mtime +14 -delete

两点提醒:备份目录 /opt/backup 不放在 /opt/npm 内,避免被下次备份重复打包;跨机容灾则把 /opt/backup 同步到异地(rsync 或对象存储均可)。

四、版本升级与回滚

4.1 升级标准流程

三步:备份 → 变更版本标签 → 重建服务实例。

  1. 按 3.1 节完成备份(跨版本升级必须做,原因见 4.2 的回滚限制);
  2. 在部署编排中把主服务的版本标签(如 2.16.0)改为目标版本;
  3. 重建服务实例:编排检测到版本变化会自动拉取新版本并重建,数据目录不受影响,全程约半分钟(具体命令与实测回显见《Nginx Proxy Manager Docker Compose 部署指南》的升级操作)。

升级完成后立即执行第二章 2.1~2.4 的巡检命令确认健康。

4.2 回滚

编排形态下回滚就是把版本标签改回旧版本并重建服务实例。v2.16.0 之前的版本(如 2.12.x → 2.16.0 跨度)涉及元数据库自动迁移,迁移后数据库结构已变,直接回滚旧版本可能无法识别新库——这是回滚最大的坑。因此升级前务必备份(3.1 节),回滚时先恢复备份再启动旧版本,而不是仅改标签。

4.3 版本与标签策略

生产环境固定精确版本标签(如 2.16.0),升级动作显式化;latest/2 标签的自动漂移会让回滚失去基准(标签选型依据见《Nginx Proxy Manager 2.16.0 介绍与选型指南》)。关注官方 Releases 中的安全修复条目,v2.16.0 即包含多项安全修复(证书私钥权限、密码修改后旧令牌未失效等),遇到同类 CVE 应尽快跟进升级。

五、证书申请与续期机制

5.1 自动续期机制

NPM 内置 Certbot 5.8.0,续期由管理后端的定时器驱动。每次服务启动时日志可见续期器初始化(实测服务运行日志节选):

npm-2.16.0-app  | [10/18/2026] [7:40:20 AM] [SSL      ] › ℹ  info      Let's Encrypt Renewal Timer initialized
npm-2.16.0-app  | [10/18/2026] [7:40:20 AM] [SSL      ] › ℹ  info      Renewing SSL certs expiring within 30 days ...
npm-2.16.0-app  | [10/18/2026] [7:40:20 AM] [IP Ranges] › ℹ  info      IP Ranges Renewal Timer initialized
npm-2.16.0-app  | [10/18/2026] [7:40:20 AM] [SSL      ] › ℹ  info      Completed SSL cert renew process

续期窗口为 30 天——运行实例内的续期模块源码参数为 renewBeforeExpirationBy: [30, "days"](/app/internal/certificate.js 实读核实),即后端每日检查一次,到期不足 30 天的 Let's Encrypt 证书自动触发 Certbot 续期(v2.16.0 起默认签发 ECDSA secp384r1 证书,全局参数文件 /etc/letsencrypt.ini 的逐项解读见《Nginx Proxy Manager 2.16.0 配置参数详解》)。续期要求与首次申请相同:HTTP 校验需域名公网可达且 80 端口开放,DNS 校验需凭据有效。

5.2 证书有效期巡检

通过证书列表接口批量核对有效期(自定义证书与 Let's Encrypt 证书同表):

TOKEN=$(cat /opt/npm/token.txt) && curl -s "http://127.0.0.1:8094/api/nginx/certificates" \
  -H "Authorization: Bearer $TOKEN" \
  | python3 -c "import json,sys; d=json.load(sys.stdin); [print(c['id'], c['provider'], c['nice_name'], c['domain_names'], 'expires_on:', c['expires_on']) for c in d]"

实测回显(本实例仅一张自签证书;生产环境应有 provider=letsencrypt 的记录):

1 other demo.local self-signed ['demo.local'] expires_on: 2027-10-18 07:18:51

巡检关注点:expires_on 距今不足 30 天且持续未变的 Let's Encrypt 证书,说明自动续期未成功,立即查 /data/logs/letsencrypt.log 定位原因(常见原因见第六章 Q2)。管理界面「SSL Certificates」页同样展示该信息与到期倒计时。

5.3 续期失败兜底

Let's Encrypt 申请/续期的完整过程都落在 /data/logs/letsencrypt.log(自动轮转出 .1 等历史文件)。实测一次申请失败的日志尾部(无效邮箱被 ACME 拒绝):

certbot.errors.Error: Unable to register an account with ACME server. The ACME server believes admin@example.com is an invalid email address. Please ensure it is a valid email and attempt registration again.
2026-10-18 07:25:05,396:ERROR:certbot._internal.log:Unable to register an account with ACME server. The ACME server believes admin@example.com is an invalid email address. Please ensure it is a valid email and attempt registration again.

调试签发流程时可设置环境变量 LE_STAGING=true 走 Let's Encrypt 测试环境,避免调试期触发正式环境限额(频率限制见官方文档)。

六、日志管理与排障

6.1 日志文件体系

全部日志集中在 /data/logs(宿主机 /opt/npm/data/logs),实测本实例日志总量与构成:

du -sh /opt/npm/data/logs && ls -lh /opt/npm/data/logs/proxy-host-1_access.log /opt/npm/data/logs/backend.log

实测回显:

76K     /opt/npm/data/logs
-rw-r--r-- 1 root root  21K Oct 18 07:40 /opt/npm/data/logs/backend.log
-rw-r--r-- 1 root root 1.8K Oct 18 07:40 /opt/npm/data/logs/proxy-host-1_access.log

命名规律与用途(完整对应关系见《Nginx Proxy Manager 2.16.0 配置参数详解》):<类型>-<主机ID>_access.log / _error.log 为各主机独立日志(类型含 proxy-host、dead-host、redirection-host、stream),fallback_* 为兜底站点与全局错误,letsencrypt.log 为证书过程日志,backend.log 为管理 API 日志。

访问日志的轮转由 NPM 内置的 logrotate 配置管理(/etc/logrotate.d/nginx-proxy-manager 实测内容节选):

/data/logs/*_access.log /data/logs/*/access.log {
    su npm npm
    create 0644
    weekly
    rotate 4
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
    kill -USR1 `cat /run/nginx/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript

即:每周轮转、保留 4 份、压缩归档,轮转后向 Nginx 发 USR1 信号重开日志文件。磁盘巡检时该目录通常稳定在很小体量;v2.16.0 新增的界面内日志查看器读取的正是这些文件,无需登录服务器即可查看。

6.2 故障排查实录

以下五例均为本文实测中真实发生并记录的故障,每例给出「现象 → 根因证据 → 处理动作」。

Q1:数据面配置非法 / 界面提示主机离线 现象:nginx -t 报错,或界面主机卡片出现离线横幅。根因证据链:先看生成配置的错误副本与主机错误日志(配置生成机制见《Nginx Proxy Manager 2.16.0 配置参数详解》):

ls /opt/npm/data/nginx/proxy_host/ /opt/npm/data/nginx/stream/ && tail -5 /opt/npm/data/logs/proxy-host-1_error.log

实测回显(正常实例的基线输出;异常时会出现 .conf.err 文件与 Nginx 错误行):

/data/nginx/proxy_host/:
1.conf
2.conf

/data/nginx/stream/:
2.conf

处理:.conf.err 中的 Nginx 报错即语法错误原文(多数来自 Advanced Config 手写指令),改正后重新在界面保存该主机即可恢复。

Q2:代理返回 502 Bad Gateway 实测现象:停止演示后端后访问 demo.local:

curl -sk -o /dev/null -w 'BACKEND_DOWN=%{http_code}\n' --resolve demo.local:8095:127.0.0.1 https://demo.local:8095/

实测回显:

BACKEND_DOWN=502

根因证据(主机错误日志):

grep -E 'connect|upstream|resolve' /opt/npm/data/logs/proxy-host-1_error.log | tail -2

实测回显:

2026/10/18 07:24:27 [error] 273#273: *11 demo could not be resolved (2: Server failure), client: 10.89.24.1, server: demo.local, request: "GET / HTTP/1.1", host: "demo.local:8095"

处理:could not be resolved → 上游主机名不可解析(后端已停/网络不通),恢复后端即恢复(实测恢复后 502 变回 200);connect() failed → 解析成功但端口不通,查上游服务与防火墙;日志为空但持续 502 → 用 2.2 节 nginx -t 确认配置本身。

Q3:Let's Encrypt 证书申请失败 实测现象(无效域名 + 假邮箱走 HTTP 校验):

{"error":{"code":500,"message":"Internal Error"},"debug":{"stack":["Error: Saving debug log to /data/logs/letsencrypt.log","Unable to register an account with ACME server. The ACME server believes admin@example.com is an invalid email address. ...(节选)]}}

处理:按 letsencrypt.log 中的原始 Certbot 错误分三类处置——邮箱无效(本例)→ 换真实邮箱;域名解析不通 → HTTP 校验需域名公网解析且 80 端口可达,或改用 DNS 校验 + 泛域名;触达频率限额 → LE_STAGING=true 走测试环境调试,正式签发等待限额窗口。

Q4:启动/新建主机时报 port is already allocated 实测现象(8093 已被占用时再绑定同端口,错误关键字行节选):

Bind for 0.0.0.0:8093 failed: port is already allocated

处理:ss -ltnp | grep <端口> 找到占用方——多为同机另一套 NPM 实例或重复执行了部署;停掉多余实例或改端口。Stream 主机新建时端口冲突也会在界面以类似错误提示。

Q5:HTTPS 测试报 tlsv1 unrecognized name 实测现象:

curl -sk https://127.0.0.1:8095/ -H "Host: demo.local"; echo "EXIT=$?"

实测回显:

EXIT=35

加 -v 可见 TLS alert, unrecognized name。根因:TLS 握手按 SNI 匹配证书与 server 块,用 IP 访问时 SNI 不是任何已配置域名。这不是故障,是测试方法问题:用 --resolve(或 openssl s_client -servername)带上正确 SNI 即通过(2.4 节巡检命令即采用该写法)。同类问题也会出现在「客户端未发送 SNI」的老旧设备访问场景。

Q6:单命令形态启动后 Nginx 反复重启报 host not found in upstream 实测现象(元数据里存在指向编排网络服务名的 Stream/代理主机时,脱离编排网络单命令运行):

❯ Starting nginx ...
nginx: [emerg] host not found in upstream "demo" in /data/nginx/stream/1.conf:10

处理:单命令/迁移形态下先保证上游地址可达(改用 IP 或跨网可达的域名),或临时移除引用不可达上游的主机。这也是迁移演练中必须让恢复实例接入与上游连通的网络的原因(3.2 节实测即接入了同一编排网络)。

七、参考链接

  1. NPM 官方文档:https://nginxproxymanager.com/
  2. 官方 GitHub 仓库与 Releases(升级依据):https://github.com/NginxProxyManager/nginx-proxy-manager/releases
  3. 本组件部署流程:《Nginx Proxy Manager Docker Compose 部署指南》
  4. 本组件配置详解:《Nginx Proxy Manager 2.16.0 配置参数详解》
  5. 本组件认知与选型:《Nginx Proxy Manager 2.16.0 介绍与选型指南》
  6. Certbot 官方文档(续期参数与频率限制):https://eff-certbot.readthedocs.io/