dahege 2020-05-31
网络上已经有很多关于Let‘s encrypt
免费申请证书的文章,但是基本只谈最基础用法,立刻用起来是没问题了。但是在实际使用中,碰到了一些问题则比较头疼。整理以后,大概出在以下几个方面:
本文的价值在于阐述了解决这些问题的具体思路。
申请Let‘s encrypt
证书,既可以使用certbot
官方工具,也可以使用acme.sh
第三方工具,各有各的好处,主要看偏好,本文使用certbot
演示。
安装指南 :直接进《certbot官方安装指南》,选择nginx和自己的操作系统,就会生成对应的安装指南。
在给域名申请证书时,Let‘s encrypt
需要先验证你有对域名的控制权。这个验证方式有2种:文件验证和DNS验证。
文件验证的原理是在你的网站下面放一个验证文件(/.well-known/acme-challenge/
目录下),certbot
通过域名直接访问到这个验证文件,能访问到说明是你的网站,也就可以申请证书。
DNS验证的原理是你需要创建一条TXT
的记录,设置指定值,certbot
检查到这条记录就完成验证。
两种方式各有其适用场景,对于自己可以控制的域名,直接通过DNS
验证是最便捷的,不需要任何nginx
的辅助就可以完成申请和续期。但是很多时候,我们是给客户提供服务,并没有域名的控制权,就只能使用文件验证的方式。假如使用了DNS
的验证方式,客户首次申请是要手动改DNS
记录,等到过期后,也不能自动续期,需要再次手动调整DNS
记录。
为保证域名正常续期,本文的单域名证书的申请上,使用的是文件验证的方式。
对于单域名,我们统一使用文件验证的方式,因此要先写好nginx
的配置文件:
server { listen 80; server_name www.papamk.com; root /var/www/html; server_tokens off; location /.well-known/acme-challenge/ { root /var/www/html; access_log off; } return 301 https://www.papamk.com$request_uri; }
访问curl http://www.papamk.com
将会返回如下结果:
<html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx</center> </body> </html>
接着开始申请证书:
certbot certonly --webroot -w /var/www/html -d www.papamk.com
编辑nginx
配置文件,给HTTPS
增加证书的相关配置,重点是以下2名:
ssl_certificate /etc/letsencrypt/live/www.papamk.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.papamk.com/privkey.pem;
完整的nginx
配置如下:
server { listen 443 ssl; server_name www.papamk.com; root /var/www/html; index index.php index.html index.htm; access_log /dev/stdout; error_log /dev/stderr; ssl_certificate /etc/letsencrypt/live/portfolia.papamk.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/portfolia.papamk.com/privkey.pem; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { internal; try_files $uri /index.php =404; fastcgi_intercept_errors on; fastcgi_pass php-fpm:9000; fastcgi_index index.php; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
以上配置使用
php
作为示例。
certbot renew --deploy-hook ‘nginx -s reload‘
当证书在30天内过期时,就会自动更新,更新成功会重新加载nginx
。
放在crontab中,每天凌晨1点更新。
0 1 * * * certbot renew --deploy-hook ‘nginx -s reload‘
泛域名证书只支持DNS验证的方式,所以如果不能直接修改DNS记录,泛域名证书过期后就会需要手动更新。要解决这个问题,需要使用对应的DNS插件,国外的主流DNS插件都有内置支持,如果是国内。我基本都使用阿里云,官方certbot
没有对应的DNS插件,但是第三方有,传送门:
https://github.com/tengattack/certbot-dns-aliyun
pip install certbot-dns-aliyun
创建aliyun.ini
,写入授权信息(授权账号需要有AliyunDNSFullAccess
)
certbot_dns_aliyun:dns_aliyun_access_key = 12345678 certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef
修改下权限:
chmod 600 aliyun.ini
接下来就可以开始使用了。
certbot certonly -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini -d ‘*.yourdomain.com‘ --server https://acme-v02.api.letsencrypt.org/directory
certbot renew -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini --server https://acme-v02.api.letsencrypt.org/directory --deploy-hook ‘nginx -s reload‘
放到crontab
每天自动检查:
0 1 * * * certbot renew -a certbot-dns-aliyun:dns-aliyun --certbot-dns-aliyun:dns-aliyun-credentials aliyun.ini --server https://acme-v02.api.letsencrypt.org/directory --deploy-hook ‘nginx -s reload‘
这里的每天检查与单域名的每日检查2选1即可。
证书一般存放在如下路径:/etc/letsencrypt/live/
。
每个域名一个文件夹,可以看到www.yourdomain.com
的目录。
先进浏览器,看下当前证书的过期时间,然后执行强制更新:
certbot renew --force-renew --deploy-hook ‘nginx -s reload‘
再次进浏览器,查看当前证书的过期时间,如果日期有变,说明nginx
重新加载了。
certbot renew
会对30天
以内的证书更新,只要保证cron
有执行每天定时更新一次就没问题。第一次使用时,证书在30以内要注意下这个问题,确保它们得到了更新。
根据文件验证的原理,certbot
无法访问到你的内网,也就验证不通过。使用DNS
验证可以申请成功。
在许多文章中,都是通过volume
将主机的/etc/letsencrypt
挂载到容器中,但是在生产环境时,由于应用变成了有状态应用,这种方式有很大的局限性。从A机器迁移到B机器时,将会立刻报错,必须手动解决完证书问题。推荐的做法是将证书做成动态获取的,具体来说要考虑以下2个方面:
vault
),nginx
镜像在启动的时候,从vault
获取证书。如果获取不到,但是证书又是必要的,就生成证书,同步到vault
,以便镜像重启时可以获取。这个方案的技术细节可参考该文:https://developer.epages.com/blog/tech-stories/managing-lets-encrypt-certificates-in-vault/这些处理完全可以做成一个新的nginx
镜像以便重复使用。具体的镜像如何处理将另开文章讨论。
pip install certbot-dns-aliyun
执行上面命令时报出下面的错误:
解决方法:
pip install --user --upgrade setuptools