Back to articles
Technology Insight

Scaling Ghost CMS: High-Performance Multi-VPS Deployment with Automated Cloudflare Cache Purging

May 29, 2026

Introduction: The Challenge of Scaling Ghost CMS for Enterprise Needs

Ghost CMS has emerged as one of the most powerful, modern platforms for professional publishing, journalism, and content marketing. Its sleek Node.js architecture delivers exceptional raw speed compared to traditional database-heavy monoliths. However, as your media brand or corporate blog grows, relying on a single Virtual Private Server (VPS) introduces a critical single point of failure (SPOF) and strict scaling limitations.

To achieve true enterprise-grade availability and sub-second global loading times, engineering teams must look toward a distributed VPS cluster architecture backed by a robust Content Delivery Network (CDN) like Cloudflare. But caching dynamic content at the edge introduces a notorious hurdle: stale content. When an editor publishes an urgent update or a new article, readers might not see it for hours due to aggressive edge caching.

This comprehensive guide provides a step-by-step blueprint for deploying Ghost CMS on a resilient, multi-VPS infrastructure and configuring automated Cloudflare cache purging using Ghost Webhooks and specialized worker scripts.

Architectural Overview: Designing the Cluster

Before diving into terminal commands, it is essential to understand the topology of a highly available Ghost deployment. A standard single-instance setup places the Node.js application, the MySQL database, and asset storage on the same machine. In a clustered environment, we must decouple these layers.

  • The Load Balancing & Edge Layer (Cloudflare): Acts as the primary firewall, SSL termination point, and global cache provider.
  • The Application Layer (Multiple VPS Nodes): Two or more identical VPS instances running Ghost CMS inside Docker containers or via Ghost-CLI, configured behind a load balancer (such as Nginx or HAProxy) if Cloudflare Origin Pools are not utilized.
  • The Database Layer (Managed MySQL): A separate, dedicated database instance or a primary-replica cluster ensuring data consistency across all application nodes.
  • The Shared Storage Layer: A centralized storage solution (like AWS S3, DigitalOcean Spaces, or an NFS mount) to ensure that uploaded images and themes are instantly accessible by all VPS instances.

Step 1: Setting Up the Decoupled Ghost Infrastructure

1. Configuring the Shared Database

First, provision your dedicated MySQL instance. Ghost requires MySQL 8. Secure your database and create a new database user with permissions scoped strictly to your network subnet:

CREATE DATABASE ghost_prod;
CREATE USER 'ghost_user'@'10.%.%.%' IDENTIFIED BY 'YourSecurePassword';
GRANT ALL PRIVILEGES ON ghost_prod.* TO 'ghost_user'@'10.%.%.%';
FLUSH PRIVILEGES;

2. Synchronizing the Content Directory

Because Ghost expects local access to themes and media assets, you must implement a shared file system. While a storage adapter plugin (like ghost-storage-adapter-s3) is highly recommended for images, your theme files must remain synchronized across your VPS cluster. Using a tool like lsyncd or mounting a shared GlusterFS/NFS volume ensures that when a theme is updated on Node A, Node B reflects the change instantly.

3. Deploying Ghost App Instances

On each application VPS, install Ghost using Docker or the official Ghost-CLI. Ensure your config.production.json points to the centralized MySQL database and shared storage system. Both instances must run identical configurations and share the same encryption keys to allow seamless user session handoffs.

Step 2: Integrating Cloudflare for Advanced Caching

With your VPS cluster rendering Ghost pages, the next objective is protecting those servers from traffic spikes by caching heavily at the Cloudflare edge.

1. Setting Up Cache Rules

Navigate to your Cloudflare Dashboard and create a new Cache Rule for your domain. By default, Cloudflare does not cache HTML content aggressively. We want to override this behavior for maximum performance:

  1. Set the matching criteria to targeting all incoming traffic (e.g., Hostname equals blog.yourdomain.com).
  2. Configure Cache Eligibility to Eligible for Cache.
  3. Under Edge TTL, select Override origin and set it to a long duration, such as 7 days or 1 month. This ensures pages stay in Cloudflare’s edge memory globally.

2. Excluding the Admin Panel

Crucial Security Notice: You must never cache the Ghost admin portal, preview links, or API endpoints. Create a separate, higher-priority Cache Rule or Page Rule with the following conditions:

  • URI Path starts with /ghost/
  • URI Path starts with /p/ (Preview links)
  • URI Path starts with /ghost/api/

Set the Cache Level for these paths to Bypass, ensuring real-time interactivity for your editorial team.

Step 3: Automating Cache Purging with Ghost Webhooks

Now that your site is aggressively cached, any new post, page update, or deletion will not immediately appear to the public. To solve this, we will use Ghost’s native webhook system coupled with Cloudflare’s API to clear the cache precisely when updates happen.

1. Generating a Cloudflare API Token

To allow automated systems to clear your cache, you must provision an API token with minimal privileges:

  1. Go to your Cloudflare profile, select API Tokens, and click Create Token.
  2. Choose the Clear Cache template (or create a custom token with Zone - Cache Purge - Edit permissions).
  3. Restrict the token’s scope to your specific target domain zone to follow security best practices.

2. Creating the Middleware Webhook Receiver

Ghost webhooks send a standard JSON payload when events trigger. While you can target Cloudflare directly using specific orchestration tools, deploying a small, lightweight serverless function (like a Cloudflare Worker) or a microservice script on your cluster acts as a brilliant translator. This script receives the webhook and calls the Cloudflare Cache Purge API endpoint.

Here is an architectural concept of the payload handling sequence:

When an editor clicks "Publish" → Ghost fires a post.published event → The Webhook Receiver validates the payload → Executes an HTTP POST request to [https://api.cloudflare.com/client/v4/zones/](https://api.cloudflare.com/client/v4/zones/){zone_id}/purge_cache with the parameter {"purge_everything": true} or targets specific URLs for granular cache clearing.

3. Registering the Webhook in Ghost Admin

To finalize the automation cycle:

  1. Log into your Ghost Admin dashboard (accessible via a single cluster node bypass URL).
  2. Navigate to Settings > Integrations > Custom Integrations.
  3. Click Add custom integration, name it "Cloudflare Auto-Purge", and click Add Webhook.
  4. Select the Event: Post published (you should also create separate ones for Post updated, Post deleted, and Page published).
  5. Paste your Webhook Receiver URL into the Target URL field and save.

Conclusion: Monitoring and Optimization

By shifting your Ghost CMS deployment from a standalone server to a robust multi-VPS architecture paired with intelligent Cloudflare lifecycle caching, you achieve the gold standard of modern web publishing: uncompromised scalability and instantaneous content delivery.

Your origin VPS instances will experience drastically lower CPU utilization because Cloudflare shields them from up to 95% of routine GET requests. Meanwhile, your automated webhook integration guarantees that your audience encounters zero friction when reading newly published articles. Monitor your Cloudflare Analytics dashboard regularly to keep track of your cache hit ratios and ensure your infrastructure scales gracefully alongside your traffic.

Scaling Ghost CMS: High-Performance Multi-VPS Deployment with Automated Cloudflare Cache Purging | DPTCloud