本文链接:用acme_tiny自动获得Let’s Encrypt的证书
从今年7月开始,Chrome会将所有HTTP网站标记为“不安全”。这对站长来说是件有点难过的事情,因为要费心去配置证书,不然在别人看来,你就是个不安全的网站(其实即使是HTTP明文也未必会不安全,网站还是能够做加密)。买证书是个肉疼的事情,又多了一笔开销。幸好还有免费的证书可以使,那就是Let’s Encrypt,真是良心。可惜这个站申请的证书只有3个月的期限,要是手动更新还不得麻烦死。又幸好这个站支持ACME协议,可以使用REST API完成证书申请。所以只要找找脚本,就可以自动申请证书了。
在Let’s Enctypt的这个页面列出了许多可以使用的ACME客户端,我选用了acme_tiny,因为它是开源的,只有一个python文件,而且文档也比较简明。基本上看README就可以完成取得证书的方式了。
首先是生成一个account key,用来表示用户,可以为每个网站都生成一个,也可以共用同一个。这个文件很重要,最好有备份,因为必须通过个这account key才能访问和更改和你域名相关的证书:
1 |
openssl genrsa 4096 > account.key |
然后要为网站生成密钥:
1 |
openssl genrsa 4096 > domain.key |
生成证书申请文件(将yoursite.com
换成你的域名):
1 |
openssl req -new -sha256 -key domain.key -subj "/CN=yoursite.com" > domain.csr |
因为Let’s Encrypt要验证你有这个网站,你需要在网站的特定目录下放置特定文件,放置文件这件事acme_tiny会帮你做,但你需要创建一个放置文件的目录,并且更改服务器的配置,这里以nginx为例。也可以直接将这个目录放置在网站目录之下,这样就不用更改服务器配置了
1 2 |
# 这个目录的位置随意,和服务器配置对应就行 mkdir -p /var/www/challenges/ |
1 2 3 4 5 6 7 8 9 10 11 12 |
# nginx配置 server { listen 80; server_name yoursite.com; location /.well-known/acme-challenge/ { alias /var/www/challenges/; try_files $uri =404; } # 其他配置... } |
运行acme_tiny,得到证书:
1 |
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed_chain.crt |
更改服务器配置,启用证书,还是以nginx为例:
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 443 ssl; server_name yoursite.com, www.yoursite.com; ssl_certificate /path/to/signed_chain.crt; ssl_certificate_key /path/to/domain.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA; ssl_session_cache shared:SSL:50m; ssl_dhparam /path/to/server.dhparam; ssl_prefer_server_ciphers on; # 其他配置 } server { listen 80; server_name yoursite.com, www.yoursite.com; location /.well-known/acme-challenge/ { alias /var/www/challenges/; try_files $uri =404; } location / { return 301 https://$server_name$request_uri; } } |
再打开网站,就会发现它能够跳转到HTTPS并且变成“安全”的了。
为了能自动更新证书,编写脚本renew.sh
:
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 |
#!/bin/sh PATH=$1 DOMAIN=$2 if [ "$PATH" = "" -o "$DOMAIN" = "" ]; then echo "usage $0 <path> <domain>" exit 1 fi echo "Gen domain.key" openssl genrsa 4096 > $PATH/domain.key echo "Gen domain.csr" openssl req -new -sha256 -key $PATH/domain.key -subj "/CN=$DOMAIN" > $PATH/domain.csr echo "Send request" python /path/to/acme_tiny.py --account-key $PATH/account.key --csr $PATH/domain.csr --acme-dir /var/www/challenges/ > $PATH/signed_chain.crt || exit echo "Reload nginx" service nginx reload |
然后使用crontab之类的工具设置计划任务:
1 |
sudo crontab -e |
1 2 |
# m h dom mon dow command 0 0 1 */2 * /path/to/renew.sh /path/to/keys yoursite.com 2>> /var/log/acme_tiny.log |
这样就可以每两个月自动更新证书了,完美。