Certbot是一个开源工具,它是由Let's Encrypt提供的官方客户端,用于自动化获取、更新和安装Let's Encrypt证书。 优点:免费。 缺点:证书非永久,需要定期更新
申请证书
docker run --rm -it \
-e TZ=Asia/Shanghai \
-v "${PWD}/certs/:/etc/letsencrypt/" \
-v "${PWD}/logs/:/var/log/letsencrypt/" \
-p 18080:80 \
certbot/certbot certonly --standalone -d <需要申请证书的域名,如:smpt.example.com>
原理
当certbot程序运行后,letsencrypt服务器会访问目标域名的80端口(因为此时没有证书,只能访问80端口),访问路径为
"GET /.well-known/acme-challenge/YqE1g3IcgPC3PwIK7ZxNJdiU5nQimQrx6PsK8yAbvfI HTTP/1.1" 200 98 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" "-"
服务器接收到GET请求后,被nginx转发到本机的18080端口,18080端口刚好又映射了certbot容器的80端口,然后certbot程序会去完成这个acme-challenge,完成后letencrypt服务器会向访问的域名颁发证书,30天之后过期,需要再次续订
参数说明
${PWD}/certs
生成的证书会保存在这个文件夹${PWD}/logs
日志文件-p 18080:80
将certbot的80端口映射到服务器的非80端口,并用nginx进行转发,避免出现端口被占用的问题
nginx转发
server {
listen 80;
server_name [需要申请https证书的域名];
location / {
proxy_pass http://localhost:18080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
证书自动续订
为刚才申请到的证书文件夹${PWD}/certs/
赋予可读权限
chmod -R a+r certs/
把certs目录挂载到nginx容器中
-v /home/docker/dms/certbot/certs/:/etc/certs
申请证书只需要80端口,但是证书的续订要用到443端口,将443端口转发到certbot容器中
server {
listen 443 ssl http2;
server_name <申请证书的域名>;
# 证书的挂载的路径
ssl_certificate /etc/certs/live/域名/fullchain.pem;
ssl_certificate_key /etc/certs/live/域名/privkey.pem;
location / {
# 在这里,14443端口是certbot容器443端口的映射
proxy_pass http://localhost:14443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
创建一个certbot-renew.sh脚本
# 删除之前的logs文件夹,避免log文件夹无限制递增
rm -rf logs
docker run --rm -i \
-e TZ=Asia/Shanghai \
-v "${PWD}/certs/:/etc/letsencrypt/" \
-v "${PWD}/logs/:/var/log/letsencrypt/" \
-p 18080:80 \
-p 14443:443 \
certbot/certbot renew
(自己先试着运行一下这个脚本)
❗注意:crontab运行docker命令时,docker run后面不能加
-t
参数,会报错“the input device is not a TTY”
最后,在你的服务器上,添加一条crontab任务,脚本要写成绝对路径,配置好之后保存退出, 输入crontab -l
检查crontab是否配置成功
# 每天0点执行一次certbot-renew.sh
0 0 * * * cd [脚本所在目录] && /bin/bash start-certbot-renew.sh
总结
经过上面一折腾,域名的https证书就搞定了,保存在${PWD}/certs/目录下,其他docker容器挂载一下就能用