这两年,良心云和套路云这些SSL证书厂商的有效期逐渐都从1年有效期改成了3个月,需要手动签发证书的频率大增,是时候把之前听说过的acme.sh 自动签发泛域名证书折腾折腾了。
acme.sh部署
首先是安装acme.sh,这里选择了docker的方式运行,随用随抛。docker-compose的配置如下:
version: '3.8'
services:
acme-sh:
image: neilpang/acme.sh
container_name: acme.sh
network_mode: host
command: daemon
stdin_open: true
tty: true
restart: unless-stopped
使用下面的命令生成并启动容器
docker compose up -d
请注意:创建的容器 acme.sh 必须保持开启状态,否则下面的脚本不生效
账户/环境变量配置
容器启动之后,需要配置CA服务商的相关信息,acme.sh从v3版本开始,默认CA服务商变成ZeroSSL,因此这里需要有一个ZeroSSL账号。
账号注册完成后,在 https://app.zerossl.com/developer 页面生成EAB凭证。
进入容器内部
docker exec -it acme.sh /bin/sh
acme.sh 注册账户信息以及EAB凭证相关配置
acme.sh --register-account --server zerossl \
-m email \
--eab-kid xxxxxxxxxxxx \
--eab-hmac-key xxxxxxxxx
当然这一步也可以根据实际需求切换到其他CA服务商,比如 Let’s Encrypt。
根据不同的域名服务商,接下来需要配置相关的API Key等参数,详细可参考:官方文档
以CloudFlare为例,在 API tokens section 页面获取Global API Key,点击查看按钮,输入CloudFlare的密码之后,将会出现一个32位的数字/字母混合字符串,将改字符串的值设置为环境变量 CF_Key
,还需要设置 CF_Email
环境变量,值为CloudFlare的登录邮箱。
示例如下:
export CF_Key="763eac4f1bcebd8b5c95e9fc50d010b4"
export CF_Email="alice@example.com"
申请RSA/ECC双泛域名证书
创建两个文件夹,分别保存转换后的rsa证书和ecc证书
mkdir -p /etc/nginx/rsa
mkdir -p /etc/nginx/ecc
接下来在容器外的 /home/acme
目录新建脚本 crontab.sh
# 申请ecc泛域名证书
docker exec acme.sh acme.sh --issue --dns dns_cf -d abc.com -d *.abc.com
# 申请rsa泛域名证书
docker exec acme.sh acme.sh --issue --dns dns_cf -d abc.com -d *.abc.com --keylength 2048
# 转换ecc证书
docker exec acme.sh acme.sh --installcert --ecc -d abc.com \
--key-file /etc/nginx/ecc/abc.com.key \
--fullchain-file /etc/nginx/ecc/abc.com.cer
#转换rsa证书
docker exec acme.sh acme.sh --installcert -d abc.com \
--key-file /etc/nginx/rsa/abc.com.key \
--fullchain-file /etc/nginx/rsa/abc.com.cer
#生成的证书拷贝到nginx目录
docker cp acme.sh:/etc/nginx/rsa/abc.com.key /etc/nginx/conf.d/cert/rsa/abc.com.key
docker cp acme.sh:/etc/nginx/rsa/abc.com.cer /etc/nginx/conf.d/cert/rsa/abc.com.cer
docker cp acme.sh:/etc/nginx/ecc/abc.com.key /etc/nginx/conf.d/cert/ecc/abc.com.key
docker cp acme.sh:/etc/nginx/ecc/abc.com.cer /etc/nginx/conf.d/cert/ecc/abc.com.cer
#重启nginx服务
docker exec nginx nginx -s reload
其中申请证书命令中的参数 --dns dns_cf
这里指代CloudFlare为DNS解析服务商,需要根据实际场景替换,比如腾讯云为 --dns dns_dp
配置脚本定期执行
crontab -e
将下面的规则添加到最后一行,每天的0点和12点执行脚本尝试申请新证书,并更新nginx配置。
0 0,12 * * * /bin/bash /home/acme/crontab.sh > /dev/null 2>&1 &'
需要注意的是,泛域名证书的有效期为90天,上面的脚本并不会每天都会重新申请新的证书,到续期时间(证书过期前2-3天)才会申请新证书。
Nginx证书配置
参考配置如下:
# ECC Cert
ssl_certificate /etc/nginx/conf.d/cert/ecc/abc.com.cer;
ssl_certificate_key /etc/nginx/conf.d/cert/ecc/abc.com.key;
# RSA Cert
ssl_certificate /etc/nginx/conf.d/cert/rsa/abc.com.cer;
ssl_certificate_key /etc/nginx/conf.d/cert/rsa/abc.com.key;