Two months ago, I switched to DogeCloud CDN because Tencent Cloud CDN does not support immediate suspension of service upon arrears.

But!
Currently, free SSL certificates from Baota/1Panel are valid for only 90 days. Although they can be automatically renewed, you still need to frequently manually update the CDN certificate after renewal, which is very troublesome.
Fortunately, DogeCloud provides corresponding APIs, allowing us to automatically sync SSL certificates to DogeCloud CDN via scripts.

Features
- 🔑 Dynamically generate DogeCloud API access token
- 📤 One-click certificate upload and management
- 🌐 Smart certificate binding for multiple domains
- 🗑️ Old certificate cleanup (optional)
- ⏰ Seamless integration with Let's Encrypt auto-renewal
- ✅ Dual platform support (Baota/1Panel)
Quick Start
- Obtain DogeCloud API keys:
- Log in to the DogeCloud console
- Go to "User Center" → "Key Management"
- Create a new key pair
- Confirm certificate paths:
- Baota Panel:
/www/server/panel/vhost/ssl/domain directory/ - 1Panel can be skipped
- Baota Panel:
Configuration Guide
Edit the following parameters in the script:
# 多吉云 AccessKey 和 SecretK
ACCESS_KEY="your_access_key_here" # 替换为你的AccessKey
SECRET_KEY="your_secret_key_here" # 替换为你的SecretKey
# 证书路径配置
FULLCHAIN_PATH="/path/to/fullchain.pem" # 全链证书路径
PRIVKEY_PATH="/path/to/privkey.pem" # 私钥路径
# 域名配置
DOMAINS=("example.com" "cdn.example.com" "www.example.com") # 需要绑定的域名列表
# 旧证书处理策略
DELETE_OLD_CERT=false # true=自动删除旧证书 | false=保留历史证书
Deployment Guide
1Panel
- Enter the certificate management interface
Create/Edit certificate:
- Enable "Auto Renewal"
- Enable "Push certificate to local directory"
- Select a directory
- Enable "Execute script after application"
- Paste the script content
- Modify the certificate paths to:
Shell# 证书路径 FULLCHAIN_PATH="./fullchain.pem" PRIVKEY_PATH="./privkey.pem"

1Panel Certificate Settings
Baota
- Create a scheduled task:
- Task type: Shell script
- Task name: as you wish
- Execution period: once at 01:30 on the 1st of each month
- Execution user: root
- Script content: paste the script content

Baota Scheduled Task
- By combining with the scheduled task for Let’s Encrypt certificate auto-renewal
/www/server/panel/pyenv/bin/python /www/server/panel/class/acme_v2.py –renew=1, theoretically you can achieve hands-off management of DogeCloud CDN certificates.
After saving, execute the task once. If the following information is displayed, it means the certificate synchronization is complete:
证书上传成功!
证书ID:12345
证书已成功绑定到 www.vinking.top
证书已成功绑定到 vinking.top
证书ID 12344 删除成功。
----------------------------------------------------------------------------
★[2024-12-26 16:01:29] Successful
----------------------------------------------------------------------------
Code Logic
Get Keys & Generate AccessToken
DogeCloud's API has an authentication mechanism. You need to obtain the AccessKey and SecretKey from the Key Management in the console before use, and then generate an AccessToken from the AccessKey and SecretKey.
The process of generating AccessToken is to concatenate the request path and request body, then encrypt them using SecretKey with HMAC-SHA1, and finally join the resulting encrypted value with AccessKey using a colon. For the specific generation algorithm, refer to the documentation Authentication Mechanism .
# 多吉云 AccessKey 和 SecretKey
ACCESS_KEY="xxxx"
SECRET_KEY="xxxxxx"
function generateAccessToken() {
local apiPath="$1"
local body="$2"
local signStr=$(echo -e "${apiPath}\n${body}")
local sign=$(echo -n "$signStr" | openssl dgst -sha1 -hmac "$SECRET_KEY" | awk '{print $NF}')
local accessToken="$ACCESS_KEY:$sign"
echo "$accessToken"
}
After generating the AccessToken, you only need to add Authorization: TOKEN <AccessToken> in the request header to pass authentication.
Locate Baota's Domain Certificate & Upload Certificate
Under the /www/server/panel/vhost/ssl/ directory, you can find all Baota folders named after domains. The folder contains the fullchain certificate fullchain.pem and private key privkey.pem corresponding to that domain.
It is recommended to use the same wildcard certificate for the domain and all its subdomains, so that certificate synchronization for the domain and all its subdomains can be completed in one go.
Taking the domain vinking.top as an example, the directories of the fullchain file and private key file are as follows:
FULLCHAIN_PATH="/www/server/panel/vhost/ssl/vinking.top/fullchain.pem"
PRIVKEY_PATH="/www/server/panel/vhost/ssl/vinking.top/privkey.pem"
After obtaining the domain certificate, you need to submit the certificate content to https://api.dogecloud.com/cdn/cert/upload.json via POST. After a successful upload, you need to obtain the certificate ID to bind the certificate just uploaded to the domain.
Refer to the documentation Upload Certificate 、 Bind Certificate .
# 宝塔面板 Let's Encrypt 证书路径
FULLCHAIN_PATH="/www/server/panel/vhost/ssl/vinking.top/fullchain.pem"
PRIVKEY_PATH="/www/server/panel/vhost/ssl/vinking.top/privkey.pem"
# 证书备注名
CURRENT_DATE=$(date +"%y/%m/%d")
NOTE="Certificate $CURRENT_DATE"
# 需要绑定的域名列表
DOMAINS=("xxxxx.com" "cdn.xxxxx.com" "www.xxxxx.com")
# 上传证书到多吉云
function uploadCert() {
local note="$1"
local certFile="$2"
local privateKeyFile="$3"
local certContent=$(<"$certFile")
local privateKeyContent=$(<"$privateKeyFile")
local encodedCert=$(echo "$certContent" | jq -sRr @uri)
local encodedPrivateKey=$(echo "$privateKeyContent" | jq -sRr @uri)
local body="note=$note&cert=$encodedCert&private=$encodedPrivateKey"
local accessToken=$(generateAccessToken "/cdn/cert/upload.json" "$body")
local response=$(curl -s -X POST "https://api.dogecloud.com/cdn/cert/upload.json" \
-H "Authorization: TOKEN $accessToken" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "$body")
local code=$(echo "$response" | jq -r '.code')
if [ "$code" -eq 200 ]; then
echo "证书上传成功!"
local certId=$(echo "$response" | jq -r '.data.id')
echo "证书 ID:$certId"
bindCert "$certId"
else
local errMsg=$(echo "$response" | jq -r '.msg')
echo "证书上传失败,错误代码:$code,错误信息:$errMsg"
fi
}
# 绑定证书
function bindCert() {
local certId="$1"
local responses=()
for domain in "${DOMAINS[@]}"; do
(
local body="id=$certId&domain=$domain"
local accessToken=$(generateAccessToken "/cdn/cert/bind.json" "$body")
local response=$(curl -s -X POST "https://api.dogecloud.com/cdn/cert/bind.json" \
-H "Authorization: TOKEN $accessToken" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "$body")
local code=$(echo "$response" | jq -r '.code')
if [ "$code" -eq 200 ]; then
echo "证书已成功绑定到 $domain"
else
local errMsg=$(echo "$response" | jq -r '.msg')
echo "绑定证书到 $domain 失败,错误代码:$code,错误信息:$errMsg"
fi
) &
done
wait
}