Nginx:向外代理暴露Web服务

如何配置 Pigsty 中的 Nginx,对外代理并暴露内部 Web 服务,提供本地软件仓库服务。

Pigsty 的 Infra 模块默认会在节点上安装 Nginx,这是一个高性能的 Web 服务器。 Pigsty 使用 Nginx 作为所有本地 WebUI 服务的统一入口,并将其用作本地软件仓库,向内网其他节点提供服务。

当然,用户可以根据需求,调整配置,将 Nginx 用作标准的 Web 服务器,对外提供服务。 无论是作为反向代理,还是直接作为网站服务器,都可以通过适当的配置实现。 Pigsty 本身的文档站与仓库也是通过 Pigsty 自建的 Nginx 对外提供的。


配置概览

Nginx 服务器配置由 infra_portal 参数指定。

用户在这里声明所有需要通过 Nginx 代理的域名,以及对应的上游服务器端点(endpoint)或本地目录路径(path)。

例如,默认情况下,Pigsty 会这样配置 Nginx,下面的配置会使用 Nginx 对外暴露 Home,Grafana,Prometheus,Alertmanager 四项服务:

infra_portal:  # domain names and upstream servers
  home         : { domain: h.pigsty }
  grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
  prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
  alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
  blackbox     : { endpoint: "${admin_ip}:9115" }
  loki         : { endpoint: "${admin_ip}:3100" }

当安装 Pigsty 时,Pigsty 会自动根据以上配置生成 Nginx 的配置文件。

/etc/nginx/conf.d/haproxy/           # <--- 存放着 HAPROXY 管理界面的位置定义
/etc/nginx/conf.d/home.conf          # <--- Pigsty 默认服务器定义(本地软件源,HAPROXY转发)
/etc/nginx/conf.d/grafana.conf       # <--- 代理访问内网 Grafana 服务器
/etc/nginx/conf.d/prometheus.conf    # <--- 代理访问内网 Prometheus 服务器
/etc/nginx/conf.d/alertmanager.conf  # <--- 代理访问内网 Alertmanager 服务器

Nginx 默认服务于 80/443 端口,home 服务器是本地软件源,同时也是默认的 Nginx 服务器。 如果你想通过 Nginx 访问其他服务,只需要在 infra_portal 中添加相应的配置即可,任何带有 domain 参数的配置都会被 Nginx 自动代理。


配置剧本

当安装 Pigsty 时,这些配置会在默认的 install.yml 剧本,或者 infra.yml 剧本中自动生效。 但是用户也可以在 Pigsty 部署后使用 infra.yml 剧本中的 nginx 子任务重新初始化 Nginx 配置。

./infra.yml -t nginx           # 重新配置 Nginx
./infra.yml -t nginx_config    # 重新生成 Nginx 配置
./infra.yml -t nginx_launch    # 重新启动 Nginx 服务

这意味着如果您想要调整 Nginx 服务器的配置,只需要修改 pigsty.yml 配置文件,并执行上面的 nginx 任务即可生效。

当然,你也可以选择先使用 nginx_config 子任务重新生成 Nginx 配置文件,人工检查后使用 nginx -s reload 重新在线加载配置。


配置详情

配置变量 infra_portal 通常定义在全局变量 all.vars 中,默认值如下所示:

all:
  vars:
    infra_portal:  # domain names and upstream servers
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }

默认配置意味着,用户默认可以通过:

  • h.pigsty 访问 home 服务器,这是默认服务器,对应 Pigsty 的文件系统首页与本地软件源,通常指向本机上的 /www 目录。
  • g.pigsty 访问 grafana 服务器,这是默认的 Grafana 服务,通常指向管理节点(admin_ip)上的 3000 端口。
  • p.pigsty 访问 prometheus 服务器,这是默认的 Prometheus 服务,通常指向管理节点(admin_ip)上的 9090 端口。
  • a.pigsty 访问 alertmanager 服务器,这是默认的 Alertmanager 服务,通常指向管理节点(admin_ip)上的 9093 端口。

注意这里的 blackboxloki 没有配置 domain 参数,因此不会被添加到 Nginx 的配置中,因为它们没有配置 domain 参数。 但是这并不意味着用户可以直接把这两项定义移除掉,因为内网中的其他服务可能会引用这里的配置(例如日志 Agent 会引用 Loki endpoint 地址发送日志)

用户可以通过丰富的配置参数,为不同的服务配置不同的配置,如下所示:


服务器参数

每一条服务器记录都有一个独一无二的 name 作为 key,一个配置字典作为 value。在配置字典中,目前有以下几个可用配置项:

  • domain可选,指定代理的域名,如果不填写,则 Nginx 不会对外暴露此服务。

    对于那些需要知道 endpoint 地址,但不想对外暴露的服务(例如 Loki, Blackbox Exporter),可以不填写此参数

  • endpoint可选,指定上游服务的地址,可以是 IP:PORT 或者 DOMAIN:PORT

    • 当此服务器为上游服务时,可以指定此参数,Pigsty 会生成一个标准的反向代理配置,并将请求转发给上游的 endpoint 地址。
    • 此参数与 path 参数是互斥的,不能同时存在:如果一个服务器是反向代理服务器,那么它不能同时是本地网页服务器。
    • 在此参数值中,可以使用 ${admin_ip} 占位符,Pigsty会填入 admin_ip 的值。
    • 如果指定了此参数,则 Pigsty 默认会使用 endpoint.conf 配置模板,这是反向代理的标准模板
    • 如果同时指定了 conf 参数,则 conf 参数指定的模板有更高的优先级。
    • 如果上游强制要求 HTTPS 访问,你可以额外设置 scheme: https 参数。
  • path可选,指定本地 Web 服务器的根目录,可以是绝对路径或者相对路径。

    • 当此服务器为本地 Web 服务器时,可以指定此参数,Pigsty 会生成一个标准的本地 Web 服务器配置,并将请求转发给本地的 path 目录。
    • 此参数与 endpoint 参数是互斥的,不能同时存在,如果一个服务器是本地网页服务器,那么它不能同时是上游代理服务器。
    • 如果指定了此参数,则 Pigsty 默认会使用 path.conf 配置模板,这是本地 Web 服务器的标准模板
    • 如果同时指定了 conf 参数,则 conf 参数指定的模板有更高的优先级。
    • 如果你希望 Nginx 自动生成文件列表索引,可以设置 index: true 参数,默认是不打开的。
  • conf: 可选,如果指定,则将会使用 templates/nginx/ 中定义的配置模板。

    • 当你想要任意定制 Nginx 配置时可以指定此参数,指定一个存在于 templates/nginx 目录中的模板文件名。
    • 如果没有指定此参数,Pigsty 将根据服务器的类型(Home, Proxy, Path)自动应用相应的 默认模板
      • home.conf: 默认服务器的模板(用于 home)。
      • endpoint.conf: 上游服务代理的模板(例如:用于Grafana,Prometheus 等)
      • path.conf:本地 Web 服务器的模板(默认没有使用,但 home 是特殊的本地服务器)
  • certbot: 可选,指定此服务器的 certbot 证书名称,Pigsty 会自动使用 certbot 生成的证书。

    • 如果您的证书是使用 certbot 生成的,你可以指定此参数为 certbot 生成的证书名称,Pigsty 会自动使用此证书。
    • 您应当填入 certbot 生成证书的域名部分。例如 certbot: pigsty.cc 会自动使用
      • 证书:/etc/letsencrypt/live/pigsty.cc/fullchain.pem,但可以被显式指定的 cert 参数(完整路径)覆盖。
      • 私钥:/etc/letsencrypt/live/pigsty.cc/privkey.pem,但可以被显式指定的 key 参数(完整路径)覆盖。
    • certbot 证书名称通常与 domain 参数相同,例如 g.pigsty 的证书名称为 g.pigsty.cc,但也有特例:当你同时申请多个证书时,certbot 会生成一个捆绑证书,名称为申请列表中的第一个域名。
  • cert: 可选,指定此服务器的 SSL 证书文件名,需要给出完整路径。

  • key: 可选,指定此服务器的 SSL 私钥文件名,需要给出完整路径。

  • domains: 可选,除了默认的 domain 域名,您还可以为此服务器指定多个额外的域名

  • scheme: 可选,指定此服务器的协议(http/https),留空则默认使用 http,通常用于强制要求 HTTPS 访问的上游 Web 服务。

  • index: 可选,如果设置为 true, Nginx 会为目录自动生成文件列表索引页面,方便浏览文件,对于软件仓库类通常可以打开,对于网站通常应当关闭。

  • log: 可选,如果指定,则日志将打印到 <value>.log ,而非默认的 access.log 中。

    • 作为特例,上游代理服务器的日志总是会打印到 <name>.log 中。

复杂的配置样例

Pigsty 自带的配置模板 conf/demo.yml 有一个更详细的案例,给出了 Pigsty 文档站的配置样例。

是的,Pigsty 的文档站也是在一台普通云服务器上使用 Pigsty 本身建设的,其配置如下所示:

infra_portal:
  home         : { domain: home.pigsty.cc }
  grafana      : { domain: demo.pigsty.cc ,endpoint: "${admin_ip}:3000" ,websocket: true ,cert: /etc/cert/demo.pigsty.cc.crt ,key: /etc/cert/demo.pigsty.cc.key }
  prometheus   : { domain: p.pigsty.cc    ,endpoint: "${admin_ip}:9090" }
  alertmanager : { domain: a.pigsty.cc    ,endpoint: "${admin_ip}:9093" }
  cc           : { domain: pigsty.cc      ,path:     "/www/pigsty.cc"   ,cert: /etc/cert/pigsty.cc.crt ,key: /etc/cert/pigsty.cc.key }

  blackbox     : { endpoint: "${admin_ip}:9115" }
  loki         : { endpoint: "${admin_ip}:3100" }
  minio        : { domain: m.pigsty.cc    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
  postgrest    : { domain: api.pigsty.cc  ,endpoint: "127.0.0.1:8884"   }
  pgadmin      : { domain: adm.pigsty.cc  ,endpoint: "127.0.0.1:8885"   }
  pgweb        : { domain: cli.pigsty.cc  ,endpoint: "127.0.0.1:8886"   }
  bytebase     : { domain: ddl.pigsty.cc  ,endpoint: "127.0.0.1:8887"   }
  jupyter      : { domain: lab.pigsty.cc  ,endpoint: "127.0.0.1:8888", websocket: true }
  gitea        : { domain: git.pigsty.cc  ,endpoint: "127.0.0.1:8889" }
  wiki         : { domain: wiki.pigsty.cc ,endpoint: "127.0.0.1:9002" }
  noco         : { domain: noco.pigsty.cc ,endpoint: "127.0.0.1:9003" }
  supa         : { domain: supa.pigsty.cc ,endpoint: "10.10.10.10:8000" ,websocket: true }
  dify         : { domain: dify.pigsty.cc ,endpoint: "10.10.10.10:8001" ,websocket: true }
  odoo         : { domain: odoo.pigsty.cc ,endpoint: "127.0.0.1:8069"   ,websocket: true }
  mm           : { domain: mm.pigsty.cc   ,endpoint: "10.10.10.10:8065" ,websocket: true }

这个文档站的 Nginx 配置要比默认的配置复杂一些:

  • home 服务器使用了一个真实的公网域名 home.pigsty.cc
  • grafana 服务器使用了一个真实的公网域名 demo.pigsty.cc,并配置了 websocket: true 以支持 WebSocket 连接。
  • cc 服务器是 Pigsty 的文档站,它使用了真实公网域名 pigsty.cc,并指向了本地的 /www/pigsty.cc 目录。
  • 下面还定义了一系列 Docker App 服务器,将这些应用的 Web 界面通过域名对外暴露。
  • ccgrafana 直接通过 certkey 参数指定了 HTTPS 证书。

配置域名

您可以通过 IP:Port 直接访问特定服务,例如 IP:3000 访问 Grafana,IP:9090 访问 Prometheus。 但这样的行为通常并不可取,常规安全最佳实践要求您通过域名访问服务,而不是通过 IP:Port 直接访问。 通过域名访问意味着你只需要对外暴露一个 Nginx 服务,减小攻击面,并便于统一添加访问控制!

使用域名访问 Pigsty WebUI 时,您需要配置 DNS 解析,有以下几种方式:

  • 使用真域名,通过云厂商/域名厂商的 DNS 解析服务,将公网域名指向你的服务器公网IP
  • 使用内网域名,在内网 DNS 服务器上添加内网域名,并指向你服务器的内网IP地址
  • 使用本机域名,在你浏览器所在主机的(/etc/hosts)添加一条静态解析记录

通过本机访问

如果你是唯一的用户,那么可以直接修改本地 /etc/hosts 文件(Linux/MacOS), 在 Windows 系统上,您需要修改 C:\Windows\System32\drivers\etc\hosts 文件。 无论是什么系统,修改此文件通常需要管理员权限。

你可以添加以下静态解析记录,将 Pigsty 的默认域名指向你的服务器IP地址:

<ip_address>  h.pigsty a.pigsty p.pigsty g.pigsty

如果你会用到其他服务,也可以添加其他服务对应的域名解析记录:

10.10.10.10 h.pigsty a.pigsty p.pigsty g.pigsty
10.10.10.10 api.pigsty ddl.pigsty adm.pigsty cli.pigsty lab.pigsty
10.10.10.10 supa.pigsty noco.pigsty odoo.pigsty dify.pigsty

通过办公网访问

如果您的服务需要在办公网共享访问,例如让所有同事都可以通过域名访问,那么除了让同事都在自己的电脑上添加上面的静态解析记录之外,更正规的做法是使用内网DNS服务器。

您可以要求网络管理员在公司内部 DNS 服务器中添加相应的解析记录,将其指向 Nginx 服务器所在的 IP 地址。

当然还有另一种选项,Pigsty 默认安装也会在 53 端口提供一个 DNS 服务器,您可以通过配置 /etc/resolv.conf 文件或图形化界面配置 DNS 服务器,来使用内网域名访问部署在办公网中的服务。

通过互联网访问

如果您的服务需要直接暴露在互联网网上,通常您需要通过 DNS 服务商(Cloudflare,Aliyun DNS 等)解析互联网域名。 当然,你依然可以使用本地 DNS 服务器或本地静态解析记录来访问服务,但这样你的服务(除了默认的home服务器)就没法被互联网上的其他用户访问了。

您可以将所有需要暴露的域名都解析到 Nginx 服务器所在的 IP 地址。或者更简单的将 @* A 记录都解析到 Nginx 服务器所在的 IP 地址。 当你申请好新域名并将其指向你的服务器公网IP后,你还需要修改 Pigsty 的 infra_portal ,将域名填入各个服务器条目的 domain 字段中。

通过公网访问的域名,最佳实践是申请 HTTPS 证书,并始终使用 HTTPS 访问。我们将在下一节介绍这个主题。


配置HTTPS

HTTPS 是当代 Web 服务的主流配置,然而并非所有用户都熟悉 HTTPS 的配置方法。因此 Pigsty 默认为用户启用 HTTPS 支持。

如果你的 Nginx 只是对内网,办公网提供服务,那么 HTTPS 是一个 可选项; 如果你的 Nginx 需要对 互联网 提供服务,那么我们 强烈建议 您使用真实的域名与真正的 HTTPS 证书。 使用 HTTPS 不仅能够加密您的网络流量避免非法窥探篡改,而且能够避免访问 “未备案” 域名时恼人的体验。

本地域名与自签名证书

因为 Pigsty 默认使用的域名都是本地域名(x.pigsty),无法申请真正的域名 HTTPS 证书,所以 Pigsty 默认使用自签名证书。

Pigsty 会使用自签名的 CA 为所有的 infra_portal 中的域名签发证书。当然此证书并非权威证书,在浏览器中会提示证书不可信。你可以选择:

  • “我知道不安全,继续访问”
  • 使用 Chrome 浏览器时,你也可以使用敲击键入 thisisunsafe 来绕过证书验证
  • 将 Pigsty 自动生成的 pigsty-ca CA 证书加入浏览器所在电脑的 信任的根 CA 列表
  • 回退到 HTTP 或者 IP:Port 访问,不使用 HTTPS (不推荐)
  • 不使用本地域名与自签名证书,而是使用真正的域名与真正的 HTTPS 证书。

默认生成的自签名 CA 公钥和私钥位于 pigsty 本地目录的:files/pki/ca/ca.crtfiles/pki/ca/ca.key

真实域名与真证书

HTTPS 证书通常是一项收费服务,但是您可以使用诸如 certbot 这类工具申请免费的 Let’s Encrypt 证书。

使用 Certbot 申请真正 HTTPS 证书的教程将在下一篇 Certbot教程:申请免费HTTPS证书 中详细介绍。





最后修改 2025-03-01: refactor docs (caae0ad)