使用acme.sh脚本申请Let's Encrypt免费泛域名证书

问题描述

在之前搭建Hexo博客的时候是使用了 letsencrypt-auto 脚本来生成 Let’s Encrypt 证书的,但是用这个我没能实现自动续期,于是学习了一下,发现改用 acme.sh 脚本可以很方便的实现我的需求,本文记录一下使用过程。

操作步骤

下载并执行脚本

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

生成证书

acme.sh 实现了 acme 协议支持的所有验证协议。一般有两种方式验证:http 和 dns 验证。

如果是http方式的话,需要在你网站的根目录下放置一个文件来验证你的域名的所有权。

1
acme.sh  --issue  -d mydomain.com -d www.mydomain.com  --webroot  /home/wwwroot/mydomain.com/

如果是dns方式的话,需要手动在域名托管商那里添加一条TXT记录,验证域名的所有权。本文就是基于这种认证方式。acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种域名解析商的自动集成,也就是说acme.sh脚本,会调用这些域名解析商家的API(当然这需要你的授权),脚本将替你完成手动添加TXT记录并验证的过程,非常方便,具体过程如下:

在域名解析商新建一个API Token

以我的域名托管的 Dnspod 为例,登陆账号之后,点击头像,在弹出框中选择安全设置,然后在左侧的导般菜单中选择密钥管理,点击创建,填写名称之后,会生成一对 ID 和 Token,牢记这个 Token,这个只在申请的时候显示一次,以后是不可以再回显出来的了。有了这个 Token 之后 acme.sh 就可以通过Dnspod的API来操作你的域名了,所以这个 Token 一定要保证安全不要泄露出去。

在VPS上设置配置API Token

因为只需要认证一次,所以我将只需要在执行 acme.sh 脚本之前配置2个临时的环境变量即可。

1
2
export DP_Id="170037"
export DP_Key="*****************************"

验证域名、生成证书

--dns 参数指定你使用的是哪家的域名解析商,dns_dp 是固定值,代表 Dndpod,每一个 -d 参数可以指定一个域名,我这里是指定了一个根域名,以及二级泛解析域名,执行下面这句命令之后,会等待120秒钟,成功之后会在 /root/.acme.sh/ 目录中生成相应的证书。

一定要注意,不要直接在你的 Nginx 中配置使用这个路径下的证书,而是需要先执行下面的安装步骤,使用 --install-cert 命令来将证书生成在你指定的位置

1
~/.acme.sh/acme.sh  --issue  --dns dns_dp  -d ningyu.me  -d *.ningyu.me

安装证书

--keypath 这个参数是要指定将生成的私钥和证书放在什么位置,这个路径是可以你自己任意指定的。

--reloadcmd 这个参数是实现当证书更新了之后,会自动执行的命令,比如我这里就是当证书更新了,要重新启动一下 Nginx,让 Nginx重新加载新的证书。

1
~/.acme.sh/acme.sh --installcert -d ningyu.me -d www.ningyu.me -d *.ningyu.me --keypath /usr/share/workspace/ssl/ningyu.key --fullchainpath /usr/share/workspace/ssl/ningyu.pem --reloadcmd "systemctl restart nginx"

使用证书

在你的 Nginx 的配置文件中,找到需要配置的虚拟主机项(server),指定 ssl_certificatessl_certificate_key,在我的配置中是将根域名、www 子域名和其它的二级域名共用这一个证书。

ssl_dhparam这个参数指定的文件可以通过 openssl dhparam -out /usr/share/workspace/ssl/dhparam.pem 2048命令来生成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server {
listen 80;
server_name localhost;
rewrite ^(.*)$ https://$host$1 permanent;
}
server {
listen 443 ssl;
server_name ningyu.me www.ningyu.me;
ssl_certificate /usr/share/workspace/ssl/ningyu.pem;
ssl_certificate_key /usr/share/workspace/ssl/ningyu.key;
ssl_dhparam /usr/share/workspace/ssl/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
location / {
root /usr/share/workspace/tony-website/.dist;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name blog.ningyu.me;
ssl_certificate /usr/share/workspace/ssl/ningyu.pem;
ssl_certificate_key /usr/share/workspace/ssl/ningyu.key;
ssl_dhparam /usr/share/workspace/ssl/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
location / {
root /usr/share/workspace/hexo/blog/public;
index index.html index.htm;
}
}

检查证书自更新

acme.sh 脚本会自动在你的系统添加一条计划任务,例如为我添加的就是每天的0点58分,会自动的更新一下证书,这样就不用担心Let's Encrypt 证书到期的问题了。

1
2
[root@heirloom-dc8 webhook-linux-amd64]# crontab -l
58 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

脚本相关内容

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新,因此 acme.sh 也经常更新以保持同步。

手动升级 acme.sh 到最新版:

1
acme.sh --upgrade

如果你不想手动升级, 可以开启自动升级:

1
acme.sh  --upgrade  --auto-upgrade

你也可以随时关闭自动更新:

1
acme.sh --upgrade  --auto-upgrade  0

参考

EOF