Nginx Proxy Manager 使用笔记
版本说明
本文写于 2022-03。
Nginx Proxy Manager 的核心界面操作流程(新增代理主机、SSL 证书申请)经 2026-07 复核基本仍适用,具体 UI 细节请以实际部署版本为准。
# 1. 手写 nginx.conf 反代十个域名,第十一个开始容易出错
给单个域名配反向代理,手写 nginx.conf 完全够用;但域名/子域名一多,每加一个都要新建 server 块、申请证书、改配置、nginx -t、reload,重复劳动之外还容易漏配 SSL 或写错 proxy_pass 目标。Nginx Proxy Manager(NPM)把这套流程做成了一个 Web UI + 数据库驱动的管理面,本质是用 Docker 容器跑一个预置了证书自动化(Let's Encrypt)的 Nginx,把"改配置文件"变成"填表单"。
# 2. 为什么用它而不是继续手写配置
- 证书全自动:申请、续期 Let's Encrypt 证书在 UI 里点几下就完成,不用自己维护
certbot定时任务。 - 配置即数据:每个代理主机(Proxy Host)的配置存在 SQLite/MySQL 里,改动即时生效,不用手动
reload。 - 降低误配风险:域名、目标地址、SSL 强制跳转、WebSocket 支持这些常见项都是表单化的,比手写
location/proxy_set_header更不容易漏字段。
代价是:所有代理规则都过一层 NPM 自己的抽象,遇到非常规的 Nginx 高级用法(比如复杂的 map、自定义限流规则)时,还是需要在"Advanced" 标签页里手写 Nginx 片段,本质没有绕开 Nginx 配置本身,只是把常见场景标准化了。
# 3. 部署与使用:准备 → 执行 → 验证
# 3.1 准备:docker-compose.yml
version: '3'
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81' # 管理面板端口
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
2
3
4
5
6
7
8
9
10
11
12
# 3.2 执行:启动与初次登录
docker compose up -d
浏览器访问 http://<host>:81,默认账号 admin@example.com / 密码 changeme,首次登录必须立即改掉——这是公开在官方文档里的默认凭证,暴露在公网的实例几分钟内就会被扫到。
# 3.3 执行:添加一个代理主机
Hosts → Proxy Hosts → Add Proxy Host:
- Domain Names:
app.example.com - Scheme:
http(后端服务的协议,不是访问者用的协议) - Forward Hostname/IP:后端服务的容器名或内网 IP
- Forward Port:后端服务端口
- 勾选
Block Common Exploits、Websockets Support(如果后端需要) - SSL 标签页:选择
Request a new SSL Certificate,勾选Force SSL
# 3.4 验证
# 确认证书签发成功
curl -vI https://app.example.com 2>&1 | grep -E "SSL certificate|subject"
# 确认强制跳转生效
curl -I http://app.example.com
# 应返回 301/308 跳转到 https
# 确认后端连通
curl -I https://app.example.com
# 应返回后端服务的实际状态码,而非 502
2
3
4
5
6
7
8
9
10
# 4. 常见坑
症状:证书签发一直失败,报 Failed authorization procedure。
原因:Let's Encrypt HTTP-01 验证需要 80 端口能从公网直接访问到 NPM 容器;如果域名解析还没生效、或者前面还有一层 CDN/防火墙挡住了 80 端口,验证请求根本到不了 NPM。
解药:先用 curl -I http://app.example.com/.well-known/acme-challenge/test 确认 80 端口链路畅通,再重新申请证书;用了 Cloudflare 之类的 CDN 要先把该域名的代理(橙色云朵)临时关掉。
症状:代理配置好了,访问返回 502 Bad Gateway。
原因:Forward Hostname 填的是宿主机 IP,但后端服务和 NPM 是不同的 Docker 网络,容器间不通;或者 Scheme 选错(后端明明是 https 却选了 http)。
解药:把后端服务和 NPM 放进同一个 Docker network,Forward Hostname 直接填服务名(Docker DNS 自动解析);确认 Scheme 与后端服务实际监听的协议一致。
症状:管理面板本身长期暴露在公网,被扫描器爆破默认口令。 原因:81 端口习惯性对公网开放,且很多人图方便一直用初始密码,或者密码强度不够。 解药:管理面板端口只对内网/VPN 开放,或者在前面再加一层 Nginx Proxy Manager 自己代理并配 IP 白名单;同时务必首次登录就改密码并开启强密码策略。
# 5. 可复用的规则
- HTTP-01 证书验证要求 80 端口从公网直达,前面有 CDN/防火墙时先临时放行再申请证书。
- 502 优先查两件事:Forward Hostname 是否在同一网络能解析、Scheme 是否与后端实际协议一致。
- 管理面板端口(81)默认凭证必须首次登录立即修改,且不应对公网开放。
- 常规反代场景用表单配置,遇到高级 Nginx 特性再用 "Advanced" 标签页手写片段,两者不冲突。
# 6. 延伸阅读
手写 Nginx 反代与限速限流的原理见 nginx 利用内置模块配置限速限流;证书之外的访问控制见 Nginx 添加用户认证。
# 7. Agent 可直接解析的元数据块
{
"_meta": {
"doc_version": "2026-07-29",
"article_id": "nginx-proxy-manager-usage",
"profile_context": "any",
"estimated_setup_time": "20min"
},
"quick_start": {
"step_1": "docker compose up -d",
"step_2": "浏览器访问 http://<host>:81,用默认账号登录并立即改密码",
"step_3": "Proxy Hosts → Add Proxy Host,填写域名/后端地址,SSL 标签页申请证书并勾选 Force SSL"
},
"safety_rules": [
"首次登录必须立即修改默认账号密码",
"管理面板端口(81)不应对公网开放",
"申请证书前确认 80 端口对公网可直达(无 CDN/防火墙阻挡)"
],
"verification": {
"check_cert": "curl -vI https://<domain> 确认证书 subject 与域名匹配",
"check_redirect": "curl -I http://<domain> 应返回 301/308 跳转",
"check_backend": "curl -I https://<domain> 应返回后端实际状态码而非 502"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AI Agent 使用指南:
- 当用户说"帮我加一个反代域名" → 按
quick_start.step_3填表单,再用verification三项确认 - 当用户说"502 报错" → 按第 4 节第二条排查 Docker 网络与 Scheme 配置
- 02
- ORDER BY 配合 LIMIT 触发的索引选择陷阱 原创08-07
- 03
- Nginx 运维知识地图:从配置基础到反向代理实战 原创07-29