acme.sh免费SSL证书自动续期

ACME(自动证书管理环境)是一个互联网工程任务组维护的协议,它允许自动化 Web 服务器证书的部署,acme.sh 是支持 ACME 协议流行的客户端之一,可以通过其实现 SSL 证书的自动申请、续期等。利用它我们可以实现90天免费SSL证书的自动续期,从申请证书到使用证书完全自动化,无需人工操作。

一、安装acme.sh

安装过程非常简单,一条命令即可:

curl https://get.acme.sh | sh

或者

wget -O -  https://get.acme.sh | sh

安装过程进行了以下几步:

1.把 acme.sh 安装到你的 home 目录下:~/.acme.sh/

2.创建 一个 shell 的 alias到.bashrc,例如 alias acme.sh=~/.acme.sh/acme.sh

3.创建 cronjob, 每天 0:00 点自动检测所有的证书,acme.sh会在证书到期前30天自动更新证书。

更高级的安装选项请参考: https://github.com/acmesh-official/acme.sh/wiki/How-to-install

升级acme.sh

如果已经安装了acme.sh,建议升级到最新版本

acme.sh --upgrade

二、选择认证方式

acme.sh支持两种认证方式,HTTP认证和DNS认证,目的都是为了验证目标域名的所有者,其中:

  • HTTP认证需要指定wwwroot目录,http认证的原理是:acme.sh会在网站根目录生成一个验证文件然后通过http获取该文件内容来实现认证,这个方式十分便捷,但缺点是不支持泛域名认证*.example.com,因为不会有人将多个域名的web服务放在同一个目录下。

  • DNS认证需要提供域名解析服务托管商的API接口密钥,DNS认证的原理是:acme.sh会通过API接口自动在域名解析中新增一条包含特殊字符的TXT记录,然后通过解析域名得到这串特殊字符进行比对认证,这个方式支持泛域名认证,但是需要我们提供域名解析权给到acme.sh,APIkey需要注意保管避免泄露。

由于HTTP不支持泛域名证书,而我的子域名又比较多,所以我这里选择DNS认证来生成泛域名证书,我的域名托管在腾讯云中,我们需要到腾讯云控制台申请SecretId 和 SecretKey,然后将其添加到环境变量中供acme.sh调用

export Tencent_SecretId="AKIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export Tencent_SecretKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

其他域名解析托管商配置方法,请参考:https://github.com/acmesh-official/acme.sh/wiki/dnsapi

三、生成证书

使用一条命令即可生成证书:

acme.sh --register-account -m my@example.com \
        --issue \
        --dns dns_tencent \
        -d newmorning.work -d *.newmorning.work \
        -k 4096
  • 参数解释:

    • --register-account -m my@example.com:acme.sh默认使用ZeroSSL,这里是提供域名账号用于注册ZeroSSL或其他证书提供商

    • --issue :生成证书

    • --dns dns_tencent :使用dns认证,并指定dns提供商腾讯云

    • -d newmorning.work -d *.newmorning.work :要生成证书的域名,可使用泛域名

    • -k 4096:acme.sh默认生成ECC证书,这里我们选择指定4096长度的RSA证书

证书生成成功,acme.sh会输出证书所在位置,例如:

[Wed Apr 23 15:06:12 CST 2025] Your cert is in: /root/.acme.sh/newmorning.work/newmorning.work.cer
[Wed Apr 23 15:06:12 CST 2025] Your cert key is in: /root/.acme.sh/newmorning.work/newmorning.work.key
[Wed Apr 23 15:06:12 CST 2025] The intermediate CA cert is in: /root/.acme.sh/newmorning.work/ca.cer
[Wed Apr 23 15:06:12 CST 2025] And the full-chain cert is in: /root/.acme.sh/newmorning.work/fullchain.cer

四、部署证书

acme.sh 不建议直接使用~/.acme.sh/目录下的证书文件,而是通过 acme.sh 提供的命令将证书安装到指定位置,以确保证书的正确使用和续期,详情请参考 Install the cert to Apache/Nginx etc,下面以Nginx为例。

acme.sh --install-cert -d newmorning.work \
        --key-file /etc/ssl_cert/newmorning.work/key.pem \
        --fullchain-file /etc/ssl_cert/newmorning.work/cert.pem \
        --reloadcmd  "nginx -s reload"

证书安装完成后,将证书和私钥配置到nginx中,示例:

server {
    listen 443 ssl http2;

    server_name example.com;

    # 请替换为证书实际路径
    ssl_certificate     /etc/ssl_cert/newmorning.work/key.pem;
    ssl_certificate_key /etc/ssl_cert/newmorning.work/cert.pem;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;
    ssl_prefer_server_ciphers on;
    location / {
        root /nginx/www/html;
    }
}

五、调整自动任务

crontab -l 发现acme.sh为我们默认创建了一条crontab任务,即每天的5点03分执行更新

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

在实际应用中我们不需要这么频繁,由于acme.sh会提前30天更新证书,所以我们设置为每周一次即可,这里设置为每周一的5点03分更新证书,另外增加了一条更新证书1小时后刷新nginx。

3 5 * * 1 "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
3 6 * * 1 /usr/sbin/nginx -s reload

到这里我们就可以完全把SSL证书托管给acme.sh了,再也不用担心忘记证书更新啦!

当然为了以防万一,我们最好还是监控一下HTTP和SSL,哈哈