如何使用acme.sh从CA生成免费证书并实现自动续签

现在SSL证书的有效期基本在一年左右,而免费的SSL证书的有效期只有90天,对于运维人员来说就需要每年甚至每季度更新一次证书。在今年10月10日苹果公司更是提出将SSL证书有效期缩短为45天的标准提案,试想一下,如果真的缩短到45天,那运维人员岂不是一个半月就要更新一次…那就只剩下自动化这条路了。

现在全球领先的云服务提供商都已经全部支持ACME自动化配置SSL证书,acme.sh项目就实现了ACME协议,通过它就可以从ZeroSSL,Let’s Encrypt等CA生成免费的证书并自动续签

安装acme.sh


安装很简单,就一条命令

1
curl https://get.acme.sh | sh -s email=my@email.com && source ~/.bashrc

说明
my@email.com替换为你自己真实的邮箱地址

如果要安装acme.sh的服务器位于中国大陆, 可能会无法访问GitHub导致安装失败,因此,对于中国大陆用户推荐从https://gitee.com/neilpang/acme.sh下载安装,具体安装命令为

1
2
3
4
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@email.com
source ~/.bashrc

安装脚本会将acme.sh安装到~/.acme.sh目录中,同时自动创建crontab计划任务,在每天00:XX(XX是随机的)自动检测所有的证书,如果快到期了,则自动续期并更新证书

生成证书


acme.sh实现了ACME协议支持的所有验证方式(HTTP/DNS/TLS-SNI/EXTERNAL-ACCOUNT),最常用的有HTTP和DNS两种方式。

说明

  • HTTP验证:需要在网站根目录下放置一个文件,来验证对域名的所有权,然后才可以生成证书。(需要公网IP和开放相应端口)
  • DNS验证:需要手动通过域名服务商提供的API自动在域名上添加一条txt解析记录,验证域名所有权。
  • 本文采用的是不需要公网IP的DNS验证

DNS验证的真正强大之处在于可以使用域名解析商提供的API自动添加TXT记录,且在完成验证后删除对应的记录。acme.sh目前支持超过一百家的DNS API,详情可以查看acme.sh官方文档,本文以阿里云为例。

获取域名服务商的Key和Secret信息

首先,登录你的阿里云账号(https://ram.console.aliyun.com/users)获取用于访问资源的RAM(Resource Access Management) API密钥,并添加DNS相关的权限策略,具体操作可参考以下阿里云官方文档

说明
RAM API密钥是用于身份验证和授权的重要凭证,确保用户能够安全地访问和管理其云资源,请妥善保管

然后执行以下命令配置AccessKey IDAccessKey Secret

1
2
export Ali_Key="<AccessKey ID>"
export Ali_Secret="<AccessKey Secret>"

说明
Ali_KeyAli_Secret将会被保存在~/.acme.sh/account.conf文件中。当未来再次需要使用时,系统会自动从这个文件中读取,无需用户再次输入。

DNS自动验证签发证书

说明
DNS手动验证需要手动在域名上添加一条TXT解析记录,验证域名所有权,这种方式将无法自动更新证书,所以建议使用DNS自动验证(DNS API)

以我的域名为例,一级域名为koenli.com,二级域名为www.koenli.com,签发证书的命令如下:

1
2
# acme.sh --issue --dns dns_ali -d <一级域名> -d <二级域名1> -d <二级域名2>
acme.sh --issue --dns dns_ali -d koenli.com -d www.koenli.com

配置证书到Nginx/Apache或者其他服务


证书生成好以后,我们需要把证书复制给对应的Nginx、Apache或其他WEB服务去使用。

说明
必须使用--install-cert命令来把证书复制到目标文件,请勿直接使用~/.acme.sh/目录下的证书文件,这里面的文件都是内部使用,而且目录结构将来可能会变化。

配置到Nginx

1
2
3
4
acme.sh --install-cert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx reload"

说明
更新证书后,acme.sh会通过reloadcmd传递的命令自动重新加载WEB服务的配置,因此请确认传递的reloadcmd命令准确无误。

配置到Apache

1
2
3
4
5
acme.sh --install-cert -d example.com \
--cert-file /path/to/certfile/in/apache/cert.pem \
--key-file /path/to/keyfile/in/apache/key.pem \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 force-reload"

说明
更新证书后,acme.sh会通过reloadcmd传递的命令自动重新加载WEB服务的配置,因此请确认传递的reloadcmd命令准确无误。

配置到雷池WAF

说明
因为我配置了雷池WAF,证书需要配置在雷池上,配置步骤会有所区别。

在证书签发完成后,通过绿色字体部分获取证书存放路径

将证书中的fullchain.cer文件和域名.key文件拉取到本地,登录雷池,选择“防护站点”-“证书管理”-“添加证书”-“上传已有证书”,将证书文件上传到雷池

在“防护站点”-“站点管理”-对应站点右侧“...”-“编辑”中,配置站点证书为上一步上传的证书

在服务器上执行以下命令在雷池的站点配置文件中(雷池默认的安装路径为/data/safeline)查找对应域名的证书存放路径和文件名

1
2
# cat /data/safeline/resources/nginx/sites-enabled/* | grep -C 4 <雷池上配置的站点域名>
cat /data/safeline/resources/nginx/sites-enabled/* | grep -C 4 www.koenli.com

输出类似如下,表示cert文件的文件名为cert_119.crt,key文件的文件名为cert_119.key

1
2
3
4
...
ssl_certificate /etc/nginx/certs/cert_119.crt;
ssl_certificate_key /etc/nginx/certs/cert_119.key;
...

最后执行以下命令配置证书到雷池的证书存放路径

说明
雷池WAF为容器部署,所以站点配置文件中看到的存放路径为在容器中对应的路径,实际对应到宿主机上的路径为/data/safeline/resources/nginx/certs/

1
acme.sh --install-cert -d koenli.com -d www.koenli.com --key-file /data/safeline/resources/nginx/certs/cert_119.key --fullchain-file /data/safeline/resources/nginx/certs/cert_119.crt --reloadcmd "docker exec safeline-tengine nginx -s reload"

说明
更新证书后,acme.sh会通过reloadcmd传递的命令自动重新加载WEB服务的配置,因此请确认传递的reloadcmd命令准确无误。

查看已安装证书信息


1
2
# acme.sh --info -d <一级域名>
acme.sh --info -d koenli.com

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
DOMAIN_CONF=/root/.acme.sh/koenli.com/koenli.com.conf
Le_Domain=koenli.com
Le_Alt=www.koenli.com
Le_Webroot=dns_ali
Le_PreHook=
Le_PostHook=
Le_RenewHook=
Le_API=https://acme.zerossl.com/v2/DV90
Le_Keylength=2048
Le_OrderFinalize=https://acme.zerossl.com/v2/DV90/order/xxxxxx/finalize
Le_LinkOrder=https://acme.zerossl.com/v2/DV90/order/xxxxxx
Le_LinkCert=https://acme.zerossl.com/v2/DV90/cert/xxxxxx
Le_CertCreateTime=1735116684
Le_CertCreateTimeStr=2024-12-25T15:45:58Z
Le_NextRenewTimeStr=2025-02-23T15:45:58Z
Le_NextRenewTime=1740214284
Le_RealCertPath=
Le_RealCACertPath=
Le_RealKeyPath=/data/safeline/resources/nginx/certs/cert_119.key
Le_ReloadCmd=docker exec safeline-tengine nginx -s reload
Le_RealFullChainPath=/data/safeline/resources/nginx/certs/cert_119.crt

更新证书


目前证书每60天自动更新,你无需任何操作。但是也可以执行以下命令强制续签证书

1
2
# acme.sh --renew -d <一级域名> --force
acme.sh --renew -d koenli.com --force

常见问题


安装acme.sh时出现以下警告信息

1
2
3
[Fri Dec 27 15:22:22 CST 2024] It is recommended to install socat first.
[Fri Dec 27 15:22:22 CST 2024] We use socat for standalone server if you use standalone mode.
[Fri Dec 27 15:22:22 CST 2024] If you don't use standalone mode, just ignore this warning.

从信息中可以看出是建议我们安装socat,那就听从官方建议装上即可

1
yum install socat -y