对于个人开发者和小型项目来说,由 Let’s Encrypt 提供的免费 SSL 证书无疑是开启 HTTPS 的福音。但它有一个烦恼——证书有效期只有 90 天。这意味着每隔两三个月,我们就需要登录服务器,手动执行续签命令,否则网站就会因证书过期而无法访问。
虽然可以在网站服务器上直接设置 cron
定时任务来续签,但这有几个缺点:
- 分散管理:如果有多台服务器,需要在每台服务器上都进行配置。
- 验证麻烦:使用 HTTP-01 方式验证时,需要临时占用 80 端口,有时会与现有 Web 服务冲突。
- 无法申请泛域名证书:HTTP-01 验证不支持申请像
*.yourdomain.com
这样的泛域名证书。
那么,有没有一种方法,可以集中、自动、且一劳永逸地解决这个问题呢?答案是肯定的。
使用内网树莓派作为“证书管家”
我们的核心思路是,将证书的申请与续签任务,与网站的实际运行分离开来。我们指定一台低功耗、可 7x24 小时运行的设备作为“证书管家”,定期执行续签工作。
整个自动化流程如下:
- 定时触发:树莓派上的
cron
定时任务,在每天凌晨自动触发续签脚本。 - 智能续签:脚本调用
Certbot
,Certbot 会检查证书是否在未来 30 天内过期。如果不需要续签,则直接退出;如果需要,则进入下一步。 - DNS-01 验证:Certbot 使用我们预先配置的 DNSPod API 密钥,自动在我们的域名解析中添加一条临时的 TXT 记录,以向 Let’s Encrypt 证明我们对该域名的所有权。
- 获取证书:验证成功后,Let’s Encrypt 会颁发新的证书,并由 Certbot 将其保存在树莓派本地。
- 安全部署:树莓派通过
scp
(Secure Copy) 将最新的证书文件安全地推送到远端的腾讯云服务器上。 - 远程生效:证书推送完毕后,树莓派再通过
ssh
远程命令,让腾讯云服务器上的 Nginx 服务重新加载配置,使新证书即刻生效。
准备工作
在开始之前,请确保你拥有:
- 一台安装了 Ubuntu (ARM64) 系统的树莓派,并能正常联网。
- 一台部署了网站的腾讯云服务器 (Ubuntu)。
- 一个在腾讯云 DNSPod 进行解析的域名。
- 树莓派和服务器之间可以通过 SSH 正常通信。
实战步骤
获取 DNSPod API 密钥
这是实现 DNS-01 验证的关键。API 密钥需要从腾讯云主控制台获取。
- 登录腾讯云控制台,进入访问管理 (CAM)。
- 在左侧菜单选择 访问密钥” -> “API 密钥管理。
- 点击 新建密钥,你将获得一对
SecretId
和SecretKey
。请务必立即复制并妥善保管SecretKey
!
在树莓派上安装并配置 Certbot
-
安装 Certbot 及腾讯云插件
# 在树莓派上执行 sudo apt update sudo apt install python3-pip -y sudo pip3 install certbot certbot-dns-tencentcloud
-
创建 API 凭证文件
# 在树莓派上执行 mkdir -p ~/.secrets/certbot nano ~/.secrets/certbot/tencentcloud.ini
在文件中写入以下内容,并替换成你自己的密钥:
dns_tencentcloud_secret_id = 你的SecretId dns_tencentcloud_secret_key = 你的SecretKey
-
设置严格的文件权限(非常重要!)
# 在树莓派上执行 sudo chmod 600 ~/.secrets/certbot/tencentcloud.ini
配置服务器的远程接收环境
我们需要在腾讯云服务器上创建一个专用的、低权限的用户来接收证书和执行命令,以提高安全性。
-
创建专用用户
# 在腾讯云服务器上执行 sudo adduser cert-updater
-
创建证书存放目录并授权
# 在腾讯云服务器上执行 sudo mkdir -p /home/cert-updater/certs sudo chown -R cert-updater:cert-updater /home/cert-updater/certs
打通树莓派到服务器的“自动化通道”
要让脚本自动运行,必须配置两个关键的“免密”环节。
-
配置树莓派
root
用户的 SSH 免密登录
由于我们的定时任务最终会以root
权限运行,所以需要为树莓派的root
用户配置到服务器的免密登录。# 在树莓派上执行 sudo -i # 切换到 root 用户 ssh-keygen -t rsa # 一直回车 ssh-copy-id cert-updater@<你的腾讯云服务器IP> # 按提示输入一次 cert-updater 的密码 exit # 退回到普通用户
-
配置服务器
cert-updater
用户的 Sudo 免密权限
让cert-updater
用户可以无需密码就执行 Nginx 重载命令。# 在腾讯云服务器上执行 sudo visudo
在打开的文件的最底部,添加这一行:
cert-updater ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
首次手动获取证书
我们先手动运行一次 Certbot,获取第一个泛域名证书。
# 在树莓派上执行
sudo certbot certonly \
--authenticator dns-tencentcloud \
--dns-tencentcloud-credentials ~/.secrets/certbot/tencentcloud.ini \
-d yourdomain.com \
-d *.yourdomain.com \
--agree-tos -m [email protected] --non-interactive
请将上面的 *.yourdomain.com
[email protected]
字段更换为实际的内容。
如果看到 Successfully received certificate.
的提示说明已经成功!
编写自动化脚本
在树莓派上,创建一个 renew_ssl.sh
脚本,将续签、上传、重载三个动作串联起来。
# 在树莓派上执行
nano ~/renew_ssl.sh
将下面的完整脚本粘贴进去,并修改顶部的配置项:
#!/bin/bash
## 配置项 ##
DOMAIN="yourdomain.com"
REMOTE_USER="cert-updater"
REMOTE_IP="<你的腾讯云服务器IP>"
REMOTE_CERT_DIR="/home/cert-updater/certs"
LOG_FILE="/var/log/ssl_renew.log"
## 脚本主体 ##
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
log_message "开始执行 SSL 证书续签与部署任务..."
# 1. 续签
log_message "步骤 1/3: 正在尝试使用 Certbot 续签证书..."
sudo certbot renew --quiet
# 2. 部署
if [ $? -eq 0 ]; then
log_message "Certbot 续签检查完成,开始同步证书..."
ssh $REMOTE_USER@$REMOTE_IP "mkdir -p $REMOTE_CERT_DIR"
sudo scp -r /etc/letsencrypt/live/$DOMAIN/* $REMOTE_USER@$REMOTE_IP:$REMOTE_CERT_DIR/
if [ $? -eq 0 ]; then
log_message "证书同步成功。"
# 3. 重载
log_message "步骤 3/3: 正在远程重载 Nginx 服务..."
ssh $REMOTE_USER@$REMOTE_IP "sudo systemctl reload nginx"
if [ $? -eq 0 ]; then
log_message "任务成功: Nginx 重载成功!"
else
log_message "错误: 远程 Nginx 重载失败!"
fi
else
log_message "错误: SCP 同步证书失败!"
fi
else
log_message "错误: 'certbot renew' 命令执行失败!"
fi
log_message "所有任务执行完毕。"
为脚本添加执行权限,并将其移动到 /root/
目录,方便管理:
# 在树莓派上执行
chmod +x ~/renew_ssl.sh
sudo mv ~/renew_ssl.sh /root/renew_ssl.sh
手动测试一下脚本sudo /root/renew_ssl.sh
。
设置定时任务
# 在树莓派上执行
sudo crontab -e
在文件末尾添加一行,让脚本每天凌晨 3:15 自动运行:
15 3 * * * /root/renew_ssl.sh
保存退出,大功告成!
配置 Nginx
最后,别忘了登录你的腾讯云服务器,修改 Nginx 配置文件,让它使用我们自动部署的证书。
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL 证书路径指向我们配置的目录
ssl_certificate /home/cert-updater/certs/fullchain.pem;
ssl_certificate_key /home/cert-updater/certs/privkey.pem;
# ... 其他 SSL 优化配置和网站配置 ...
}
检查配置并重载 Nginx:
sudo nginx -t
sudo systemctl reload nginx
总结
完成以上操作我们便成功配置了SSL 证书的全自动续签。