五年前Let‘s Encrypt还不支持泛域名证书,我这个懒人为了省事,一下子买了五年的wildcard证书。截止到2020年7月22日,Let’s Encrypt已经有近六千四百万活跃的域名,有一亿三千六百万个证书,每天签发近一百五十万次。最重要的是证书全部是免费的,经过这几年的发展,Let‘s encrypt已经是目前互联网最重要的组织之一。而且周边和教程都已经非常成熟了,客户端就有几十种。我的网站要求就两点,一是能支持签发和续签widlcard证书,第二就是要使用简单,最终综合比较了一下选择了Lego。

Lego是Go语言写的,使用之前要先安装GoLang。

一、安装GoLang
从官网下载go语言相应版本的客户端,解压安装即可,需要注意以下两点:

  1. Linux系统下不要安装多个版本的GO
  2. 需要正确设置GOROOT和环境变量。

不然编译lego会有很多错误,例如go的解压后的目录在/usr/local/go,设置如下:

export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin/

将这两条设置放到profile或者bash_profile中即可,和JDK设置类似,这里不需要多说。

二、编译Lego
编译就比较简单了,两条命令即可:

git clone https://github.com/go-acme/lego
cd lego && make build

等待执行完,编译好的文件在dist目录下,复制到PATH里就可以直接用了。

三、签发和续签证书
使用超级简单,签发和续签一条命令即可。泛域名证书只能通过dns验证,需要域名NS的api key,具体支持的ns厂商可以通过:

lego dnshelp

查看需要设置的参数:

lego dnshelp -c dnspod

签发需要先设置api,dnspod完整的API Token是由 ID,Token 组合而成,用英文的逗号分割:

export DNSPOD_API_KEY="ID_xxxx,Token_xxxxxx"
export DNSPOD_HTTP_TIMEOUT="300"

签发:

lego --email="will@nixops.me" --domains="nixops.me" --domains="*.nixops.me" --accept-tos --path=/tmp/lego/ --dns="dnspod"  --dns.resolvers="8.8.8.8" run

--run-hook: 签发成功后执行的命令或脚本

续签:

lego --email="will@nixops.me" --domains="nixops.me" --domains="*.nixops.me" --accept-tos --path=/tmp/lego --dns="dnspod" renew --reuse-key 

--reuse-key: 不重新生成私钥
--renew-hook: 续签成功后执行的命令或脚本,如替换证书,reload服务
--days: 可以指定提前续期的天数

四、自动签发和续签脚本

#!/bin/bash

lego_bin=/root/lego/lego
save_path=/usr/local/keys/
account_email="will@nixops.me"

export DNSPOD_API_KEY="ID_xxxx,Token_xxxxxx"
export DNSPOD_HTTP_TIMEOUT="300"


case $1 in

run)
    $lego_bin --email="$account_email" --domains="*.$2" --domains="$2" --accept-tos --path=$save_path --dns="dnspod"  --dns.resolvers="1.1.1.1" run --run-hook="`readlink -f $0` reload"  >>/var/log/letencrypt.log
;;

renew)
    for domain in `$lego_bin  --path=$save_path list -n` ; do
    $lego_bin --email="$account_email" --domains="*.$domain" --domains="$domain" --accept-tos --path=$save_path --dns="dnspod" renew --reuse-key --renew-hook="`readlink -f $0` reload" >>/var/log/letencrypt.log 
done
;;

reload)
    cp -f $save_path/certificates/*.crt /usr/local/openresty/nginx/conf/vhosts/keys/
    cp -f $save_path/certificates/*.key /usr/local/openresty/nginx/conf/vhosts/keys/
    rm -rf /usr/local/openresty/nginx/conf/vhosts/keys/*.issuer.crt
    /usr/local/openresty/bin/openresty -s reload
   ;;

*)
   echo "黙认签发泛域名证书,只写根域名即可"
   echo "证书保存在 $save_path"
   echo "用法: 1. 签发证书 $0 run nixops.me"
   echo "用法: 2. 续签证书 $0 renew "
   echo "用法: 3. 复制证书,reload服务 $0 reload"
   
;;
esac

将以上脚本加入crontab中,每天执行一次renew:

crontab -e
15 3  * * * /usr/local/bin/ssl.sh renew nixops.me >>/dev/null 2>&1

最后不得不说,DNSPOD、namesilo的ns太渣了,默认解析TTL太长导致dns验证的签发和续签都太慢,失败太常见了,成功才是偶然。付费的ns一般都比较稳定,例如aws的router53能在2分钟内签发完成,免费ns测试cloudflare不错,其它的没有测试过。