Due to Tencent Cloud CDN not supporting immediate service suspension for unpaid fees, we switched to DogeCloud CDN two months ago.
Currently, the free SSL certificates from Baota/1Panel only have a validity period of 90 days. Although they can be automatically renewed, it still requires frequent manual updates of the CDN's certificate after renewal, which is very troublesome.
Fortunately, DogeCloud provides a corresponding API that allows us to automatically synchronize SSL certificates to DogeCloud CDN through scripts.
Features#
- 🔑 Dynamically generate DogeCloud API access tokens
- 📤 One-click certificate upload and management
- 🌐 Intelligent certificate binding for multiple domains
- 🗑️ Old certificate cleanup feature (optional)
- ⏰ Seamless integration with Let's Encrypt automatic renewal
- ✅ Dual platform support (Baota/1Panel)
Quick Start#
- Obtain DogeCloud API key:
- Log in to the DogeCloud console
- Go to "User Center" → "Key Management"
- Create a new key pair
- Confirm certificate path:
- Baota panel:
/www/server/panel/vhost/ssl/domain_directory/
- 1Panel can be skipped
- Baota panel:
Configuration Guide#
Edit the following parameters in the script:
# DogeCloud AccessKey and SecretKey
ACCESS_KEY="your_access_key_here" # Replace with your AccessKey
SECRET_KEY="your_secret_key_here" # Replace with your SecretKey
# Certificate path configuration
FULLCHAIN_PATH="/path/to/fullchain.pem" # Full chain certificate path
PRIVKEY_PATH="/path/to/privkey.pem" # Private key path
# Domain configuration
DOMAINS=("example.com" "cdn.example.com" "www.example.com") # List of domains to bind
# Old certificate handling strategy
DELETE_OLD_CERT=false # true=automatically delete old certificates | false=keep historical certificates
Deployment Guide#
1Panel#
- Go to the certificate management interface
- Create/Edit certificate:
- Enable "Automatic Renewal"
- Enable "Push Certificate to Local Directory"
- Select directory
- Enable "Execute Script After Application"
- Paste the script content
- Change the certificate path to:
# Certificate path
FULLCHAIN_PATH="./fullchain.pem"
PRIVKEY_PATH="./privkey.pem"
Baota#
- Create a scheduled task:
- Task type: Shell script
- Task name: Any name
- Execution period: Execute once on the 1st of every month at 01:30
- Execution user: root
- Script content: Paste the script content
- In conjunction with the automatic renewal Let's Encrypt certificate scheduled task
/www/server/panel/pyenv/bin/python /www/server/panel/class/acme_v2.py –renew=1
, it can theoretically achieve the synchronization of DogeCloud CDN certificates.
After saving, execute the task once. If the following information is displayed, the certificate synchronization has been completed:
Certificate upload successful!
Certificate ID: 12345
Certificate successfully bound to www.vinking.top
Certificate successfully bound to vinking.top
Certificate ID 12344 deleted successfully.
----------------------------------------------------------------------------
★[2024-12-26 16:01:29] Successful
----------------------------------------------------------------------------
Code Logic#
Obtain Key & Generate AccessToken
#
DogeCloud's API has a verification mechanism. Before use, you need to obtain the AccessKey
and SecretKey
from the console's Key Management, and then generate the AccessToken
based on the AccessKey
and SecretKey
.
The generation process of AccessToken
is to concatenate the request address and request content, then use SecretKey
for HMAC-SHA1
encryption, and finally connect the obtained encrypted value with AccessKey
using a colon. The specific generation algorithm can be referenced in the documentation Verification Mechanism.
# DogeCloud AccessKey and 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 the verification.
Find Baota's Domain Certificate & Upload Certificate#
In the /www/server/panel/vhost/ssl/
directory, you can find all folders named after the domain in Baota, which contain the full certificate chain fullchain.pem
and private key privkey.pem
corresponding to this domain.
It is recommended to use the same wildcard certificate for the domain and all its subdomains, which can achieve one-time synchronization of the certificate for the domain and all its subdomains.
Taking the domain vinking.top
as an example, the directory for the full certificate chain file and private key file is 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 uploaded certificate to the domain.
Refer to the documentation Upload Certificate, Bind Certificate.
# Baota panel Let's Encrypt certificate path
FULLCHAIN_PATH="/www/server/panel/vhost/ssl/vinking.top/fullchain.pem"
PRIVKEY_PATH="/www/server/panel/vhost/ssl/vinking.top/privkey.pem"
# Certificate note name
CURRENT_DATE=$(date +"%y/%m/%d")
NOTE="Certificate $CURRENT_DATE"
# List of domains to bind
DOMAINS=("xxxxx.com" "cdn.xxxxx.com" "www.xxxxx.com")
# Upload certificate to DogeCloud
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 "Certificate upload successful!"
local certId=$(echo "$response" | jq -r '.data.id')
echo "Certificate ID: $certId"
bindCert "$certId"
else
local errMsg=$(echo "$response" | jq -r '.msg')
echo "Certificate upload failed, error code: $code, error message: $errMsg"
fi
}
# Bind certificate
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 "Certificate successfully bound to $domain"
else
local errMsg=$(echo "$response" | jq -r '.msg')
echo "Failed to bind certificate to $domain, error code: $code, error message: $errMsg"
fi
) &
done
wait
}
This article is synchronized and updated to xLog by Mix Space
The original link is https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn