certbot 证书
· 5 min read
证书创建与自动续。
腾讯云 DNSPod 3.x 新版文档: https://cloud.tencent.com/document/product/1427/112178
在线模拟:https://console.cloud.tencent.com/api/explorer?Product=dnspod&Version=2021-03-23&Action=DeleteRecord
安装 certbot
ubuntu 16 及以上版本自带 snap,不需要安装 通过 snap 安装 certbot
https://certbot.eff.org/instructions?ws=nginx&os=snap
sudo apt update
sudp apt install snapd
sudo snap install --classic certbot
创建 certbot-certonly.sh
创建证书
#!/bin/bash
DOMAIN="*.henmao.com"
EMAIL="phpgege@gmail.com"
LOG_DIR="/home/ubuntu/docker/logs/nginx/letscencrypt"
CONFIG_DIR="/home/ubuntu/docker/services/nginx/ssl"
AUTH_HOOK_PATH="./auth-hook.sh"
CLEANUP_HOOK_PATH="./cleanup-hook.sh"
sudo certbot certonly \
--manual \
--preferred-challenges dns \
--logs-dir "$LOG_DIR" \
--config-dir "$CONFIG_DIR" \
--manual-auth-hook "$AUTH_HOOK_PATH" \
--manual-cleanup-hook "$CLEANUP_HOOK_PATH" \
-d "$DOMAIN" \
--email "$EMAIL" \
--agree-tos \
# --dry-run
# 检查 certbot 命令是否成功
if [ $? -eq 0 ]; then
echo "证书创建成功,正在重启 Nginx..."
cd /home/ubuntu/docker
sudo docker compose restart nginx
# curl -X POST https://example.com/success -d "status=success&domain=$DOMAIN"
else
echo "证书更新失败。"
# curl -X POST https://example.com/failure -d "status=failure&domain=$DOMAIN"
fi
创建 certbot-renew.sh
证书续期,基于 certbot-certonly.sh 将里面的 certbot certonly 改成 certbot renew
#!/bin/bash
DOMAIN="*.henmao.com"
EMAIL="phpgege@gmail.com"
LOG_DIR="/home/ubuntu/docker/logs/nginx/letscencrypt"
CONFIG_DIR="/home/ubuntu/docker/services/nginx/ssl"
AUTH_HOOK_PATH="./auth-hook.sh"
CLEANUP_HOOK_PATH="./cleanup-hook.sh"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting certbot renewal process..."
sudo certbot renew \
--manual \
--preferred-challenges dns \
--logs-dir "$LOG_DIR" \
--config-dir "$CONFIG_DIR" \
--manual-auth-hook "$AUTH_HOOK_PATH" \
--manual-cleanup-hook "$CLEANUP_HOOK_PATH" \
-d "$DOMAIN" \
--email "$EMAIL" \
--agree-tos \
# --dry-run
# 检查 certbot 命令是否成功
if [ $? -eq 0 ]; then
echo "证书更新成功,正在重启 Nginx..."
cd /home/ubuntu/docker
sudo docker compose restart nginx
# curl -X POST https://example.com/success -d "status=success&domain=$DOMAIN"
else
echo "证书更新失败。"
# curl -X POST https://example.com/failure -d "status=failure&domain=$DOMAIN"
fi
创建 auth-hook.sh
调用 auth-hook.js
#!/bin/bash
/home/ubuntu/.nvm/versions/node/v20.18.1/bin/node /home/ubuntu/docker/services/crons/auth-hook.js
创建 auth-hook.js
动态添加 DNS TXT 记录
// 参考:https://console.cloud.tencent.com/api/explorer?Product=dnspod&Version=2021-03-23&Action=CreateTXTRecord
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher
const tencentcloud = require("tencentcloud-sdk-nodejs-dnspod");
const fs = require("fs");
const DnspodClient = tencentcloud.dnspod.v20210323.Client;
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
const clientConfig = {
credential: {
secretId: "****",
secretKey: "****",
},
region: "",
profile: {
httpProfile: {
endpoint: "dnspod.tencentcloudapi.com",
},
},
};
// 实例化要请求产品的client对象,clientProfile是可选的
const client = new DnspodClient(clientConfig);
const params = {
Domain: process.env.CERTBOT_DOMAIN,
RecordLine: "默认",
Value: process.env.CERTBOT_VALIDATION,
SubDomain: '_acme-challenge',
};
console.log("添加params", params);
client.CreateTXTRecord(params).then(
(data) => {
console.log("添加成功", data);
fs.writeFileSync("./record_id.txt", String(data?.RecordId));
},
(err) => {
console.error("添加失败", err);
}
);
创建 cleanup-hook.sh
调用 cleanup-hook.js
#!/bin/bash
/home/ubuntu/.nvm/versions/node/v20.18.1/bin/node /home/ubuntu/docker/services/crons/cleanup-hook.js
创建 cleanup-hook.js
删除 DNS TXT 记录
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher
const tencentcloud = require("tencentcloud-sdk-nodejs-dnspod");
const fs = require("fs");
const DnspodClient = tencentcloud.dnspod.v20210323.Client;
const clientConfig = {
credential: {
secretId: "****",
secretKey: "****",
},
region: "",
profile: {
httpProfile: {
endpoint: "dnspod.tencentcloudapi.com",
},
},
};
// 实例化要请求产品的client对象,clientProfile是可选的
const client = new DnspodClient(clientConfig);
const data = fs.readFileSync("./record_id.txt", "utf8");
const RecordId = data.trim(); // 去除空格和换行符
const params = {
Domain: "henmao.com",
RecordId: Number(RecordId),
};
console.log("删除params", params);
client.DeleteRecord(params).then(
(data) => {
console.log("删除成功", data);
},
(err) => {
console.error("删除失败", err);
}
);
添加执行权限
chmod +x certbot-certonly.sh certbot-renew.sh auth-hook.sh cleanup-hook.sh
定时任务
分 | 时 | 天 | 月 | 周几 | 命令 |
---|---|---|---|---|---|
Minute 每个小时的第几分钟执行该任务 | Hour 每天的第几个小时执行该任务 | Day 每月的第几天执行该任务 | Month 每年的第几个月执行该任务 | DayOfWeek 每周的第几天执行该任务,0表示周日 | Command 指定要执行的程序 、脚本或命令 |
每隔 2 个月执行一次
# 在 ubuntu 用户下做的计划任务
crontab -u ubuntu -e
# 每 10 天的凌晨 3 点执行一次
0 3 */10 * * /home/ubuntu/docker/services/crons/certbot-renew.sh >> /home/ubuntu/docker/logs/certbot-renew.log 2>&1 </dev/null &