Automating BunnyCDN Cache Management for Ghost CMS: A Cloudflare Worker Solution
Learn how to automate BunnyCDN cache purging for Ghost CMS using Cloudflare Workers. This guide covers webhook integration, Perma-Cache cleanup, and step-by-step deployment, helping you ensure content freshness while optimizing storage costs.
In my previous post, I discussed integrating Bunny CDN to enhance my blog's performance. If you're interested, you can read about it in the post below:
While Bunny CDN improved performance, I encountered a significant workflow issue: manually purging the cache after publishing each post. This manual step required logging into Bunny CDN's website, and like any manual process, I sometimes forgot to do it. When that happened, visitors would see outdated cached content instead of my new posts. To eliminate this overhead and potential for human error, I decided to automate the cache purging process.
During my research on Ghost CMS's documentation, I discovered a valuable feature: webhooks that can trigger cache purging automatically whenever a site.changed
event occurs.
This feature significantly simplified my workflow. Setting it up only requires creating a custom integration through the admin portal. With the trigger mechanism built in, I could focus entirely on developing an always-online middleware to handle the cache purging process.
Workflow Design
Since the process would now be automated, the middleware needed to interface with Bunny CDN's API to handle cache purging. After consulting the official API documentation, I found that purging the entire Pull Zone's cache was straightforward:
All I need are two parameters: My Bunny account AccessKey
and The Pull Zone ID.
With the API requirements clear, the next step was choosing an appropriate development platform and language for the middleware. Cloudflare Workers emerged as the ideal solution, offering a serverless execution environment where I could develop applications without managing infrastructure. I chose JavaScript for its straightforward deployment process to Cloudflare Workers.
Another notable issue which needs to be solved is Bunny CDN is Perma-Cache, a secondary permanent cache layer between the CDN and your origin. When content isn't found in the CDN cache, it checks the Geo-Replicated storage before reaching the origin server.
While this caching system enhances performance, it has a potential drawback: each cache purge creates a new folder in the linked Storage Zone without removing previous ones. This accumulation could lead to unnecessary storage costs over time. To address this, the workflow needs to incorporate Storage Zone API calls to identify and remove outdated Perma-Cache folders. The API documentation related is as below:
The complete cache purging automation workflow can be visualized in the flowchart below:
Source Code Explanation
I have open sourced the code on GitHub, which you can find in the below repo:
Purpose of the Code
- Automates cache purging in BunnyCDN via API integration.
- Verifies requests using a Ghost webhook signature or manual trigger token.
- Cleans up unused folders in BunnyCDN’s Perma-Cache storage.
Key Features
- Webhook Verification: Ensures only authorized requests (from Ghost or a manual trigger) are processed.
- Pull Zone Cache Purge: Clears BunnyCDN’s pull zone cache for the specified zone ID.
- Perma-Cache Cleanup: Identifies and deletes stale folders in BunnyCDN storage.
How the Code Works
- Request Handling
- Listens for HTTP requests.
- Validates required environment variables.
- Routes the request based on the URL path (e.g.,
/purge-full-cache
).
- Authentication
- Manual Trigger: Checks for a token in the request headers.
- Ghost Webhook: Verifies the signature using a secret key and HMAC.
- Pull Zone Cache Purge
- Calls BunnyCDN API to purge the pull zone cache.
- Logs success or failure.
- Perma-Cache Folder Cleanup
- Fetches a list of folders in the Perma-Cache directory.
- Deletes each folder and logs the results (success or failure).
- Error Handling
- Logs all errors with detailed messages.
- Responds with appropriate HTTP status codes.
Required Environment Variables
GHOST_WEBHOOK_SECRET
: Secret key for verifying Ghost webhook requests.BUNNY_PULLZONE_ID
: ID of the BunnyCDN pull zone.BUNNY_API_KEY
: API key for BunnyCDN access, where you can get yours here.BUNNY_STORAGE_ZONE_HOSTNAME
,BUNNY_STORAGE_ZONE_NAME
,BUNNY_STORAGE_ZONE_PASSWORD
: Credentials for BunnyCDN storage, where you can get in theFTP & API Access
tab in your storage zone menu.
Workflow Summary
- Trigger: A request to
/purge-full-cache
. - Validate: Environment variables and authentication.
- Purge: Clear pull zone cache via BunnyCDN API.
- Clean: Delete stale folders from Perma-Cache.
- Respond: Return a summary of actions performed.
Code Deployment
Deploy to the Cloudflare Worker
Deployment to Cloudflare is straightforward: navigate to the Workers & Pages
tab in your Cloudflare dashboard, create a new worker, and paste the code from worker.js
.
Then, configure your environment variables by accessing Settings
→ Variables and Secrets
in your worker's configuration panel and input your credentials.
Create Custom Integration in Ghost
Cloudflare automatically assigns a public domain to each worker. To connect it with Ghost, create a custom integration under the Integrations
tab as shown below:
That's it! Now whenever your website changes, it will automatically trigger the Cloudflare Worker to clear all caches.
Security & Manual Trigger
The code incorporates multiple layers of security to prevent unauthorized access. For requests from Ghost, it validates a webhook signature using an HMAC mechanism with a shared secret (GHOST_WEBHOOK_SECRET
). This ensures that only requests generated by Ghost are accepted. The signature validation also includes a timestamp check, rejecting requests older than 5 minutes to guard against replay attacks.
For administrative purposes, the code supports a manual trigger mechanism. By including a pre-defined manualtriggertoken
in the HTTP request headers, authorized users can bypass signature verification. However, this token is securely stored as an environment variable (MANUAL_TRIGGER_TOKEN
), ensuring only those with access to the correct token can execute the manual trigger. Together, these measures safeguard the integrity of the workflow while allowing flexibility for cache management tasks.
Conclusion
By automating the cache purging process with Ghost webhooks and Cloudflare Workers, I've eliminated manual intervention and potential human error from my blog's content delivery workflow.
The solution not only handles Bunny CDN's cache purging automatically but also manages Perma-Cache storage efficiently, preventing unnecessary costs. This automated system ensures that my readers always see the latest content while maintaining optimal performance.
The entire solution is open-source and readily available for other Ghost CMS users who want to implement similar automation in their BunnyCDN setup.
Discussion