终极指南:Let's Encrypt 通配符证书自动化部署(腾讯云 + Nginx 多子域版)

11 阅读4分钟

终极指南:Let's Encrypt 通配符证书自动化部署(腾讯云 + Nginx 多子域版)

本指南专为国内云服务器环境优化,彻底解决了访问 GitHub 超时、默认 CA 机构限流报错(retryafter=86400)、以及公共 DNS 检查超时等常见痛点,并针对 Nginx 的多子域名独立配置文件及 ECC 证书兼容性提供了标准模板。

准备工作

获取你的腾讯云 API 密钥(SecretIdSecretKey),用于后续授权程序自动修改 DNS 解析记录进行验证。


第一步:安装 acme.sh(国内镜像加速版)

💡 避坑说明: 国内服务器使用官方的 curl https://get.acme.sh | sh 命令极易在下载阶段卡死在 0%。因此,我们强制使用官方提供的国内 Gitee(码云)镜像进行源码安装。

Bash

# 1. 确保服务器已安装 Git
yum install git -y

# 2. 从官方 Gitee 镜像拉取最新代码
git clone https://gitee.com/neilpang/acme.sh.git

# 3. 进入目录并执行安装(请替换为你自己的邮箱,用于接收证书过期或异常提醒)
cd acme.sh
./acme.sh --install -m your_email@163.com

# 4. 刷新环境变量,使 acme.sh 命令全局生效
source ~/.bashrc

第二步:环境预配置(极其关键)

1. 切换默认证书颁发机构 (CA) 为 Let's Encrypt

💡 避坑说明: acme.sh 默认使用 ZeroSSL,但其免费接口在处理通配符证书时,经常会触发 The retryafter=86400 value is too large 的限流报错导致卡死。Let's Encrypt 对通配符的支持更加稳定。

Bash

acme.sh --set-default-ca --server letsencrypt

2. 导入腾讯云 API 凭证

Bash

export Tencent_SecretId="你的SecretId"
export Tencent_SecretKey="你的SecretKey"

第三步:申请通配符证书

💡 避坑说明: 国内服务器在请求海外公共 DNS(如 8.8.8.8)时容易发生 error code: 35/28 的网络超时死循环。通过添加 --dnssleep 120 参数,可以强制脚本在添加 DNS TXT 记录后睡眠 120 秒,跳过本地检测,直接让 Let's Encrypt 官方去验证。

请将 yourdomain.com 替换为你的真实域名(需同时包含顶级域名和通配符):

Bash

acme.sh --issue --dns dns_tencent -d yourdomain.com -d *.yourdomain.com --dnssleep 120

执行后耐心等待倒计时结束,看到绿色的 Cert success. 及证书内容输出,即代表申请成功。此证书为新一代高性能 ECC 证书。


第四步:提取证书到 Nginx 目录

⚠️ 严正警告: 绝对不能在 Nginx 中直接配置引用 ~/.acme.sh/ 内部目录下的证书文件。必须使用专门的 --install-cert 命令将其提取到系统标准目录,这样才能保证日后的自动续期功能正常触发 Nginx 重载。

Bash

# 1. 创建统一的证书存放目录
mkdir -p /etc/nginx/ssl

# 2. 执行安装与映射(后续自动续期成功后,会自动触发 --reloadcmd 里的命令)
acme.sh --install-cert -d yourdomain.com \
--key-file       /etc/nginx/ssl/yourdomain.com.key \
--fullchain-file /etc/nginx/ssl/yourdomain.com.pem \
--reloadcmd      "systemctl reload nginx"

第五步:Nginx 多子域名配置 (ECC 证书优化版)

针对一台服务器管理多个子域名(如 zq.yourdomain.com, api.yourdomain.com 等),最佳实践是将每个子域名的配置写在独立的 .conf 文件中(如 /etc/nginx/conf.d/yourdomain-zq.conf)。

💡 避坑说明:

  1. 较新的 Nginx 版本已废弃 ssl on; 语法,需直接在 listen 端口后追加 ssl
  2. 由于签发的是新一代 ECC 证书,如果继续使用纯 RSA 的加密套件会导致握手失败。必须在 ssl_ciphers 中加入 ECDHE-ECDSA 支持。

子域名标准配置模板(可直接在各文件中复制替换 SSL 部分):

Nginx

server {
    # 强制将 HTTP 请求跳转到 HTTPS (可选,强烈推荐)
    listen 80;
    server_name zq.yourdomain.com; # 替换为当前配置文件的实际子域名
    return 301 https://$host$request_uri;
}

server {
    # 正确的新版语法:端口后紧跟 ssl,并删除旧的 ssl on; 语句
    listen 443 ssl; 
    server_name zq.yourdomain.com; # 替换为当前配置文件的实际子域名

    # --- 统一的通配符证书路径 ---
    ssl_certificate       /etc/nginx/ssl/yourdomain.com.pem;
    ssl_certificate_key   /etc/nginx/ssl/yourdomain.com.key;
    
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; 
    
    # --- ECC 证书兼容套件 ---
    # 必须包含 ECDHE-ECDSA 以支持 ECC 证书,随后保留对老旧客户端的兼容
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    ssl_prefer_server_ciphers on;

    # --- 具体的业务逻辑配置 ---
    location / {
        root /data/your_project_path; # 静态目录
        index index.html index.htm;
        
        # 如果是 Vue/React 等单页应用(SPA),加上此行防止刷新报 404
        try_files $uri $uri/ /index.html; 
        
        # 或者如果是反向代理:
        # proxy_pass http://127.0.0.1:8080;
    }
}

配置修改完毕后,执行检查并重载:

Bash

nginx -t
systemctl reload nginx

第六步:验证自动续期机制 (Auto Renewal)

Let's Encrypt 证书有效期为 90 天。acme.sh 已在安装时自动写入了系统的 Cron 定时任务,它会在证书到期前 30 天自动走一遍上述流程,并无缝重启 Nginx,实现真正的永久免费、无人值守

你可以通过以下命令查看该定时任务是否成功植入:

Bash

crontab -l

(你将看到一条指向 acme.sh --cron 的任务记录。)