
nginx-proxy-manager 证书管理实战指南HTTP 验证、DNS 验证与自定义证书的签发与维护【免费下载链接】nginx-proxy-managerDocker container for managing Nginx proxy hosts with a simple, powerful interface项目地址: https://gitcode.com/GitHub_Trending/ng/nginx-proxy-manager导读本文基于 nginx-proxy-manager 内置的证书帮助文档frontend/src/locale/src/HelpDoc/en/Certificates.md葡萄牙语版本见 frontend/src/locale/src/HelpDoc/pt/Certificates.md系统讲解在该项目中签发与管理 SSL 证书的三种方式HTTP 验证HTTP-01证书、DNS 验证DNS-01证书与自定义证书上传。读完本文你将掌握每种方式的前置条件、适用场景尤其是 wildcard 通配符域名的支持差异并理解证书从签发、自动续期到撤销的底层实现机制从而在 nginx-proxy-manager 中为代理主机、重定向主机、404 主机与 TCP/UDP 流式转发正确配置 TLS。证书是整个反向代理体系中安全性的基石nginx-proxy-manager 的证书对象被代理主机Proxy Host、重定向主机Redirection Host、404 主机Dead Host和流式转发Stream共同引用见 backend/models/certificate.js 中的关系映射。因此理解证书的三种来源方式是使用该项目的必修课。一、证书的三种来源总览在 nginx-proxy-manager 管理界面中打开Certificates证书页面下图点击 Add SSL Certificate 即可看到三种入口Lets EncryptHTTP 验证、Lets EncryptDNS 验证和 Custom自定义证书。nginx-proxy-manager 证书管理页面三者的核心区别可以总结为下表特性HTTP 验证证书DNS 验证证书自定义证书验证通道HTTP-0180 端口DNS-01TXT 记录无验证直接上传是否需要先建 Proxy Host需要指向本机且可经 HTTP 访问不需要不需要是否支持通配符域名wildcard不支持支持取决于证书本身证书提供方Lets EncryptLets Encrypt经 DNS Provider 插件任意 CA自动续期支持支持不支持需手动更新从源码看三种来源最终都写入同一张certificate表backend/models/certificate.js通过provider字段区分Lets Encrypt 签发的证书provider为letsencrypt自定义证书为other见 backend/internal/certificate.js。二、HTTP 验证证书HTTP-01 Challenge2.1 工作原理HTTP 验证证书意味着 Lets Encrypt 服务器会通过 HTTP而非 HTTPS访问你的域名在/.well-known/acme-challenge/路径下验证一个临时令牌文件验证成功后签发证书。nginx-proxy-manager 为这一流程准备了专用的临时站点配置模板 backend/templates/letsencrypt-request.conf该模板监听 80 端口并仅开放 ACME 挑战路径server { listen 80; listen [::]:80; server_name {{ domain_names | join: }}; access_log /data/logs/letsencrypt-requests_access.log standard; error_log /data/logs/letsencrypt-requests_error.log warn; include conf.d/include/letsencrypt-acme-challenge.conf; location / { return 404; } }2.2 前置条件根据原文档要求使用 HTTP 验证方式必须满足为你的域名创建一个Proxy Host该 Proxy Host 必须可以通过 HTTP 访问并且流量指向这台 nginx-proxy-manager 安装域名的 DNS 记录必须已解析到本机且 80 端口对外可达。签发完成后你可以修改这个 Proxy Host让它同时使用该证书提供 HTTPS 连接。但必须保留 HTTP 访问配置——因为证书的续期仍然要通过 HTTP 挑战完成。这是原文档反复强调的关键约束如果把 HTTP 关掉续期将会失败。2.3 不支持的场景此方式不支持 wildcard通配符域名因为 HTTP-01 挑战要求对每个具体域名逐一发起 HTTP 请求无法为*.example.com这种通配符一次性完成验证。需要通配符证书请改用下一节的 DNS 验证方式。2.4 签发流程的源码实现在 backend/internal/certificate.js 的create()方法中Lets Encrypt 证书的签发遵循一条明确的六步流程找出使用了这些域名的现有主机internalHost.getHostsWithDomains临时禁用这些主机的 nginx 配置disableInUseHosts避免端口冲突生成 Lets Encrypt 请求配置generateLetsEncryptRequestConfig即上文模板调用 certbot 签发证书requestLetsEncryptSsl移除临时配置deleteLetsEncryptRequestConfig恢复之前禁用的主机配置并重载 nginx。对应的 certbot 命令backend/internal/certificate.js大致如下certbot certonly -n \ --config /etc/letsencrypt.ini \ --work-dir /tmp/letsencrypt-lib \ --logs-dir /data/logs \ --cert-name npm-certificate_id \ --agree-tos -m 你的邮箱 \ --authenticator webroot \ --preferred-challenges http \ --domains example.com,www.example.com其中--cert-name npm-certificate_id将证书与数据库中的证书 ID 一一对应证书文件最终存放在/etc/letsencrypt/live/npm-certificate_id/见 backend/internal/certificate.js。另外注意发起 Lets Encrypt 请求前用户账号必须配置了有效的邮箱地址否则会抛出 A valid email address must be set on your user account to use Lets Encrypt 错误backend/internal/certificate.js。2.5 签发前的可访问性测试在正式签发前界面还会提供 HTTP 挑战测试功能对应 APIPOST /api/nginx/certificates/test-http见 backend/routes/nginx/certificates.js。其实现backend/internal/certificate.js会在本机 ACME 挑战目录写入一个测试文件然后通过第三方 HTTP 探测工具访问http://domain/.well-known/acme-challenge/test-challenge根据返回结果给出ok、404、no-host、wrong-data等诊断结论帮助你定位 DNS 解析、防火墙或反代配置问题。三、DNS 验证证书DNS-01 Challenge3.1 工作原理DNS 验证证书要求使用一个DNS ProviderDNS 供应商插件。该插件会通过你的 DNS 服务商 API 在域名下自动创建临时的 TXT 记录_acme-challengeLets Encrypt 查询该记录以确认你对域名的所有权验证成功后签发证书。相比 HTTP 方式DNS 验证有两大优势原文档明确说明不需要预先创建 Proxy Host不需要 Proxy Host 配置 HTTP 访问——因为验证完全发生在 DNS 层面与 80/443 端口是否可达无关。3.2 通配符域名支持此方式支持 wildcard 域名。这是签发*.example.com通配符证书的唯一内置途径尤其适合内部服务多、不想为每个子域名单独签证书的场景。3.3 DNS Provider 插件机制nginx-proxy-manager 内置了数量庞大的 DNS 插件清单定义在 backend/certbot/dns-plugins.json覆盖 Cloudflare、DigitalOcean、GoDaddy、DNSPod、Aliyun阿里云、Tencent Cloud腾讯云、Route 53Amazon、OVH、Hetzner、Vultr、Linode、Azure、Google 等主流厂商。每个插件条目包含四要素{ cloudflare: { credentials: # Cloudflare API token\ndns_cloudflare_api_token0123456789abcdef0123456789abcdef01234567, dependencies: acme{{certbot-version}}, full_plugin_name: dns-cloudflare, name: Cloudflare, package_name: certbot-dns-cloudflare, version: {{certbot-version}} } }其中credentials是界面提示用户填写的凭证模板full_plugin_name是 certbot 的认证器名称。后端通过GET /api/nginx/certificates/dns-providers把这份清单暴露给前端backend/routes/nginx/certificates.js前端在 frontend/src/components/Form/DNSProviderFields.tsx 中渲染为下拉选项。当你选择某个 DNS 提供商后后端会按需安装对应的 certbot 插件installPlugin()使用 pip 在 certbot 虚拟环境中安装package_name version指定的包见 backend/lib/certbot.js安装命令形如. /opt/certbot/bin/activate pip install --no-cache-dir acmeCERTBOT_VERSION certbot-dns-cloudflareCERTBOT_VERSION deactivate凭证会以0600权限写入/etc/letsencrypt/credentials/credentials-certificate_id避免其他用户读取backend/internal/certificate.js。其中 Route 53 比较特殊它不是通过命令行参数传凭证而是通过环境变量AWS_CONFIG_FILE指向凭证文件backend/internal/certificate.js。3.4 签发流程与可调参数DNS 验证的签发流程backend/internal/certificate.js同样会临时禁用占用这些域名的现有主机但不需要生成临时的 nginx 配置源码注释 With DNS challenge no config is needed, so skip 3 and 5。核心 certbot 命令为certbot certonly -n \ --config /etc/letsencrypt.ini \ --work-dir /tmp/letsencrypt-lib \ --logs-dir /data/logs \ --cert-name npm-certificate_id \ --agree-tos -m 你的邮箱 \ --preferred-challenges dns \ --domains *.example.com,example.com \ --authenticator dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/credentials/credentials-certificate_id除凭证外你还可以配置以下参数对应 backend/schema/components/certificate-object.json 中meta的字段定义meta 字段含义默认值dns_challenge是否启用 DNS 验证falsedns_providerDNS 提供商标识对应 dns-plugins.json 的键无dns_provider_credentials供应商 API 凭证内容无propagation_seconds等待 TXT 记录全球生效的秒数无不传则用插件默认值key_type私钥类型rsa或ecdsarsa其中propagation_seconds会转换为 certbot 的--plugin-propagation-seconds参数backend/internal/certificate.js用于在 DNS 记录尚未全球生效时避免验证失败key_type会转换为--key-type参数backend/internal/certificate.js。前端 frontend/src/modals/DNSCertificateModal.tsx 中 DNS 证书默认选择ecdsa密钥类型。四、自定义证书Custom Certificate4.1 使用场景自定义证书用于上传你自己的 SSL 证书通常由你的证书颁发机构CA签发例如企业内部的私有 CA、付费商业证书或由其他工具如 acme.sh签发的证书。该方式与 Lets Encrypt 无关适合需要长期固定证书、或证书已由组织统一管理的场景。4.2 可上传的文件后端在 backend/internal/certificate.js 中定义了允许上传的三种文件allowedSslFiles文件字段说明certificate证书本体PEM 格式certificate_key私钥intermediate_certificate中间证书/证书链上传时会先经过校验私钥通过openssl pkey -check验证证书通过openssl x509解析出 CNCommon Name、签发者issuer与有效期notBefore/notAfter过期证书会被拒绝backend/internal/certificate.js。上传界面同时提供POST /api/nginx/certificates/validate预校验接口backend/routes/nginx/certificates.js在保存前即可发现证书与私钥不匹配等问题。4.3 证书落盘与使用自定义证书被写入/data/custom_ssl/npm-certificate_id/目录如果提供了中间证书会与证书本体拼接成fullchain.pem私钥单独写入privkey.pembackend/internal/certificate.js供 nginx 引用。删除自定义证书时不会触发吊销操作只有 Lets Encrypt 证书在删除时会调用revokeLetsEncryptSsl向 CA 吊销backend/internal/certificate.js。五、证书生命周期签发后的一切5.1 自动续期Lets Encrypt 证书的自动续期由后端内置的定时器驱动。在 backend/internal/certificate.js 中定时器间隔为1 小时intervalTimeout: 1000 * 60 * 60续期阈值为到期前 30 天renewBeforeExpirationBy: [30, days]每次触发时查询数据库中provider letsencrypt且expires_on早于阈值日期的证书逐个串行执行续期——源码注释明确指出必须串行否则会报 Another instance of Certbot is already running 错误backend/internal/certificate.js。续期动作会写入审计日志action: renewed见 backend/internal/certificate.js并自动更新数据库中的expires_on。你也可以在界面上手动触发续期POST /api/nginx/certificates/:id/renewbackend/routes/nginx/certificates.js。5.2 下载与导出Lets Encrypt 证书支持打包下载后端会把/etc/letsencrypt/live/npm-id/下所有.pem文件打包为 zip 返回backend/internal/certificate.js便于你在其他服务器或负载均衡器上复用同一份证书。自定义证书provider other不支持此下载接口且自定义证书仅允许在上传后以文件替换方式更新POST /api/nginx/certificates/:id/uploadbackend/routes/nginx/certificates.js。5.3 权限控制证书操作受权限系统约束。创建证书要求用户具备certificates:create权限backend/internal/certificate.js对应的权限定义为可管理证书管理员角色默认拥有全部权限普通用户可通过授权获得见 backend/lib/access/certificates-create.json。在证书列表与详情查询时非管理员用户只能看到自己创建的证书permission_visibility ! all时按owner_user_id过滤见 backend/internal/certificate.js这也意味着证书与创建它的用户绑定多人协作时需注意归属问题。六、选择建议与常见坑位结合原文档与源码实现给出如下实操建议普通子域名且 80 端口可达优先选 HTTP 验证证书。注意签发后保留 Proxy Host 的 HTTP 访问否则 30 天后自动续期必然失败。需要通配符证书或 80 端口不可达 / 使用 CDN 代理选 DNS 验证证书。需要提前到 DNS 服务商后台创建 API Token并按 backend/certbot/dns-plugins.json 中该供应商的credentials模板填写凭证。若 TXT 记录生效较慢可调大propagation_seconds。企业内部 CA 或合规要求选自定义证书上传证书、私钥与中间证书三件套注意私钥不能加密带 passphrase 的私钥校验会超时失败。首次签发失败排查顺序先使用证书页面的 HTTP 挑战测试确认域名可达再确认账号邮箱已填写最后查看/data/logs/letsencrypt-requests_*.log与 certbot 日志/data/logs定位具体错误。证书被多个主机引用时签发过程中 nginx 会短暂重载、对应主机配置会被临时禁用再恢复backend/internal/certificate.js因此建议在业务低峰期执行首次签发。通过以上三种证书方式的合理搭配你可以在 nginx-proxy-manager 中构建一套完整的 TLS 证书管理方案HTTP 验证覆盖常规站点、DNS 验证打通通配符与内网穿透场景、自定义证书满足企业合规要求而自动续期与审计日志则保证了证书的全生命周期可维护、可追溯。【免费下载链接】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),仅供参考