encrypt certificate 证书更新详解
原理说明
- 通过certbot容器,将宿主机上映射的证书文件,通过域名方式续期更新。
- 通过nginx容器,读取宿主机上映射的证书文件,供博客https访问
========== 证书操作部分 ===========
1. 创建certbot容器
a. 见下文贴的docker-compose.yml配置文件
b. 将该配置文件放到某个目录下,执行docker-compose up -d
创建容器
version: '3.8'
services:
certbot:
container_name: "certbot"
image: certbot/certbot:v1.14.0
restart: unless-stopped
tty: true
stdin_open: true
volumes:
- ./data/letsencrypt:/etc/letsencrypt # 将获取的证书导出到容器外的工作文件夹
- ./data/backup:/var/lib/letsencrypt/backup
entrypoint: "/bin/sh" # 必须使用 entrypoint 而不是 command, 以重写 certbot image 的 entrypoint
2. 创建证书
* 进certbot容器:容器已创建,并在对应目录下执行命令进容器,docker-compose exec certbot sh
* 申请证书的命令:certbot certonly
* 指定域名:-d xxx.com,每个 -d 加一个域名
* 指定验证方式:使用参数--preferred-challenges dns时,则需要在域名的dns加一条txt解析
* 怎么创建证书?容器内执行,`certbot certonly -a manual --preferred-challenges dns(后续交互会要求输入邮箱、并给出验证提示),执行过程原文见下
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
/opt/certbot # certbot certonly -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d triliumcn.atibm.com --preferred-challenges dns --
server https://acme-v02.api.letsencrypt.org/directory --manual
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): xxx@xxx.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for ghost.atibm.com and 4 more domains
Performing the following challenges:
dns-01 challenge for atibm.com
dns-01 challenge for ghost.atibm.com
dns-01 challenge for trilium.atibm.com
dns-01 challenge for triliumcn.atibm.com
dns-01 challenge for www.atibm.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.atibm.com with the following value:
0j_CAdI8yxRO2yQRmm4pFeyz2bvqdQNJmb4Hc65nAII
Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.ghost.atibm.com with the following value:
CZkbSDMlDKiw0JE5Yj3YHfqDcIE9VLqChe3F2OGg23g
Before continuing, verify the record is deployed.
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.trilium.atibm.com with the following value:
9JS4dyl2Q4I9N2sLLwAO7oUgBGo3jf0smnZOiDARUWU
Before continuing, verify the record is deployed.
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.triliumcn.atibm.com with the following value:
AE1Bz_bWFBP-me6AmSRe1CJake_qNy2y_tJp0n3tk5U
Before continuing, verify the record is deployed.
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.www.atibm.com with the following value:
dpZTUssWbUF9kg49W9RgHoZxAkm18G_WG_5Byws4ck8
Before continuing, verify the record is deployed.
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
Waiting for verification...
Cleaning up challenges
Subscribe to the EFF mailing list (email: xxx@xxx.com).
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/ghost.atibm.com/privkey.pem
Your certificate will expire on 2024-09-10. To obtain a new or
tweaked version of this certificate in the future, simply run
certbot again. To non-interactively renew *all* of your
certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
3. 删除和查看证书命令
a. 怎么删除证书?在容器内执行,certbot delete --cert-name ghost.atibm.com
b. 怎么查看证书有效期?certbot certificates
执行效果如下
/opt/certbot # certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: ghost.atibm.com
Serial Number: 336402f715a5e2e8d9a37e60f3ef22bebdc
Key Type: RSA
Domains: ghost.atibm.com
Expiry Date: 2021-08-25 04:34:08+00:00 (VALID: 29 days)
Certificate Path: /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/ghost.atibm.com/privkey.pem
Certificate Name: ghost.atibm.com
Serial Number: 4dc16882a468e352fe437d1e10c0bae5bf7
Key Type: RSA
Domains: ghost.atibm.com
Expiry Date: 2021-08-25 23:53:11+00:00 (VALID: 29 days)
Certificate Path: /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/ghost.atibm.com/privkey.pem
4. 更新证书续期(dns方式)
前提是已经申请过证书+证书文件已保存本地,这时候执行renew对证书续期是有效的。
新申请证书和扩展加入新域名,需要走一下上面的流程。
自动更新
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
/opt/certbot # certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ghost.atibm.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
/etc/letsencrypt/live/ghost.atibm.com/fullchain.pem expires on 2024-09-10 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 定时自动更新
# 定时任务更新证书 - 不支持manual模式,需要standalone或web模式,这个我没弄好
# 增加定时任务,每周尝试更新正式(前提是certbot已经定义了域名证书文件,renew才能有效,证书会在到期30天可以续订更新证书)
/opt/certbot # crontab -e
# do daily/weekly/monthly maintenance
# min hour day month weekday command
5 2 * * 0 certbot renew --quiet >> /var/log/certbot-renew.log 2>&1
手动更新证书
# 手动更新证书 - 利用域名商的api接口,执行命令
--------同时开3个窗口 之 手动续期1/3 ----------
[ghost@instance-20210526-1514 certbot]$ docker-compose exec certbot sh
# 申请多个域名的新证书
/opt/certbot # certbot certonly --cert-name ghost.atibm.com -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d test.atibm.com --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --manual
# 扩展新域名证书
/opt/certbot # certbot certonly --cert-name ghost.atibm.com --expand -d ghost.atibm.com -d atibm.com -d www.atibm.com -d trilium.atibm.com -d test.atibm.com --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --manual
...
Please deploy a DNS TXT record under the name
_acme-challenge.www.atibm.com with the following value:
dpZTUssWbUF9kg49W9RgHoZxAkm18G_WG_5Byws4ck8
...
-----dns记录销毁
/opt/certbot # lexicon namecom delete atibm.com TXT --name _acme-challenge --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.www --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.ghost --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.trilium --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.test --auth-username ATdoit --auth-token yourtoken;lexicon namecom delete atibm.com TXT --name _acme-challenge.triliumcn --auth-username ATdoit --auth-token yourtoken;
-------- 同时开3个窗口 之 添加dns记录2/3 ----------
/opt/certbot # pip install dns-lexicon
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge --content sZOrBtQxdp4Mco33jG42F2Tzs4DK7bX5my-xiyITFTs --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.ghost --content EHreZqYRd2AtIWHFrbZ-lVwfIbtVjiIwKk9-nfW6QGw --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.trilium --content Z6CfrmTS47RW8EWKgqZzweIjq_Sgh4ehHKj06sM1jkQ --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.test --content t6R0lsjDpe9sBPFZ1kpMEx593dUozf2EwhTkX1cES4A --auth-username ATdoit --auth-token yourtoken
/opt/certbot # lexicon namecom create atibm.com TXT --name _acme-challenge.www --content _OWfZX5Z8f11TszICy2Ga2IdAKSCJuFsjJrRkgtzxTg --auth-username ATdoit --auth-token yourtoken
-------- 同时开3个窗口 之 nginx重载3/3 ----------
在certbot里确认,并提示通过后,到宿主机重载
[ghost@instance-20210526-1514 certbot]$ docker exec nginx nginx -s reload
========== nginx部分 ===========
提示:刚才的各种操作,仅仅是用了一个certbot容器,在容器内的目录下,创建和更新维护一份证书文件,仅仅这样操作,并不能将证书用到你的网站https上
- 证书文件传递原理解释
certbot容器维护的证书目录 -> 映射宿主机目录 -> 映射nginx容器 -> nginx的conf.d配置读取nginx容器ssl证书文件 -> 用户访问你的https网站成功
这个链路就是用户访问读取ssl过程。 - certbot容器的证书映射到宿主机:
在certbot的docker-compose.yml文件里的volumes设置,增加一行
- /etc/letsencrypt:/etc/letsencrypt
- nginx容器映射到宿主机的证书地址:
在nginx的docker-compose.yml文件里的volumes设置,增加一行
- /etc/letsencrypt:/etc/letsencrypt
- nginx的conf.d网站配置文件增加https设置:
a. 直接贴配置,留意其中443 ssl端口监听和ssl文件地址
[ghost@instance-20210526-1514 nginx]$ cat data/conf.d/ghost.conf # 映射的ghost博客代理配置文件
# redirect all http traffic to https
server {
listen 80;
server_name ghost.atibm.com atibm.com www.atibm.com;
# google adsense ads.txt
location /ads.txt {
alias /usr/share/nginx/html/ghost/ads.txt;
}
return 301 https://$host$request_uri;
}
# redirect some domain https traffic to https://ghost.atibm.com
server {
listen 443 ssl;
server_name atibm.com www.atibm.com;
ssl_certificate /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ghost.atibm.com/privkey.pem;
location /ads.txt {
alias /usr/share/nginx/html/ads.txt;
}
return 301 https://ghost.atibm.com$request_uri;
}
# defined ghost.atibm.com 443
server {
listen 443 ssl;
server_name ghost.atibm.com;
ssl_certificate /etc/letsencrypt/live/ghost.atibm.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ghost.atibm.com/privkey.pem;
root /var/lib/ghost/current/core/server/public;
access_log /var/log/nginx/ghost-access.log main;
error_log /var/log/nginx/ghost-error.log warn;
location /ads.txt {
alias /usr/share/nginx/html/ghost/ads.txt;
}
location / {
proxy_pass http://ghost:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 10m;
client_body_buffer_size 128;
}
}
通过以上的证书文件映射,主要实现了2个关键操作:
- certbot容器维护nginx所访问的证书文件
- nginx容器设置ghost网站配置的ssl地址
最终实现了用户访问https网站成功,以及每三个月的证书更新