自从 Let's Encrypt 支持泛域名之后,为网站设置https就变得非常简单了。之前需要维护多个子域名的证书更新,操作起来也是很麻烦的。
因为最近我的 gogit.itfanr.cc 的https证书到期,所以就研究了一下泛域名的申请过程,想要将我所有 itfanr.cc 下的二级域名都设置成https的请求方式。
目前比较常用的为 Let's Encrypt 生成证书的工具比较多,比如 certbot 和 acme.sh 是我之前接触过的两款。这里我要使用 acme.sh 这个工具来安装 Let's Encrypt 证书。
acme.sh
acme.sh 是由国人利用 shell 脚本开发的,兼容各种 Linux 系统。仅仅依赖 curl。 acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书。
acme.sh 支持 --webroot, --standalone, --apache, --nginx and --dns 5种证书申请模式。
安装
可以直接通过下面的脚本来安装 acme.sh:
1 | curl https://get.acme.sh | sh |
安装过程不会污染已有的系统任何功能和文件,acme.sh 会被自动安装到 ~/.acme.sh/ 中。
并且,还默认创建一个 bash 的 alias, 方便你的使用: alias acme.sh=~/.acme.sh/acme.sh 。
此外,acme.sh 还自动创建了 cronjob任务, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书.
单域名申请
当你只想要为一个域名设置 https 时,可以使用 --standalone 模式来申请。
比如我之前在为 gogit.itfanr.cc 设置时,我的网站程序是跑在Docker容器下的,外面用 Nginx 来做跳转。
首先,我需要先将占用 80 端口的 Nginx 服务停掉,然后再设置:
1 | $ sudo service nginx stop |
然后,生成https证书:
1 | $ acme.sh --issue -d gogit.itfanr.cc --standalone |
其中,gogit.itfanr.cc 请换成自己的站点域名。
Standalone 模式默认使用的是 80 端口,如果你的 80 端口无法使用的话,也可以指定相应的端口:
1 | $ acme.sh --issue -d gogit.itfanr.cc --standalone --httpport 88 |
获取AccessKeys
因为我要将 itfanr.cc 域名下所有的二级域名都设置成 https ,那么上面一个域名一个域名的设置方法就不行了。
泛域名就是类似于 *.example.com 这样的域名。
acme.sh 目前支持数十种域名解析商的API,可以自动添加 TXT 记录来验证。
这里我以阿里云DNS为例,其他支持的域名验证方式,可以查看这里了解 以及相应的设置方法
acme.sh 访问阿里云 DNS 是通过阿里云 DNS 公开的 API 以及用户的 AccessKeys 来进行交互的。
为了保证安全,阿里云 AccessKeys 是使用 阿里云子账户 来添加的。
登录 [阿里云管理控制台](https://home.console.aliyun.com/) – 点击头像中的 accesskeys – 选择 开始使用子用户AccessKeys {或者直接点击该网址} – 设置 用户名 – 选择权限中输入“DNS”,选择 AliyunDNSFullAccess(管理员解析(DNS)的权限) 这项 – 之后子账户和AK都创建成功了。


AliyunDNSFullAccess 表示 “管理员解析(DNS)的权限”,既该账户就有了添加DNS记录和删除DNS记录的权限,但没有其他权限。
一定要在这一步记录下这个 AccessKey 信息,之后就无法看到了。
添加配置
在 bash 中执行如下命令,将参数添加到环境变量中:
1 | export Ali_Key="AccessKeyId" |
注意,这里的 Ali_Key 和 Ali_Secret 是和你所使用的域名提供商一一对应的。具体的可在这里查找:相应的设置方法
另外,这个临时环境变量只需配置这一次,当成功申请证书后,API信息会被自动保存在 ~/.acme.sh/account.conf ,下次你使用 acme.sh 的时候会被自动使用。
生成泛域名证书
接下来正式开始申请泛域名证书,将 example.com 换成你自己的域名:
1 | $ acme.sh --issue --dns dns_ali -d example.com -d '*.example.com' |
申请完成后可以在 ~/.acme.sh/example.com 下看到证书文件:
证书文件是 fullchain.cer
密钥文件是 example.com.key
证书续期
Let’s Encrypt 证书的有效期为三个月,acme.sh会每隔60天自动帮你续期。在以上命令执行后,会在 crontab 里添加计划,通过命令查看:
1 | $ crontab -l |
将证书配置到Nginx
放在 ~/.acme.sh/example.com 目录下的证书文件不能直接拿来使用,需要拷贝到一个自定义的目录下,再配置到Nginx中才能正常的使用。
Docker使用acme.sh
上面的方法安装起来虽说已经很简单了,但是对于像我这种但凡能用Docker来解决的问题绝对不用其他方式。
获取镜像
1 | $ docker pull neilpang/acme.sh |
创建acme.sh证书保存目录
1 | $ mkdir /etc/acme.sh |
运行 acme.sh 容器
这里依然需要从域名服务商处获得的ID和Secret:
1 | $ docker run --rm \ |
注意这里第一个域名为顶级域名,后面一个为泛域名。
这种方式将自动为你的域名添加一条 txt 解析,验证成功后,这条解析记录会被删除,所以对你来说是无感的,就是要等待 120 秒。
证书生成成功后,默认保存在 .acme.sh/example.com 中。
容器化自动续期
可以以后台进程的方式运行一个容器:
1 | $ docker run --name acme.sh \ |
这样,acme.sh 证书到60天就会自动更新。
注意事项
当我按照如上方法生成域名证书时,执行命令:
1 | $ docker run --rm \ |
发现会提示如下错误:
1 | ➜ acme.sh docker run --rm \ |
经查证,其中的泛域名 *.example.com 中由于带有 * 号,会报错。相应的解决方法是添加引号:-d '*.example.com'
我的操作记录
创建本地证书保存目录:
1 | $ mkdir /etc/acme.sh |
执行:
1 | ➜ acme.sh docker run --rm \ |
发现,当最后一行提示信息为 Sleep 120 seconds for the txt records to take effect 时,说明正在自动执行DNS绑定的操作。
当日志继续输出时,可以看到最后提示执行成功了 Cert success.:
1 | [Tue Sep 18 15:11:32 UTC 2018] Sleep 120 seconds for the txt records to take effect |
查看 /etc/acme.sh 目录下:
1 | ➜ acme.sh ls |
其中, 证书文件是 fullchain.cer ,密钥文件是 itfanr.cc.key 。
配置Nginx
在域名的nginx配置文件中新增证书配置,例如我的 gogit.itfanr.cc 域名的配置文件 gogit.conf 如下:
1 | server { |
然后更新nginx,重新载入配置:
1 | $ sudo nginx -s reload |
在浏览器中访问域名,可以看到地址栏中的小绿锁已经出现了。
