实现原理
本质上还是通过 certbot 通过脚本方式向 Let’s Encrypt 机构颁发和更新 SSL/TLS 证书。单个域名和通配符的区别是: 前者通过 nginx 的配置 location 规则来,通配符需要通过设置 dns 在域名上添加 txt 规则来验证。
具体操作
实验操作环境为 centos7
1.下载 certbot
yum update -y
yum install certbot -y
2.申请 RSA 通配符证书命令
certbot -d XXX.com -d *.XXX.com --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory certonly --agree-tos --register-unsafely-without-email
这里可以只写子域名,如果像包括根域名可以使用-d 也加上。如果一个-d 只需要配置一个 txt 规则,如果是 2 个-d 配置 2 个 txt 规则。解释
--register-unsafely-without-email : 跳过邮箱验证
3.添加 txt 规则
上面的命令输出完完后,会有 txt 记录,
在阿里云或者自己的域名服务器上配置下。进入自己域名的 DNS 记录管理页面,增加两条 TXT 记录,多数情况下,仅需在域名(Name)处填入 _acme-challenge,在内容(Target)处填入上一步 Certbot 生成的内容即可(记得填写两个,多个文本记录之间以换行符(Enter 键)分隔),不同 DNS 提供商处可能会略有不同,根据实际情况修改:
当查看 TXT 记录解析成功后,回到申请证书的 Press Enter to Continue 处,直接回车。成功会有下面的提示:
配置文件下在/etc/letsencrypt/live/xxx.com/里面:
说明证书已颁发成功。
3. 在 nginx 配置证书
下面是一个 nginx 应用该证书的一个例子
server {
server_name xxx.com;
listen 443 http2 ssl;
ssl on;
ssl_certificate /etc/cert/xxx.com/fullchain.pem;
ssl_certificate_key /etc/cert/xxx.com/privkey.pem;
ssl_trusted_certificate /etc/cert/xxx.com/chain.pem;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
因为我的 nginx 是用 docker 部署的,这里略有不同,需要使用容器卷,地址写 nginx 容器内的路径。我这里随便找个子域名测试下:
#a
server {
listen 80;
listen [::]:80;
server_name a.xxx.com www.a.xxx.com;
server_tokens off;
gzip on;
gzip_static on;
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
location / {
return 301 https://a.xxx.com$request_uri;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 处理 https 请求
server {
listen 443 ssl;
server_name a.xxx.com;
server_tokens off;
# /etc/letsencrypt/live/xxx.com/fullchain.pem; 路径根据自己的实际情况填写
ssl_certificate /etc/nginx/ssl/child-xxx/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/child-xxx/privkey.pem;
ssl_trusted_certificate /etc/nginx/ssl/child-xxx/chain.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
# root /usr/share/nginx/html;
# index index.html;
location / {
proxy_pass http://x.x.x.x:18080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
4.续期
命令如下:
certbot renew
证书 3 个月有效期,在过期时执行就可以了。
因为没有过期,所以显示不能 renew。
5.自动续期
编写个 renew_cert.sh 脚本
#!/bin/bash
certbot renew
# 90 天一次
0 0 */90 * * /root/cert-scripts/child-xxx/renew_cert.sh
正常这样就可以了,我的 renew_cert.sh 还需要添加文件拷贝到 nginx 容器的操作,就不展示了。
相关: