通过acme签发免费HTTPS证书并实现自动续期的方法

如下操作基于 Ubuntu 24.04 环境进行,域名在阿里云解析。
使用 acme.sh 配合阿里云 DNS API,实现支持泛域名的 SSL 证书签发。
acme.sh 安装后会自带 cron 定时任务,实现全自动续期。

特别说明:
阿里云 DNS 插件(dns_ali)是 acme.sh 内置自带的,不需要像系统软件那样单独执行 apt install 或额外下载安装。
实际上,acme.sh 的设计已经将各类 DNS 服务商的适配脚本作为内置插件来管理。
通过官方脚本安装 acme.sh 后,所有支持的 DNS 服务商脚本(包括阿里云的 dns_ali.sh)都会被自动放置到工作目录下的 dnsapi/ 文件夹中。
因此,签发命令的 --dns dns_ali 参数会直接引导 acme.sh 去调用其内部已有的 dns_ali.sh 脚本,整个过程是开箱即用的,无需额外“安装插件”这一独立步骤。

1. 前提准备:创建阿里云 RAM 子用户(安全第一)

不要使用主账号的 AccessKey。创建一个仅拥有 DNS 管理权限的 RAM 子用户,即使密钥泄露也不会危及服务器、账单等其他资源。

  1. 登录阿里云 RAM 访问控制控制台。
  2. 身份管理 → 用户 → 创建用户:
  • 登录名称:例如 acme-dns
  • 访问方式:只勾选“使用永久 AccessKey 访问”(不要开启控制台登录)
  1. 创建成功后,立即保存 AccessKey ID 和 AccessKey Secret(Secret 只显示一次)。
  2. 在用户列表中点击该用户 → 权限管理 → 新增授权 → 搜索并勾选系统策略 AliyunDNSFullAccess,授权范围保持“账号级别”。
  3. 等待约 1 分钟让权限缓存生效。

2. 安装 acme.sh

执行一键安装:

curl https://get.acme.sh | sh -s email=你的邮箱@example.com
source ~/.bashrc
acme.sh -v   # 确认安装成功,应显示版本号

安装脚本会自动完成三件事:把程序装到 ~/.acme.sh/、添加 acme.sh 命令别名、注册自动续期的 cron 任务。

受中国大陆境内的网络环境限制,如果执行上述一件安装比较慢甚至无法执行安装时,可以采用如下 Gitee 源码安装 的方式。

git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m 你的邮箱@example.com
source ~/.bashrc
acme.sh -v   # 确认安装成功,应显示版本号

3. 配置阿里云 DNS API 凭据

将上一步获取的 AccessKey 设置为环境变量(建议写入 ~/.bashrc 以便持久化):

export Ali_Key="你的AccessKeyId"
export Ali_Secret="你的AccessKeySecret"

写入 ~/.bashrc:

echo 'export Ali_Key="你的AccessKeyId"' >> ~/.bashrc
echo 'export Ali_Secret="你的AccessKeySecret"' >> ~/.bashrc
source ~/.bashrc

注意:acme.sh 对阿里云 DNS 的变量名是 Ali_Key / Ali_Secret,不要误写成 ALIYUN_ACCESS_KEY 等其他形式。

4. 签发泛域名证书(DNS-01 验证)

假设你的主域名是 example.com,需要覆盖所有子域名。关键点:泛域名 *.example.com 不包含主域名本身,因此必须同时用 -d 指定两者。

acme.sh --issue \
  --dns dns_ali \
  -d example.com \
  -d '*.example.com' \
  --keylength ec-256
  • --dns dns_ali:调用阿里云 DNS API 自动添加/清理 TXT 验证记录。
  • --keylength ec-256:签发 ECC 证书(更小、更快,现代浏览器兼容性良好)。如不需要 ECC,可省略此参数,默认签发 RSA 证书。

执行后,acme.sh 会自动在阿里云 DNS 中添加一条 _acme-challenge 的 TXT 记录,等待 Let‘s Encrypt 验证通过后自动删除该记录,无需手动干预。

签发成功后,证书默认存放于 ~/.acme.sh/example.com_ecc/ 目录下。

5. 安装证书到 Nginx 并配置自动重载

--issue 只负责“签发”,还需要把证书安装(复制) 到 Nginx 实际读取的路径,并设置续期后的重载命令。

mkdir -p /etc/nginx/ssl

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

# 非root用户执行时使用需要将 systemctl reload nginx 替换为 sudo /bin/systemctl reload nginx.service
acme.sh --install-cert -d example.com --ecc \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "sudo /bin/systemctl reload nginx.service"

--install-cert 会把证书和私钥复制到指定路径,并将这些路径和 --reloadcmd 写入域名配置文件,后续每次自动续期后都会自动执行 systemctl reload nginx,使新证书立即生效。

Nginx 配置示例:

server {
    listen 443 ssl;
    server_name example.com *.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # 其余反向代理或静态站点配置
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

server_name 中同时写入 example.com 和 *.example.com,才能让主域名和子域名都匹配到这张证书。

6. 验证自动续期机制

acme.sh 安装时已自动注册 cron 任务,每天凌晨随机时间检查所有证书的剩余有效期。当证书距离到期少于 30 天时,自动触发续期,续期成功后执行你设置的 --reloadcmd。

可以通过以下命令确认 cron 任务存在:

crontab -l | grep acme.sh

正常应看到类似输出:

0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

如需手动测试续期流程(不等待临近过期),可强制续期一次并观察 Nginx 是否被重载:

acme.sh --renew -d example.com --ecc --force

【参考】
Nginx免费SSL自动续期


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,在下面评论区告诉我^_^^_^