https证书自动续订(renew)问题
注意: 如果你的域名的顶级域名是.cf
, .ga
, .gq
, .ml
, .tk
,并且接入了cloudflare,那么都不能直接用acme.sh获取,只能手动去cloudflare创建,创建方法:SSL/TLS
→Origin Server
→Origin Certificates
→Create Certificate
,然后手动把证书和密钥内容复制保存到证书文件和密钥文件中。
之前写过一篇文章:为你的网站配置免费的HTTPS支持,看本文之前,建议先看一下这篇文章。
前面文章讲的方法主要是无法自动续订通配符证书,其原因是通配符证书需要向域名服务商添加一个txt记录,其实用前面文章中的certbot renew
也是可以的,只是要指定更新域名服务商txt记录的shell脚本,该脚本需要调用域名服务商提供的接口,如果你熟悉shell,完全可以自己写,如果你不想麻烦,已经有人帮写好了一个工具:acme.sh。
配置步骤
再简单说一下配置步骤:
- 1.获取https证书(即ssl证书,前面说了,http是用ssl或tls来加密数据包的,所以我们要选获取ssl证书)
- 2.在http服务器(如nginx、apache等)中配置使用ssl证书
- 3.过期前自动更新证书(证书是有时效的,比如letsencrypt的证书有效期是90天)
http证书的类型
https证书有指定域名的证书和通配符证书,指定域名如:xiebruce.com
和www.xiebruce.com
就是指定域名,而*.xiebruce.com
即为通配符证书。通配符证书的好处,就在于,如果你后面又增加了几个网站子域名,比如aaa.xiebruce.com
、bbb.xiebruce.com
,你就可以直接用通配符证书,否则你每增加一个子域名,就要申请一次证书,特别麻烦。
既然通配符证书简单,是不是只申请通配符证书就行了呢?是的,但要注意通配符证书是不包括自解析的,比如本博客的域名为xiebruce.top
或www.xiebruce.top
,有www的,可以用*.xiebruce.top
通配符证书,但没有www的是无法使用通配符证书的,因为即使*
是空,那也只能匹配.xiebruce.top
,最前面多了一个点,所以无法匹配。
所以我们需要给通配符证书同时设置两个域名(一个证书是可以设置多个域名的),一个当然就是通配域名*.xiebruce.top
,另一个就是不包括在通配域名中的xiebruce.top
。
获取https证书的方法
获取数字证书一般都是用ACME(Automatic Certificate Management Environment )自动证书管理环境工具来获取,这样的工具有多种,比如:
- certbot
- certbot-auto
- acme.sh
- certbot-letencrypt-wildcardcertificates-alydns-au
鉴于大部分情况下都需要使用通配符证书,所以前面两个并不合适(无法自动更新通配符证书),如果是阿里云买的域名或国外买的域名,可以用第三个acme.sh
,最后一个可用于阿里、腾讯云、GoDaddy的域名,因为我的是阿里云买的域名,我这里使用第三个,即acme.sh
(后面两个工具都是国人写的)。
安装ssl证书获取工具(acme.sh)
acme.sh的github最初是https://github.com/Neilpang/acme.sh,但现在它会自动跳转到https://github.com/acmesh-official/acme.sh,好像是“Neilpang”加入了官方开发组。
安装acme.sh:
curl https://get.acme.sh | sh
安装.acme.sh会自动安装到~/.acme.sh
目录中(注意它是一个目录,不是单个文件),也就是说,如果你是用root用户安装,那么会安装到/root/.acme.sh
目录中,如果是用普通用户,比如你的用户名是zhangsan
,那么它将会被安装到/home/zhangsan/.acme.sh
目录中。
安装中出现的这三句红色的提示不用管它:
[2019年 02月 15日 星期五 01:04:08 CST] It is recommended to install socat first.
[2019年 02月 15日 星期五 01:04:08 CST] We use socat for standalone server if you use standalone mode.
[2019年 02月 15日 星期五 01:04:08 CST] If you don't use standalone mode, just ignore this warning.
安装完它会自动在.bashrc
或.zshrc
的最后添加以下命令(这是添加环境变量,这样你就可以直接使用acme.sh
命令了):
. "/home/xiebruce/.acme.sh/acme.sh.env"
你只要source一下就可以使用了,如果你用的是bash:
source ~/.bashrc
如果你使用的是zsh:
source ~/.zshrc
source之后,试一下(如果正常,则会出来帮助选项):
acme.sh -h
获取通配符证书
阿里云中获取证书:
先从阿里云中获取“AccessKey ID”和“Access Key Secret”:https://ak-console.aliyun.com/#/accesskey。
在你的~/.bashrc
或.zshrc
文件中添加阿里云的“AccessKey ID”和“Access Key Secret”(添加后source一下,跟前面一样,不再赘述):
export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"
然后获取*.xiebruce.top
的通配符证书,注意要加上xiebruce.top
,而且要它放第一个(否则生成的证书目录名会被命名成有*号的那个,目录名有*号不太好),因为它是无法匹配通配符证书的:
acme.sh --issue --dns dns_ali -d xiebruce.top -d '*.xiebruce.top'
另外,它会等待120秒(这个时间以后有可能会改,而且可以手动用--dnssleep xx
来指定,xx是整数,代表等待多少秒),原因是要等阿里云的txt记录解析生效,其实不需要这么久,不过为了保证成功率,还是等久一点好。
注意,如果是namesilo,因为它是每15分钟(900秒)向外同步一次,所以我们要设置--dnssleep=910
,超过900,这样容易让它识别到添加的txt记录
acme.sh --issue --dns dns_namesilo --dnssleep 910 -d xiebruce.top -d '*.xiebruce.top'
其它平台的具体可以看这里dnsapi。
从CloudFlare获取证书:
点击CloudFlare的右上角头像→点击下拉菜单中的My Profile
,滚到差不多到底部,你就可以看到一个“Global API Key”和一个“Origin CA Key”,“Global API Key”就是我们要的Key:
在你的~/.bashrc
或.zshrc
文件中添加CloudFlare的这两个变量(任何位置都行):
export CF_Email="[email protected]"
export CF_Key="85302dsiorw3oisjdkf899234sdf72dfdb46"
然后命令是一样的,只不过--dns
指定的api为dns_cf
(查看~/.acme.sh/dnsapi/
目录,里面有所有支持的api):
acme.sh --issue --dns dns_cf -d xiebruce.top -d '*.xiebruce.top'
至于为什么阿里云要的是Ali_Key
和Ali_Secret
,而CloudFlare要的是CF_Email
和CF_Key
?查看~/.acme.sh/dnsapi/
下的api文件,打开对应的文件,比如阿里的就是dns_ali.sh
,CloudFlare的就是dns_cf.sh
,打开文件自然能看到里面需要什么变量。
安装证书
上边的获取证书,是放到了~/.acme.sh
目录中的(实际上是在该目录中生成了一个xiebruce.top
文件夹,文件夹里就是获取到的证书):
理论上我们在nginx中引用它即可,实际上也可以,但最好不要直接引用它,而是先把它拷贝到另一个目录中比如nginx要用就拷贝到nginx目录中,或者你喜欢放在/etc
下或/usr/local/etc
下也行,我是放到了nginx的目录中,但不需要自己手动拷贝,直接用以下命令:
acme.sh --install-cert -d 'xiebruce.top' \
--key-file /usr/local/nginx/letsencrypt/private.pem \
--fullchain-file /usr/local/nginx/letsencrypt/fullchain.pem \
--reloadcmd "nginx -s reload"
解析:
--install-cert
:表示安装证书,其实就是把证书文件拷贝到指定目录。
-d
:指定拷贝哪个域名的证书,不过由于我们获取的时候,写了两个域名,一个是xiebruce.top
,一个是通配*.xiebruce.top
,写哪个好呢?就写xiebruce.top
,因为生成的文件夹名字是xiebruce.top
。
--key-file
:指定证书私钥(本例是xiebruce.top.key
文件)的目标路径(即指定要拷到哪里,从哪里拷不用指定,因为肯定是在acme.sh
的工作目录中,该工具会自动去找的)。
--fullchain-file
:fullchain是所有证书文件,该选项指定拷贝fullchain.cer
文件到哪里。
--reloadcmd
:重载的命令,因为证书改变后,nginx如果不重新加载配置,新证书是不会生效的。
注意:要保证--key-file
和--fullchain-file
指向的目录存在,如果不存在,则要先创建,否则拷贝失败,比如我是用的openresty所以我放在以下目录,你自己的可以看情况,你自己喜欢放哪就放哪:
mkdir /usr/local/openresty/nginx/letsencrypt
自动续订(renew)
把以下命令加入到定时任务中即可实现证书过期时自动续订证书(事实上安装的时候已经自动帮你加了,所以你不用手动加了):
0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" >> /var/log/acme.sh-auto-renew.log
解析:
0 0 * * *
:表示每天的0点执行一次。
/root/.acme.sh/acme.sh --cron
:其实就是acme.sh --cron
,只不过在定时任务中要把acme.sh
的绝对路径写出来,该命令会把你所有的证书都renew一遍,并且会自动install并reload nginx,也就是说,renew获取到新证书后,它会自动执行前面的安装命令最后会执行reloadcmd
指定的重载nginx的命令。有人可能会有疑问,这样是不是nginx每天都会重载一次?不会的,你单独执行一下acme.sh --cron
命令看看结果:
[2019年 02月 15日 星期五 00:40:43 CST] ===Starting cron===
[2019年 02月 15日 星期五 00:40:43 CST] Renew: 'xiebruce.top'
[2019年 02月 15日 星期五 00:40:43 CST] Skip, Next renewal time is: 2019年 04月 15日 星期一 15:45:22 UTC
[2019年 02月 15日 星期五 00:40:43 CST] Add '--force' to force to renew.
[2019年 02月 15日 星期五 00:40:43 CST] Skipped xiebruce.top
[2019年 02月 15日 星期五 00:40:43 CST] ===End cron===
看到其中的“Skip, Next renewal time is”了吗?没有到续订日期,它会跳过,而且还给出下次续订的日期,所以只有到了续订日期,才会真正续订并reload nginx,否则相当于没有执行。
--home "/root/.acme.sh"
:这个是指定acme.sh
的工具目录,其实不指定应该也是可以的。
>> /var/log/acme.sh-auto-renew.log
把前面命令执行输出的结果存到指定的日期文件中。
多台机同一个网站问题
一般情况下都会在负载均衡那台机做一个就够了,不需要每台机都做,如果要多台机做,那就用一台机来更新,然后同步到其他机器。
使用证书
本文主要讲如何使用acme.sh
安装证书以及自动续订证书,至于获取到证书以后如何使用,请参考:为你的网站配置免费的HTTPS支持,主要就是在nginx中引用两个证书文件。

