跳过正文
  1. blog/

CertBot自动化SSL证书部署

·1707 字·
Blog 运维
Aoidayo
作者
Aoidayo
懒人
目录

前言
#

为什么需要使用SSL证书自动部署?

  • SSL证书的时间比较短,之前可以使用1年证书的时候手动部署无所谓,但是最近两年(指从24年开始)免费证书的有效期都普遍变成了3个月。每三个月都得手动续期一下,我自己每三个月拉一次证书和私钥、然后传到服务器上的这个流程已经做了十几遍了,流汗了🤣😅。
  • 现在的短有效期证书以后可能会更短,据说CA/Browser Forum通过的决议会在2029年让证书最长有效期会缩到47天。这种短周期会让倒闭证书的自动化部署流程,同时减少网站内容传输没有被SSL证书加密、而被劫持的风险。
  • 现在的SSL证书本质上就是可以给你的网站内容传输做一次加密,实际上也是WebPKI信任模型的边界:证书不能帮你证明这是家合法合规公司,他只负责加密通道。

证书自动化的机制:

  • ACME协议把证书申请变成了可编程的API:通过DNS验证某个域名是你自己的,CA就会给你发证书。(Let's Encrypt真是能和cloudflare类比的大好人啊,我以前还以为证书都需要自己花钱买的。)

我的情况:

  • 我只需要更新SSL的cert和key,将cert和key替换原来的证书和密钥文件,然后重启nginx,现在需要做的就是实现这个流程的自动化。
  • 之前我在ohttps上申请证书并部署到服务器上,使用fullchain.pem(证书和中间证书)和certkey.pem(私钥)两个文件。
  • 现在使用certbot和python3-certbot-dns-cloudflare自动化该流程,向let's encrypt申请通配符证书到本地。

关于我为什么需要SSL证书:

  • Damn的密码管理器VaultWarden强制需要SSL证书,不然不给连接。

CertBot使用
#

基本流程:

  • 1、安装
  • 2、DNS 验证插件安装
  • 3、使用CertBot申请证书

1、安装
#

两种方式: 1)使用snap安装

sudo apt update
sudo apt install snapd -y
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

2)使用apt安装

apt install certbot

验证

certbot --version

2、DNS 验证插件安装
#

(1) 申请cloudflare的api token

申请cloudflare的api token(注意不是global token)

登录 Cloudflare:

  1. 进入 → My Profile
  2. 选择 → API Tokens
  3. 点击 → Create Token
  4. 使用模板:Edit zone DNS,其中权限必须包含:Zone:DNS+Zobe
  5. Zone Resources 选择:Include → Specific zone → aoidayo.site

保存并复制完整 token。

⚠️ 注意:不要多复制空格或换行。

(2) DNS API自动验证

DNS API自动验证:以Cloudflare为例:

1、安装插件

sudo apt install python3-certbot-dns-cloudflare

2、创建 API Token 文件

sudo nano /root/.cloudflare.ini

写入:

dns_cloudflare_api_token = NEywfvoLF012e5bvEQyqqntGL4V4L971YnTInGqd

设置权限:

sudo chmod 600 /root/.cloudflare.ini

3、certbot使用
#

1、申请通配符证书

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.cloudflare.ini \
  -d aoidayo.site \
  -d "*.aoidayo.site"

这一步需要你添加通知邮箱和一些协议,我都默认yes了。

❯ sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.cloudflare.ini \
  -d aoidayo.site \
  -d "*.aoidayo.site"
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for aoidayo.site and *.aoidayo.site
Waiting 10 seconds for DNS changes to propagate

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/aoidayo.site/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/aoidayo.site/privkey.pem
This certificate expires on 2026-05-31.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

成功后证书在:

/etc/letsencrypt/live/example.com/

2、同时certbot会自动创建定时任务:

查看:

systemctl list-timers | grep certbot
# 
Tue 2026-03-03 09:46:37 CST 17h left           n/a                         n/a           certbot.timer                  certbot.service

3、测试续期:

sudo certbot renew --dry-run # 测试续期
sudo certbot renew --force-renewal # 强制续期

4、添加续期后hook

🤔 添加续期后hook,在复制证书后,自动reload nginx,最后写入nginx/ssl的op.log中。

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh # 
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh # 赋权

我的bash脚本如下:

#!/bin/bash

set -e

# ==============================
# 基本变量
# ==============================

DOMAIN="aoidayo.site"
SRC_DIR="/etc/letsencrypt/live/$DOMAIN"
DST_DIR="/home/dockers/nginx/ssl/aoidayo"
LOG_FILE="$DST_DIR/op.log"

SRC_CERT="$SRC_DIR/fullchain.pem"
SRC_KEY="$SRC_DIR/privkey.pem"

DST_CERT="$DST_DIR/fullchain.pem"
DST_KEY="$DST_DIR/certkey.pem"

TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")

# ==============================
# 检查源文件是否存在
# ==============================

if [[ ! -f "$SRC_CERT" || ! -f "$SRC_KEY" ]]; then
    echo "[$TIMESTAMP] ERROR: Source certificate files not found." >> "$LOG_FILE"
    exit 1
fi

# ==============================
# 创建目标目录
# ==============================

mkdir -p "$DST_DIR"

# ==============================
# 复制并覆盖
# ==============================

cp -f "$SRC_CERT" "$DST_CERT"
cp -f "$SRC_KEY"  "$DST_KEY"

# 设置合理权限
chmod 644 "$DST_CERT"
chmod 600 "$DST_KEY"

# ==============================
# 重启 docker nginx
# ==============================

if docker restart nginx-server > /dev/null 2>&1; then
    echo "[$TIMESTAMP] SUCCESS: Certificate updated and nginx-server restarted." >> "$LOG_FILE"
else
    echo "[$TIMESTAMP] ERROR: Docker restart failed!" >> "$LOG_FILE"
    exit 1
fi

exit 0

参考
#

最后给出本文参考。

参考: