Nginx泛域名证书自动签发:acme.sh DNS验证与泛解析站点批量部署

    发布时间:2026-09-27 12:30 更新时间:2026-09-27 12:30 阅读量:0

    做多子域名的站长大多配过泛解析,也就是在 DNS 里加一条 *.example.com,之后 a.example.com、b.example.com 不用再单独解析。麻烦的是证书:泛解析能省掉解析记录,但 HTTPS 证书不会跟着自动泛化,按子域一个个申请,几十个站点签下来既费时又容易漏。所幸 ACME 协议支持签发通配符证书,配合 *.example.com 这一张证书就能覆盖所有同级子域,本文讲清用 acme.sh 通过 DNS 验证申请泛域名证书,以及续期后如何让 Nginx 批量站点生效。

    为什么泛域名证书必须走 DNS 验证

    ACME 的验证方式主要有两类:HTTP-01 和 DNS-01。HTTP-01 要求 CA 能访问 http://你的域名/.well-known/acme-challenge/xxx 这个文件,校验的域名必须能直接解析到这台服务器。通配符证书签发时,CA 校验的是 example.com 和 *.example.com 两个标识,而 *.example.com 本身不是一个可解析的主机名,HTTP-01 没法对它做校验,所以通配符证书只能用 DNS-01。

    DNS-01 的思路是在域名下创建一条 TXT 记录 _acme-challenge.example.com,内容由 ACME 客户端生成,CA 查询到这条记录后即认为你拥有该域名的控制权。手动加 TXT 记录每次续期都要重复一遍,不现实;主流做法是用 acme.sh 配合各 DNS 服务商的 API,自动增删 TXT 记录。国内常见的是阿里云、腾讯云 DNSPod、华为云,国外有 Cloudflare、Route53 等,acme.sh 对它们都有对应的 dnsapi 脚本,具体支持列表以 acme.sh 官方仓库的 dnsapi 目录为准。

    需要提醒的是:泛域名证书只覆盖一级子域。 *.example.com 能匹配 a.example.com,但匹配不到 a.b.example.com。如果你的站点是二级子域结构,要么再签一张 *.b.example.com,要么把具体域名写进 SAN 列表,这一点在规划站点结构时就要想清楚。

    用 acme.sh 申请与自动续期

    acme.sh 是纯 shell 实现的 ACME 客户端,安装不依赖 root,也不占用系统包管理器。安装命令从官方仓库获取,执行前建议先看一眼脚本内容:

    curl https://get.acme.sh | sh -s email=you@example.com
    source ~/.bashrc
    

    安装脚本会把 acme.sh 放到 ~/.acme.sh/ 并注册一条定时任务,默认每天检查一次续期。签发泛域名证书前,先把 DNS 服务商的 API 凭证写进 acme.sh 的环境变量文件,避免密钥出现在命令行历史里。以阿里云为例(变量名以 acme.sh 对应 dnsapi 脚本的说明为准):

    export Ali_Key="你的AccessKeyId"
    export Ali_Secret="你的AccessKeySecret"
    acme.sh --issue --dns dns_ali -d example.com -d '*.example.com' \
      --keylength ec-256
    

    命令里的 -d '*.example.com' 必须加引号,否则 shell 可能先做文件名展开。同时把根域 example.com 也带上,这样一张证书同时覆盖根域和所有一级子域。首次签发时 acme.sh 会调用 API 写入 TXT 记录,等 CA 校验通过后再删掉,整个过程通常一两分钟,具体时长取决于 DNS 服务商的解析生效速度。

    证书签发后不要直接引用 ~/.acme.sh/ 下的文件,而要用 --install-cert 复制到固定路径并绑定重载命令。这一步是自动续期的关键:续期成功后 acme.sh 会执行你指定的 reloadcmd,让 Nginx 重新加载证书。

    acme.sh --install-cert -d example.com --ecc \
      --key-file       /etc/nginx/ssl/example.com.key \
      --fullchain-file /etc/nginx/ssl/example.com.pem \
      --reloadcmd      "nginx -s reload"
    

    重载前建议先跑一次 nginx -t 验证配置,避免证书文件有问题时把线上 Nginx 直接 reload 出故障。可以写成 nginx -t && nginx -s reload。想手动确认续期是否正常,用 acme.sh --renew -d example.com --force --ecc 强制续一次,观察输出和证书文件时间戳即可,不需要等到 60 天周期。

    泛解析站点的 Nginx 批量部署思路

    证书只有一张,Nginx 侧最省事的做法是让所有子域共用同一个 server 块,通过 server_name 的泛匹配接住请求。Nginx 的 server_name 支持通配符写法,*.example.com 能匹配一级子域,匹配优先级低于精确域名和以通配符开头的写法,具体顺序以官方文档 server_name 一节为准。

    server {
        listen 443 ssl;
        http2 on;
        server_name *.example.com example.com;
    
        ssl_certificate     /etc/nginx/ssl/example.com.pem;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;
    
        root /www/wwwroot/$host;
        index index.php index.html;
    
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/tmp/php-cgi-74.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    }
    

    上面的 root /www/wwwroot/$host; 是批量部署的核心:Nginx 会把 $host 替换成实际访问的域名,只要目录按域名命名,新加一个子域只要建目录、配解析,不用再改 Nginx 配置。需要注意几点:

    一是 $host 直接拼进 root 存在路径穿越风险,如果站点允许用户自定义域名访问要谨慎使用,更稳妥的是用 map 指令把白名单域名映射到固定目录;二是 PHP-FPM 的 socket 路径要按服务器实际版本填写,宝塔环境下每个 PHP 版本 socket 名不同,以面板显示为准;三是 HTTP 到 HTTPS 的跳转要单独写一个 80 端口的 server 块统一 301,别在 443 块里混写。

    如果站点数量多、配置差异大,不建议全塞进一个 server 块,可以每个站点一个 conf 文件放在 conf.d/ 或宝塔的 vhost/ 目录下,证书路径统一指向 /etc/nginx/ssl/example.com.pem。这样续期时 reload 一次全部生效,新增站点也只需复制一份配置改 server_name 和 root。另外记得把默认站点的 server 块配好 default_server,避免未匹配的域名落到某个业务站点上导致串站。

    整体思路可以概括成三步:DNS 加泛解析、acme.sh 签一张泛域名证书、Nginx 用泛匹配 server_name 加 $host 目录接住所有子域。落地后建议先拿一个测试子域验证证书链和自动续期,确认 --install-cert 的 reloadcmd 能正常触发,再批量切换正式站点。证书到期前 30 天左右 acme.sh 会自动尝试续期,记得偶尔看一眼 ~/.acme.sh/acme.sh.log,确认没有因为 API 密钥失效或 DNS 解析延迟而静默失败。

    继续阅读

    📑 📅
    WordPress 数据库表前缀修改实战:从 wp-config 到 SQL 批量改名 2026-09-27
    宝塔面板日志被CDN节点IP填满:log_format与real_ip联动调整 2026-09-27
    Nginx resolver 域名解析缓存:反代上游换 IP 后仍走旧地址的排查 2026-09-27
    MySQL被OOM Kill排查:swap、buffer pool与监控取舍 2026-09-27
    HTTPS混合内容批量修复:控制台与curl定位http资源 2026-09-27
    宝塔面板部署 WordPress 后固定链接 404:伪静态规则加载顺序与 try_files 排查 2026-09-27
    网站301与302混用导致权重分散:跳转类型选择与生效验证 2026-09-27
    WordPress后台被暴力撞库告警:登录限速与日志加固 2026-09-26
    域名下PC站与m站SEO冲突:canonical、自适应与UA跳转取舍 2026-09-26
    服务器内存充足却频繁502:PHP-FPM进程回收与pm.max_requests取舍 2026-09-27