使用acme.sh自动申请、续期、部署免费的SSL证书
参考文档:https://github.com/acmesh-official/acme.sh
一个使用纯shell操作的免费SSL证书申请部署工具。
免费的SSL证书由以下CA机构提供:
ZeroSSL.com CA(default)
Letsencrypt.org CA
BuyPass.com CA
SSL.com CA
Pebble strict Mode
Any other RFC8555-compliant CA
安装与初次使用
1、从Git安装
安装时需要指定要创建账号的邮箱,初次运行需要用邮箱在CA上创建一个账户!
root@localhost:~# mkdir /usr/local/acme
root@localhost:~# cd /usr/local/acme/
root@localhost:/usr/local/acme# git clone https://github.com/acmesh-official/acme.sh.git
root@localhost:/usr/local/acme# cd acme.sh/
root@localhost:/usr/local/acme/acme.sh# ./acme.sh --install -m xxx@xxx.com
[Wed Jan 19 09:53:09 CST 2022] It is recommended to install socat first.
[Wed Jan 19 09:53:09 CST 2022] We use socat for standalone server if you use standalone mode.
[Wed Jan 19 09:53:09 CST 2022] If you don't use standalone mode, just ignore this warning.
[Wed Jan 19 09:53:09 CST 2022] Installing to /root/.acme.sh
[Wed Jan 19 09:53:09 CST 2022] Installed to /root/.acme.sh/acme.sh
[Wed Jan 19 09:53:09 CST 2022] Installing alias to '/root/.bashrc'
[Wed Jan 19 09:53:09 CST 2022] OK, Close and reopen your terminal to start using acme.sh
[Wed Jan 19 09:53:09 CST 2022] Installing cron job
41 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
[Wed Jan 19 09:53:09 CST 2022] Good, bash is found, so change the shebang to use bash as preferred.
[Wed Jan 19 09:53:10 CST 2022] OK
root@localhost:/usr/local/acme/acme.sh# vim /etc/profile
### acme ###
export PATH=/usr/local/acme/acme.sh:$PATH
root@localhost:/usr/local/acme/acme.sh# source /etc/profile
root@localhost:/usr/local/acme/acme.sh# crontab -l
41 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
2、申请颁发单个域名证书(Nginx类型)
首次使用的时候,会在对应的网站注册一个账号!
申请证书需要等待一段时间,等待CA处理订单,等待30次后超时!
-d表示申请的指定域名,
-w表示网站根目录,用于校验,这将会指定的目录下生成相关DNS校验文件
颁发的证书通常为3个月!
root@localhost:~# acme.sh --issue -d example.com -w /var/www/html/v3html
[Wed Jan 19 11:45:38 CST 2022] Using CA: https://acme.zerossl.com/v2/DV90
[Wed Jan 19 11:45:38 CST 2022] Create account key ok.
[Wed Jan 19 11:45:38 CST 2022] No EAB credentials found for ZeroSSL, let's get one
[Wed Jan 19 11:45:40 CST 2022] Registering account: https://acme.zerossl.com/v2/DV90
[Wed Jan 19 11:46:00 CST 2022] Registered
[Wed Jan 19 11:46:00 CST 2022] ACCOUNT_THUMBPRINT='pDK-DHSyN3bTcjqa_Bkr9zvXv4cFA4mVbOMNvLxePdU'
[Wed Jan 19 11:46:00 CST 2022] Creating domain key
[Wed Jan 19 11:46:00 CST 2022] The domain key is here: /root/.acme.sh/example.com/example.com.key
[Wed Jan 19 11:46:00 CST 2022] Single domain='example.com'
[Wed Jan 19 11:46:00 CST 2022] Getting domain auth token for each domain
[Wed Jan 19 11:46:08 CST 2022] Getting webroot for domain='example.com'
[Wed Jan 19 11:46:08 CST 2022] Verifying: example.com
[Wed Jan 19 11:46:14 CST 2022] Processing, The CA is processing your order, please just wait. (1/30)
[Wed Jan 19 11:46:27 CST 2022] Success
[Wed Jan 19 11:46:27 CST 2022] Verify finished, start to sign.
[Wed Jan 19 11:46:27 CST 2022] Lets finalize the order.
[Wed Jan 19 11:46:27 CST 2022] Le_OrderFinalize='https://acme.zerossl.com/v2/DV90/order/moQ9G2k4tjnsw-nB7J356A/finalize'
[Wed Jan 19 11:46:38 CST 2022] Order status is processing, lets sleep and retry.
[Wed Jan 19 11:46:38 CST 2022] Retry after: 15
[Wed Jan 19 11:46:54 CST 2022] Polling order status: https://acme.zerossl.com/v2/DV90/order/moQ9G2k4tjnsw-nB7J356A
[Wed Jan 19 11:46:57 CST 2022] Downloading cert.
[Wed Jan 19 11:46:57 CST 2022] Le_LinkCert='https://acme.zerossl.com/v2/DV90/cert/aWSl8r_uVs8r69U0z0BI5A'
[Wed Jan 19 11:47:03 CST 2022] Cert success.
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
[Wed Jan 19 11:47:03 CST 2022] Your cert is in: /root/.acme.sh/example.com/example.com.cer
[Wed Jan 19 11:47:03 CST 2022] Your cert key is in: /root/.acme.sh/example.com/example.com.key
[Wed Jan 19 11:47:03 CST 2022] The intermediate CA cert is in: /root/.acme.sh/example.com/ca.cer
[Wed Jan 19 11:47:03 CST 2022] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer
3、配置Nginx
root@localhost:~# vim /etc/nginx/conf/example.com.conf
server {
listen 443 ssl;
server_name example.com;
root html;
ssl_certificate /etc/nginx/ssl/example.com.cer;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
4、安装域名证书到指定Nginx位置
root@localhost:~# acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.cer \
--reloadcmd "nginx -s reload"
附录-查看已管理的域名
acme.sh --list
附录-删除托管的域名
示例:
acme.sh --remove -d example.com [--ecc]
附录-申请颁发多个域名证书
示例:
acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com
附录-将证书自动安装到Nginx或Apache
Apache示例:
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"
Nginx示例:
acme.sh --install-cert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.key \
--fullchain-file /path/to/fullchain/nginx/cert.cer \
--reloadcmd "service nginx force-reload"
附录-强制更新证书
我们通常不需要手动更新证书,所有证书每60天会自动更新一次。
但是也可以手动强制更新证书。
示例:
acme.sh --renew -d example.com --force
附录-设置默认使用的CA
参考文档:https://github.com/acmesh-official/acme.sh/wiki/Server
letsencrypt https://acme-v02.api.letsencrypt.org/directory
buypass https://api.buypass.com/acme/directory
zerossl https://acme.zerossl.com/v2/DV90
sslcom https://acme.ssl.com/sslcom-dv-rsa, https://acme.ssl.com/sslcom-dv-ecc
root@localhost:~# acme.sh --set-default-ca --server letsencrypt
附录-查看证书有效期
root@localhost:/etc/nginx/ssl# openssl x509 -in www.example.cer -noout -dates
notBefore=Jan 19 00:00:00 2022 GMT
notAfter=Apr 19 23:59:59 2022 GMT
附录-自动续期+钉钉报警
自己写的脚本,结合计划任务每天执行一次!
#!/bin/bash
# @author: rby
# @description: 使用acme.sh自动申请、部署并续期(提前一周)免费的ssl证书,并通知到钉钉群告知运维工程师!
set -x
DOMAIN_LIST="
admin.example.com
api.example.com
h5.example.com
opapi.example.com
www.example.com
"
SSL_DIR="/etc/nginx/ssl"
WEBROOT="/var/nginx/html"
ACMESH="/usr/local/acme/acme.sh/acme.sh"
NOTICE_DINGDING_TOBOT="https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
noticeDingding(){
msg="{\"msgtype\": \"text\",\"text\": {\"content\": "\'"${1}"\'"},\"at\": {\"isAtAll\": true}}"
curl "$NOTICE_DINGDING_TOBOT" -H 'Content-Type: application/json' -d "$msg"
}
applyFreeSSLCertificate(){
status=0
# 1、强制申请免费ssl证书
$ACMESH --issue -d $domain -w $WEBROOT --force
[ $? -eq 0 ] && status=`expr $status + 1`
# 2、安装ssl证书到nginx
$ACMESH --install-cert -d ${domain} --key-file "${SSL_DIR}/${domain}.key" --fullchain-file "${SSL_DIR}/${domain}.cer" --reloadcmd "nginx -s reload" # 自动部署到nginx
[ $? -eq 0 ] && status=`expr $status + 1`
if [ $status -eq 2 ];then
noticeDingding "申请并部署、续期(提前一周)免费ssl证书"${domain}"成功!"
else
noticeDingding "申请并部署、续期(提前一周)免费ssl证书"${domain}"失败!请手动执行本脚本程序再次申请、续期以观测失败原因!"
fi
}
for domain in $DOMAIN_LIST;do
echo "自动申请部署并续期ssl证书,域名=$domain"
# 申请部署免费SSL证书
# 如果证书文件不存在则自动申请并部署免费的SSL证书
if [ ! -e ${SSL_DIR}/${domain}.cer ];then
applyFreeSSLCertificate
fi
# 自动续期
# 检查ssl证书到期时间,提前一周自动续期并部署新的ssl证书
expirationTimeGMT=`openssl x509 -in ${SSL_DIR}/${domain}.cer -noout -dates|grep notAfter|awk -F '=' '{print $2}'` # 证书到期GMT时间
expirationTime=`date -d "$expirationTimeGMT" +%s` # 证书到期时间,转换为以秒为单位的时间戳
currTime=`date +%s` # 当前时间戳
echo "当前证书到期时间还有$(expr $(expr $expirationTime - $currTime) / 60 / 60 / 24)天"
if [ $(expr $(expr $expirationTime - $currTime) / 60 / 60 / 24) -lt 7 ];then
applyFreeSSLCertificate
fi
done