Nginx Proxy Manager 的 Proxy Host 完全指南:入口端点、SSL 终结与反向代理实战
【免费下载链接】nginx-proxy-managerDocker container for managing Nginx proxy hosts with a simple, powerful interface项目地址: https://gitcode.com/GitHub_Trending/ng/nginx-proxy-manager
Proxy Host(代理主机)是 Nginx Proxy Manager(NPM)中最核心、最常用的功能模块:它为需要对外转发的 Web 服务提供一个统一入口端点,并能在边缘完成可选的 SSL 终结,让原本不支持 HTTPS 的后端服务也能以安全协议对外提供访问。阅读本文后,你将完整掌握 Proxy Host 的概念、字段含义、创建流程,以及它从一条数据库记录到一段真实 Nginx 配置的底层生成链路。
什么是 Proxy Host:Web 服务的入口端点
按照仓库内置帮助文档 es/ProxyHosts.md(英文版见 en/ProxyHosts.md)的定义:
Proxy Host 是你要转发的某个 Web 服务的入口端点(incoming endpoint)。
理解这句话需要拆开两个关键词:
- 入口端点(incoming endpoint):对外部客户端而言,Proxy Host 是一个可以被访问的地址,通常表现为「域名 + 端口(80/443)」。客户端只需要访问这个地址,无需关心背后真正的服务部署在哪台机器、哪个端口。
- 转发(forward):NPM 接收请求后,将其按规则转发到实际提供服务的后端(forward host、forward port)。转发本身是反向代理的经典动作——请求先到达 Nginx 边缘,再被代理到上游服务。
在源码层面,每一个 Proxy Host 最终都会对应一个 Nginxserver配置块。模板 backend/templates/proxy_host.conf 清晰地展示了这一结构:模板通过set $forward_scheme、set $server、set $port三个变量定义转发目标,再通过include conf.d/include/proxy.conf完成实际的proxy_pass动作:
server { set $forward_scheme {{ forward_scheme }}; set $server "{{ forward_host }}"; set $port {{ forward_port }}; # ... 监听、证书、安全头、强制 SSL 等片段 ... location / { # Proxy! include conf.d/include/proxy.conf; } }其中 docker/rootfs/etc/nginx/conf.d/include/proxy.conf 负责真正把请求转发出去,并补全一组标准的转发头:
add_header X-Served-By $host; proxy_set_header Host $host; proxy_set_header X-Forwarded-Scheme $x_forwarded_scheme; proxy_set_header X-Forwarded-Proto $x_forwarded_proto; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_pass $forward_scheme://$server:$port$request_uri;可见,「入口端点 + 转发目标」正是 Proxy Host 的全部本质:一个对外可见的地址(域名),加上一个内部可达的转发目标(协议 + 主机 + 端口)。
为什么需要 SSL 终结:让没有 HTTPS 能力的后端服务安全对外
帮助文档的第二句点出了 Proxy Host 最关键的增值能力:
它为你的服务提供可选的 SSL 终结(SSL termination)——即使该服务本身没有内置 SSL 支持。
什么是 SSL 终结
SSL 终结(TLS 终止)指在边缘代理(即 NPM 所在的 Nginx)上完成 HTTPS 握手、解密流量,然后把解密后的明文 HTTP 请求转发给后端。这样带来的收益很直接:
- 后端服务无需自行配置证书与私钥,可以用纯 HTTP 运行;
- 客户端与 NPM 之间的流量全程加密,杜绝明文传输;
- 证书的签发、续期、轮换集中在一个位置统一管理,运维成本大大降低。
源码中的 SSL 实现链路
SSL 终结能力在 NPM 中由三个模板片段协作完成:
- 监听端口:模板 backend/templates/_listen.conf 根据是否绑定了证书决定是否开启 443 端口监听。有证书时生成
listen 443 ssl;(含 IPv6 变体),并支持通过http2_support开关启用http2 on;。 - 证书挂载:模板 backend/templates/_certificates.conf 区分证书来源——由 Let's Encrypt 签发的证书使用
/etc/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem与privkey.pem,同时引入letsencrypt-acme-challenge.conf保证续期挑战可被 Nginx 响应;自定义上传的证书则读取/data/custom_ssl/npm-{{ certificate_id }}/下的同名文件。 - 强制跳转:模板 backend/templates/_forced_ssl.conf 在开启
ssl_forced后引入force-ssl.conf,把访问 80 端口的 HTTP 请求 301 跳转到 HTTPS,并可通过trust_forwarded_proto决定是否信任反向代理传入的X-Forwarded-Proto头。
关键提醒:可选(optional)
文档措辞是「可选的 SSL 终结」——这是 Proxy Host 区别于强制 HTTPS 的重要设计:certificate_id与ssl_forced均为可选字段(默认值0/false)。你不绑定证书、不强制跳转时,NPM 会生成一个纯 HTTP 的 80 端口server块,依旧可以完成转发。从 backend/schema/components/proxy-host-object.json 可见certificate_id属于普通可选属性,而ssl_forced的默认行为由数据库层控制。
因此,Proxy Host 可以灵活覆盖三种形态:
| 形态 | certificate_id | ssl_forced | 效果 |
|---|---|---|---|
| 纯 HTTP | 0 | false | 仅监听 80,转发明文流量 |
| HTTPS + HTTP 并存 | 证书 ID | false | 80/443 都可访问 |
| 强制 HTTPS | 证书 ID | true | 访问 80 自动跳转 443 |
为什么 Proxy Host 是 NPM 最常见的用途
帮助文档的第三句给出了定位结论:
Proxy Hosts 是 Nginx Proxy Manager 最常见的用途。
这一定位可以从 NPM 的同类功能对比中看出端倪。仓库前端将 Nginx 相关能力划分为四类(见 frontend/src/pages/Nginx 目录结构):
| 功能 | 定位 | 数据模型 |
|---|---|---|
| Proxy Hosts | 将 HTTP/HTTPS 请求反向代理到后端 Web 服务(最常用) | backend/models/proxy_host.js |
| Redirection Hosts | 域名级 301/302 重定向,不转发流量 | backend/models/redirection_host.js |
| Dead Hosts | 对无效域名返回 404,占位保护 | backend/models/dead_host.js |
| Streams | 四层 TCP/UDP 端口转发,不涉及 HTTP | backend/models/stream.js |
绝大多数互联网应用的对外形态都是「HTTP/HTTPS 之上的 Web 服务」——静态站点、前端应用、REST API、管理后台、媒体服务——它们恰好都属于 Proxy Host 的覆盖范围。相比之下,Redirection Host 只解决跳转,Dead Host 只解决兜底 404,Stream 只解决非 HTTP 的四层转发,适用面都窄得多。这也解释了为什么前端 Proxy Hosts 列表页(frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx)会内置搜索框按域名、转发主机与端口过滤,并且把「添加」按钮放在最显眼的位置——它是用户每天打交道最多的对象。
Proxy Host 的完整数据模型:核心字段全解
要真正用好 Proxy Host,需要吃透它的全部字段。后端 OpenAPI 定义 backend/schema/components/proxy-host-object.json 给出了权威清单,前端类型声明 frontend/src/api/backend/models.ts(ProxyHost接口)与之对应。字段可按职责分为四组:
1. 核心转发字段(创建时必填)
创建 Proxy Host 时,OpenAPI 定义(backend/schema/paths/nginx/proxy-hosts/post.json)要求以下四个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
domain_names | string[] | 对外域名列表,一个 Proxy Host 可绑定多个域名,如["app.example.com"] |
forward_scheme | string | 转发协议,枚举http/https,即「后端自己用的是哪种协议」 |
forward_host | string | 转发目标主机,IP 或主机名,长度 1~255 |
forward_port | integer | 转发目标端口,范围 1~65535 |
schema 自带的最小示例(POST /api/nginx/proxy-hosts的 requestBody example):
{ "domain_names": ["test.example.com"], "forward_scheme": "http", "forward_host": "127.0.0.1", "forward_port": 8080 }2. SSL 相关字段
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
certificate_id | integer | 0 | 关联证书;值为"new"时会在创建流程中快速签发新证书(见下文) |
ssl_forced | boolean | false | 强制跳转 HTTPS |
hsts_enabled | boolean | false | 启用 HSTS(HTTP Strict Transport Security)响应头 |
hsts_subdomains | boolean | false | HSTS 是否覆盖子域名 |
trust_forwarded_proto | boolean | false | 是否信任X-Forwarded-Proto头(放在更靠前的反代之后时使用) |
3. 性能与安全字段
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
http2_support | boolean | false | 443 上启用 HTTP/2 |
block_exploits | boolean | false | 引入_exploits.conf拦截常见漏洞扫描路径 |
caching_enabled | boolean | false | 启用缓存(引入_assets.conf静态资源缓存规则) |
allow_websocket_upgrade | boolean | false | 为所有路径添加 WebSocket 升级头,模板中会输出Upgrade/Connection头并指定proxy_http_version 1.1 |
4. 访问控制与高级字段
| 字段 | 类型 | 说明 |
|---|---|---|
access_list_id | integer | 关联访问列表(Access List),用于 IP 黑白名单与 Basic Auth 鉴权 |
advanced_config | string | 插入到 server 块顶部的自定义 Nginx 配置,默认空字符串 |
locations | array | 自定义 location 列表,每条含path、forward_scheme、forward_host、forward_port,可选forward_path与advanced_config |
enabled | boolean | 是否启用该 Proxy Host |
meta | object | 元信息,如{ "nginx_online": true, "nginx_err": null } |
在数据库层,backend/models/proxy_host.js 维护了一张布尔字段白名单(ssl_forced、caching_enabled、block_exploits、allow_websocket_upgrade、http2_support、enabled、hsts_enabled、hsts_subdomains、trust_forwarded_proto等),负责在 JS 布尔值与数据库整型之间自动转换,并通过domain_names.sort()保证域名始终以排序后的形式存储。模型还声明了三条关系:owner(创建者用户)、access_list(访问列表及其客户端/条目)、certificate(证书),这也是列表接口默认展开(defaultExpand)的三个对象。
创建 Proxy Host:从表单到 Nginx 配置的完整链路
下面沿「前端 → API → 内部服务 → Nginx 配置」四层,完整走一遍 Proxy Host 的创建过程。
第一步:前端表单
前端入口在 frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx 的「添加」按钮,点击后弹出 frontend/src/modals/ProxyHostModal.tsx。该模态框按选项卡组织字段:Details(域名、转发协议/主机/端口、访问列表、缓存等)、SSL(证书选择、强制 HTTPS、HSTS)、Custom locations(自定义路径转发)、Advanced(高级配置与 WebSocket)。表单通过 Formik 管理,提交时统一走useSetProxyHost,新建与编辑复用同一套逻辑。
第二步:API 层
表单提交后调用POST /api/nginx/proxy-hosts(新建)或PUT /api/nginx/proxy-hosts/{id}(更新),路由实现在 backend/routes/nginx/proxy_hosts.js。所有请求先经 JWT 中间件鉴权,再经 schema 校验;该路由还提供GET /api/nginx/proxy-hosts/{id}/enable与/disable两个切换启停的接口。
第三步:内部服务逻辑
路由将数据交给 backend/internal/proxy-host.js 的create方法,其核心流程为:
- 权限检查:通过
access.can("proxy_hosts:create", data)校验当前用户角色权限(权限规则定义见 backend/lib/access/proxy_hosts-create.json,admin 角色或持有proxy_hosts.manage权限的用户可创建); - 域名占用检查:对
domain_names中每个域名调用internalHost.isHostnameTaken,一旦与已有 Proxy/Redirection/Dead Host 冲突即抛出ValidationError,报错文案为 "is already in use"——这就是同一个域名无法被两个主机重复绑定的底层保证; - 数据清洗与落库:设置
owner_user_id、清理 SSL/HSTS 相关脏数据、为缺失的advanced_config补空字符串,然后insertAndFetch写入proxy_host表; - 可选快速签发证书:如果前端传入了
certificate_id: "new",会先创建主机记录,再调用internalCertificate.createQuickCertificate为该域名快速申请 Let's Encrypt 证书,最后回填certificate_id; - 生成并重载 Nginx 配置:记录落库后调用内部 Nginx 服务重新生成对应站点的配置文件并 reload,使新配置立即生效。
第四步:配置生成
配置由 backend/templates/proxy_host.conf 渲染。渲染时按需引入监听、证书、HSTS、强制 SSL、WebSocket 升级头等片段,advanced_config与自定义locations(模板 backend/templates/_location.conf)也会被嵌入其中。最终生成的站点文件会写入 Nginx 的 conf.d 目录,访问日志落盘到/data/logs/proxy-host-{{ id }}_access.log、错误日志到/data/logs/proxy-host-{{ id }}_error.log(均按主机 ID 隔离),模板底部还会include /data/nginx/custom/server_proxy[.]conf,允许用户以文件方式注入每个 Proxy Host 专属的额外配置。
自定义 location:一个域名,多条转发规则
除了默认的location /整站转发,Proxy Host 还支持按路径细分转发目标——这就是locations字段的用武之地。例如同一个域名下,/app转发到 A 服务、其余路径转发到 B 服务,schema 中给出的示例结构如下:
{ "path": "/app", "forward_scheme": "http", "forward_host": "example.com", "forward_port": 80 }每个自定义 location 渲染为独立的 Nginx location 块(模板 backend/templates/_location.conf),其中会补全proxy_set_header Host $host、X-Forwarded-*系列头,并同样支持挂载访问控制、资源缓存、漏洞拦截、强制 SSL 与 WebSocket 升级片段;location 级advanced_config会先于其他指令输出,供用户精细调优。是否使用默认location /则由模板顶部的use_default_location开关控制,两者可以同时存在,实现「默认整站转发 + 个别路径单独分流」。
常见使用场景与注意事项
围绕上述机制,以下场景与坑点值得留意:
- WebSocket 应用(如在线协作、实时推送):必须开启
allow_websocket_upgrade,模板才会输出proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection $http_connection;与proxy_http_version 1.1;,否则升级请求会被当作普通 HTTP 处理导致连接失败。 - 域名冲突:同一个域名(含子域名)只能归属一个主机(Proxy/Redirection/Dead 全局唯一),创建时会提前校验,重复绑定直接报错。
- 强制 HTTPS 组合拳:
ssl_forced+hsts_enabled可让浏览器强制使用 HTTPS 访问,若 NPM 前方还有一层反向代理(如 CDN),应同时打开trust_forwarded_proto,否则 Nginx 无法正确识别原始请求协议,可能导致跳转判断失真。 - 纯内网服务暴露:如果后端服务没有认证能力,可以在 Proxy Host 上挂载 Access List(
access_list_id)实现 IP 白名单或 Basic Auth 两道防线,相关客户端规则定义见 frontend/src/api/backend/models.ts 的AccessListClient(支持allow/deny指令)。 - 证书选型:对外提供 HTTPS 时优先选择 Let's Encrypt 证书(由 backend/certbot 模块与 backend/templates/_certificates.conf 的自动续期链路支撑);已有外部签发的通配符证书则走「Custom」上传通道。
- 调试入口:主机创建后若转发异常,优先查看
/data/logs/proxy-host-{id}_error.log与该主机的meta.nginx_err字段(前端列表也会展示 Nginx 在线状态与错误信息)。
小结
Proxy Host 是 Nginx Proxy Manager 中最常用、也最灵活的一类对象:它以「域名 + 转发目标」的极简模型定义了 Web 服务的对外入口,在边缘提供可选的 SSL 终结能力,让任何后端服务都能快速获得安全、规范的对外访问方式。理解它的本质(入口端点)、核心能力(SSL 终结)与定位(最常用功能),再结合proxy_host数据模型、OpenAPI 定义与四层创建链路,你就掌握了 NPM 反向代理的基石,后续无论配置 Redirection Host、Dead Host 还是 Stream,都能举一反三。
延伸阅读(仓库内资源):
- backend/templates/proxy_host.conf:Proxy Host 的 Nginx 配置主模板
- backend/internal/proxy-host.js:创建/更新/启停/删除的内部业务逻辑
- backend/routes/nginx/proxy_hosts.js:REST API 路由
- backend/schema/components/proxy-host-object.json:字段的权威 OpenAPI 定义
- frontend/src/modals/ProxyHostModal.tsx:前端创建/编辑表单
- frontend/src/pages/Nginx/ProxyHosts/TableWrapper.tsx:Proxy Hosts 列表页
- 帮助文档:es/ProxyHosts.md(西班牙语)、en/ProxyHosts.md(英语)
【免费下载链接】nginx-proxy-managerDocker container for managing Nginx proxy hosts with a simple, powerful interface项目地址: https://gitcode.com/GitHub_Trending/ng/nginx-proxy-manager
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考