Due to Tencent Cloud CDN not supporting immediate service suspension for unpaid bills, we switched to DogeCloud CDN two months ago.
Currently, the free SSL certificates for Baota/1Panel only have a validity period of 90 days. Although they can be automatically renewed, the CDN certificate still needs to be frequently updated manually 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#
- Enter 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 uploaded successfully!
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 process of generating AccessToken
involves concatenating the request address and request content, then using SecretKey
for HMAC-SHA1
encryption, and finally connecting 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
, simply add Authorization: TOKEN <AccessToken>
to the request header to pass 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 the private key privkey.pem
corresponding to that domain.
It is recommended to use the same wildcard certificate for the domain and all its subdomains, allowing for 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 remark 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 uploaded successfully!"
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 was 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