本文基于ACME v2规则,使用 lego 的CLI模式 chanllenge HTTP-01。除了使用lego,还有更多的ACME客户端供选择噢。
为了在您的网站上启用HTTPS,您需要从证书颁发机构(CA)获取证书。Let’s Encrypt 是一个证书颁发机构(CA)。要从 Let’s Encrypt 获取您网站域名的证书,您必须证明您对域名的实际控制权。您可以在您的 Web 主机上运行使用 ACME 协议的软件来获取 Let’s Encrypt 证书。
https://letsencrypt.org/zh-cn/getting-started/
docker安装Lego
docker run goacme/lego -h
如果不想用Docker方式运行lego,官方手册还提及到其他安装方式。
Nginx配置
server {
listen 80;
server_name example.com;
location /.well-known/acme-challenge { # lego ACME文件验证服务转发
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
}
给需要申请证书的域名(或子域名)server块 中添加/.well-known/acme-challenge
规则,NGINX会将该路径的访问请求转发给lego。
订购证书
创建用于存储证书的路径,这里我用/var/www/letsencrypt。
mkdir -p /var/www/letsencrypt
<span class="hljs-comment"># 申请证书docker run \-v /var/www/letsencrypt:/.lego/certificates/ \-p 81:81 \goacme/lego \--email="mail@gmail.com" \--domains="api.example.com" \--domains="example.com" \--http --http.port :81 \--accept-tos run</span>
当执行这条lego命令时,我们指定81端口为生成ACME文件的服务器,在NGINX的配置中实现了路径访问的服务转发。由此,当Let’s Encrypt服务器回应我们的请求后,会访问例如http://example.com/.well-known/acme-challenge/Rd9xe0xPPocVFcUgp0vH5IIU8KGC3R_DK2BOMBHZGlI
这样的路径来验证网站的服务器是否真实且拥有实际的控制权。
参数说明
- –email 站长的Email,可以不存在。email被视作ACME账户。
- –accept-tos 同意TOS规则,在执行run命令时必须同意(携带)。
- –http 使用HTTP-01 challenge。
- –http.port 创建ACME文件服务器,并listen 81端口的请求。
- –domains 可以指定一到多个域名同时申请证书。实际上这个地方有bug(lego v4.0.1),一条命令虽然响应了多个域名的申请,但是最终只会生成一个域名的证书(见上方的“执行结果”一图)。如果需要生成多个域名的证书,需要执行多次此命令。
速率限制
要知道Let’s Encrypt是有速率限制的,如果你正在调试lego或者其他ACME的客户端,请使用测试环境而不是生产环境的 API。
Let’s Encrypt 对证书颁发进行速率限制以确保尽可能多的人能合理使用我们的服务。我们相信这些速率限制在大多数情况下足以满足用户的需求。同时续期证书几乎不受速率限制的影响,所以大型组织可以逐步增加他们可以发布的证书数量,而无需Let’s Encrypt的干预。
我们要注意的限制有这些:
- 每个注册域名每周最多可申请50份证书
- 每个账户每小时每域名有最多验证失败 5 次的限制
- 每个IP地址每3小时最多可以创建10个账户
- 每个账户最多可以有300个待验证授权
更新Nginx配置
证书生成后会出现在/var/www/letsencrypt/certificates/
下,根据申请时的–domains命名。接下来在Nginx配置中增加443监听:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /var/www/letsencrypt/certificates/example.com.crt;
ssl_certificate_key /var/www/letsencrypt/certificates/example.com.key;
ssl_protocols TLSv1 TLSv1.2;
}
执行nginx-T
检查下配置书写是否正确,最后别忘了让nginx重新加载配置:
service nginx reload
续约证书
Let’s Encrypt证书有效期为90天(3个月),之后需要使用renew
命令申请续约。这个命令所需要带的参数跟lego run一样。
docker run \
-v /var/www/letsencrypt:/.lego/certificates/ \
-p 81:81 \
goacme/lego \
--email="mail@example.com" \
--domains="example.com" \
--http --http.port :81
renew --days 90
renew后的证书文件会变,nginx需要重新加载,执行srevice nginx reload
。
我们可以将这个任务交给cron,让它每隔3个月(也就是每4个月执行一次)执行一次。
创建一个.sh文件(我存放在 /home/acme.sh
),保存如下内容:
<span class="token shebang important">#!/bin/bash</span>
<span class="token shebang important">source</span> /etc/profile/usr/bin/docker run -v /var/www/letsencrypt:/.lego/certificates/ -p 81:81 goacme/lego --email<span class="token operator">="admin@example.com"</span> --domains<span class="token operator">="example.com"</span> --http --http.port :81 renew --days 90 <span class="token operator">></span> /home/crontab_logs/acme.log
service nginx reload
执行crontab -e
编辑当前用户的计划任务。
0 0 1 */4 * /bin/bash /home/acme.sh
如果加了sudo那么计划任务挂在root用户下,建议统一由一个用户管理计划任务。