问题背景:

最近我休婚假期间,从朋友那得知网站https访问出问题了,简单看了下发现是ssl证书过期了。免费的ssl证书现在的有限期是90天,每三个月就得续签一次。三个月前我从腾讯云服务器迁移到了阿里云服务器,并用上了宝塔面板,开启了网站的ssl证书自动续期。但由于我的网站使用了cdn加速服务,还需要将ssl证书上传到腾讯云服务器才能实现完全自动化,当时迁移时太忙手动处理了下,想着后面再说结果给忘了。

实现思路:

询问了AI,AI说宝塔其实是可以支持自动同步到腾讯云cdn的,但我看了下我的阿里云版的宝塔面板,里面确实没有这个功能(坑!)。因为这个重新装一遍系统也不太现实(太麻烦),于是我决定使用AI写一个linux定时任务来实现ssl证书上传到腾讯云并绑定云资源的需求

实现步骤:

一、服务器SSL证书免费申请及自动续期

这一部分非常简单,宝塔做好的功能,点点点就可以实现了,具体步骤如下:

在宝塔面板左侧点开网站模块,点击要配置的网站,点击SSL模块配置,选择Lets Encrypt,点击申请证书,根据提示操作即可

image-20260425153527249

二、服务器SSL证书同步到腾讯云CDN并配置域名绑定

1.编写脚本

查询了腾讯云**API Explorer的ssl部分,在其中找到了上传证书证书部署到云资源实例列表**两个接口,通过这两个接口可以实现ssl证书上传和证书与cdn域名绑定的需求,脚本语言选择nodejs,复制粘贴模版代码并整合为sslUpdate脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* 腾讯云SSL证书部署脚本,用于自动化腾讯云证书部署到cdn的工作流程
*/

// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher
const path = require("path")
require("dotenv").config({ path: path.resolve(__dirname, "../.env") })
const tencentcloud = require("tencentcloud-sdk-nodejs-ssl")
const fs = require("fs")

const SslClient = tencentcloud.ssl.v20191205.Client

//ssl证书存放路径
const sslPath = "G:/下载/Nginx"

if (!sslPath) {
console.error("请设置 SSL_PATH 环境变量指定证书路径")
process.exit(1)
}

const sslPublicKeyPath = path.join(sslPath, "fullchain.pem")
const sslPrivateKeyPath = path.join(sslPath, "privkey.key")

if (!fs.existsSync(sslPublicKeyPath) || !fs.existsSync(sslPrivateKeyPath)) {
console.error("证书文件不存在,请检查 SSL_PATH 路径")
process.exit(1)
}

const certificatePublicKey = fs.readFileSync(sslPublicKeyPath, "utf8")
const certificatePrivateKey = fs.readFileSync(sslPrivateKeyPath, "utf8")

//构建SSL客户端服务
const clientConfig = {
credential: {
secretId: process.env.SSL_SECRET_ID,
secretKey: process.env.SSL_SECRET_KEY,
},
region: "",
profile: {
httpProfile: {
endpoint: "ssl.tencentcloudapi.com",
},
},
}
const client = new SslClient(clientConfig)

//上传证书
client
.UploadCertificate({
CertificatePublicKey: certificatePublicKey,
CertificatePrivateKey: certificatePrivateKey,
"Repeatable": false //不允许上传指纹相同的证书
})
.then(
(data) => {
const { CertificateId } = data
if (CertificateId) {
console.log("证书上传成功!", CertificateId)
deployCertificateInstance(CertificateId)
}
},
(err) => {
console.error("error", err)
}
)

//证书关联cdn域名
async function deployCertificateInstance(CertificateId) {
const params = {
CertificateId,
InstanceIdList: [
"www.cyanfish.site",
"cyanfish.site",
"demo.cyanfish.site",
"picture.cyanfish.site",
].map((item) => item + "|on"), //开启域名https服务(必须开启,否则访问网页会报514错误)
ResourceType: "cdn",
Status: 1,
}
client.DeployCertificateInstance(params).then(
(data) => {
console.log("证书关联cdn域名成功!", data)
},
(err) => {
console.error("error", err)
}
)
}

2.编写linux定时任务

打开宝塔面板—>计划任务,添加一个shell命令,用于执行上面的nodejs脚本,每个月执行一次就行。

1
node /home/www/scripts/updateSSL.js

image-20260425152542320

到这里就大功告成了,不出意外以后都可以不用管ssl证书过期的事了,美滋滋