Setting up BunnyCDN with Ghost CMS

Jannis Fedoruk-Betschki
Jannis Fedoruk-Betschki 10 November 2023
Update, 19 December 2023: We have rolled out a content delivery network for all Magic Pages customers, though the approach differs from what is described in this blog post. Read more on that in our changelog.

Recently, someone in the Ghost forum asked if they could pick where their website is hosted when using Magic Pages. The short answer is, unfortunately, you can't. All our servers are in Germany. This is totally fine for anyone in Europe, but the further away you are, like in Australia, the longer it will take for a website hosted on Magic Pages to load.

This got me thinking about how to fix this without setting up servers worldwide, which is too costly for us, as a small business. Then I remembered about CDNs, short for Content Delivery Networks. Think of a CDN like a bunch of mini-stores spread out globally that have bits of your website. When someone visits your site, they get the content from the nearest store, which makes it faster for them.

So, I got to work to find whether I could implement this for Magic Pages. And guess what? I found one! I'll share how I made our own website, magicpages.co, load fast everywhere on the world using a CDN called BunnyCDN, and you can do the same for your own sites too!

Why I chose BunnyCDN to speed up my Ghost site

When I set out to find a CDN, it felt like there were a million choices. However, two big names caught my attention. The first one was Cloudflare, which is pretty much the biggest player on the CDN market. I'm already using some of their other products, so I thought, "Why not?" But then I saw the price tag. Ouch.

The first one was Cloudflare – basically the "big boy" in the league of content delivery networks. I am already using some other Cloudflare products, so it seemed natural to look in that direction. What made me look further was the pricing.

You see, I didn't just want to set this up for our own website; I wanted a cost-effective solution I could implement for all Ghost sites hosted on Magic Pages. And, because we're all about keeping costs down (no monthly subscription fees here!), Cloudflare's $20 per month and website was just too steep.

Then I found BunnyCDN, probably Cloudflare's biggest competitor. They have a pay-as-you-go pricing model, an API that I could use to manage customer sites, and servers all around the world. Sounds like a perfect match!

Screenshot of BunnyCDN's pricing as of 9 November 2023, indicating 121 servers world wide and a pricing of 0.01$/GB (Europe & North Ameria), 0.03$/GB. (Asia & Oceania), 0.045$ (South Ameria), 0.06$(Middle East & Africa).
Screenshot of BunnyCDN's pricing as of 9 November 2023

Are the speed gains measurable?

Alright, before we dive into the depth of setting up BunnyCDN and Ghost, let's take a quick peek at what this setup did for our website's speed. Just so you know, the only change I've made so far is adding BunnyCDN to the mix.

I ran a couple of speed tests from Bogota, Colombia, the location that had the worst connection to our server. I did one test before BunnyCDN worked its magic, and one after.

Here is how the page load looks like before any optimisation:

Result of a speed test using dotcom-tools.com after the CDN has been implemented, indicating a slow performance and a full page load within 3.82 seconds
Result of a speed test using dotcom-tools.com after the CDN has been implemented

And this is with the CDN enabled:

Result of a speed test using dotcom-tools.com after the CDN has been implemented, indicating a fast performance and a full page load within 1.05 seconds
Result of a speed test using dotcom-tools.com after the CDN has been implemented

Before the implementation of BunnyCDN, it took the website 3.82 seconds to laod. After? Just 1.05 seconds. We're talking about going from a sloth to a cheetah here, slashing the wait time by over 70%!

Setting up BunnyCDN with Ghost CMS

So, I was scrolling through the Ghost forum and bumped into this guide from 2021 about setting up BunnyCDN with Ghost. It's a good starting point, but you know how it is, things change. BunnyCDN's had a bit of a makeover since then. So, let's break down the steps I followed to get BunnyCDN working with all the latest features for a Ghost CMS site.

To get things started, go ahead and create a BunnyCDN account*.

Setting up your domains

To start things off, here is a brief overview of how BunnyCDN actually works: it grabs your website's content from an "origin URL" (in our case magicpages-co.mymagic.page), which is basically your website's home address. Then, BunnyCDN sets up a new subdomain (ending in *.b-cdn.net for BunnyCDN) to show a faster, cached version of your site from the nearest server to your visitor. Next, you just tell your main domain (magicpages.co for me) to use this new super-fast address. And voilà, your site's now supercharged!

For this to work, I'm assuming you've got a Ghost site all set up and linked to your main domain.

Next, you'll need to create a new (sub-)domain to act as the origin URL. Generally speaking, this URL will never be used, apart from BunnyCDN grabbing content for its cache. My origin URL is magicpages-co.mymagic.page. Link this domain to your Ghost site, but don't mess with the url setting in Ghost. Changing that can make your internal links go bust.

Basic configuration for BunnyCDN to work with Ghost CMS

Alright, now let's jump over to BunnyCDN and set up what they call a "pull-zone" – basically the control center of the new content delivery network for your website. Name your pull-zone (anything you like) and put that new sub-domain we talked about earlier into the "Origin URL" box.

Screenshot of a pull zone in the BunnyCDN dashboard, indicating the pull zone name as "magicpages-test.b-cdn.net" and the origin URL as "magicpages-co.mymagic.page"

You'll see a bunch of other settings on this page. Most of the time, you can just leave these as they are, unless you specifically want to choose options like picking a high volume tier or turning off certain areas of the world. When you're ready to go, hit that orange button at the bottom.

Next, BunnyCDN will show you an "Instructions" page. It'll talk about swapping URLs for static files. Honestly, I didn't bother with this step. In the final result, it didn't make a big difference for me. If you want to try it though, there's a helpful post by another Ghost user, if you're up for the challenge! Just know that Ghost uses the {{asset}} helper in themes to handle static files, so you basically need to rewrite some URLs in your proxy.

If you're like me and want to keep things simple, just click "Skip instructions" and move on.

Settings to make Ghost work as it should

Once you're in your BunnyCDN pull-zone, the first thing to do is head to the "Edge Rules" section. This is where we make specific rules that help BunnyCDN work with Ghost and its latest features.

Because here's the tricky part about using CDNs like BunnyCDN: they love to cache (or store) everything to make it load faster. In the end, that's exactly what you want, right? But if you're running a membership business on your Ghost site, caching everything isn't what you want. Picture this: one person logs in, BunnyCDN caches that page, and then the next visitor sees the first person's logged-in page. Not cool.

The same rule applies to the /ghost part of your site, where you do all your website editing and content creation. We don't want this section cached either, because it would make your content creation flow painfully complicated.

Now, let's get ahead and set up some edge rules to prevent those caching mishaps. On the "Edge Rules" page in BunnyCDN, look for the "Add New Rule" button. It's the orange one, you can't miss it.

Once you click on it, you'll need to fill in a few details. First, give your rule a name that makes sense to you. In the Action dropdown, pick "Override Cache Time," and then set the "Cache Time in Seconds" to 0. This means you're telling BunnyCDN not to store these pages. Keep the "Condition matching" on "Match any."

Now, here's the important part. We're going to add four conditions to make sure the right parts of your site don't get cached:

  • */ghost* (this keeps your editing area fresh)
  • */members* (so each member sees their own stuff)
  • */sitemap.xml (we don't want an outdated sitemap of your site)
  • */robots.txt (to keep the instructions for search engines up-to-date)
Screenshot of a edge rule setup in the BunnyCDN dashboard, indicating the action as "Override Cache Time", Cache Time In Seconds is set to 0, and as request URLs "*/ghost*", "*/members*", "*/sitemap.xml*", and "*/robots.txt" are selected

Alright, you're almost done with the edge rules. Save the one you just created and let's make another. Click "Add New Rule" again, and put in the same details as before. But this time, change the action to "Override Browser Cache Time." Save this rule too, and you can check edge rules off your list.

Now, head over to "Caching" -> "General". Here we need to turn off two settings:

  • Query String Sort: Turn this off. It's crucial for making sure your members can log in properly.
  • Strip Response Cookies: This also needs to be off. If it's on, you'll have trouble logging into your Ghost admin area.

Testing Your Setup to Make Sure Everything's Running Smoothly

Now, it's time to see if everything works. Let's do a quick test. Go to "General" and then "Hostnames" in your pull-zone. You'll see a hostname there ending in *b-cdn.net. Copy this and paste it into your web browser's address bar.

What you should see is your website, just as it normally looks. If it's not showing up right, there might be a hiccup in the settings we just did.

To dig deeper, open your browser's developer tools. You can usually do this by pressing F12, or right-clicking on the page and selecting "Inspect." Once there, find and click on the "Network" tab. This is basically where we can see all the communication between your web browser and the server. Now, with this tab open, refresh your website.

In the list requests, look for one that says member/. Click on it and go to the "Headers" section. In the "Response Headers," you want to find an entry that says Cdn-Cache: BYPASS.

Screenshot of the magicpages.co website with developer tools opened, indicating that the `members/` route serves a "Cdn-Cache" header with the value "BYPASS"

This is a good sign – it means that this part of your site isn't being cached by BunnyCDN, which is exactly what we want.

Linking Your Main Domain to BunnyCDN

Now it's time to bring your main website domain (in my case magicpages.co) into the BunnyCDN world. So far, we've only been working with the new origin URL and the *.b-cdn.net domain. Let's connect the dots.

Go to your BunnyCDN pull-zone settings and navigate to "General" -> "Hostnames." There, you'll see a field to enter your main domain. Type it in and click "Add hostname." BunnyCDN will then give you some steps to follow.

The main thing you need to do is update a CNAME record to point to your *.b-cdn.net hostname. After you've done that, make sure to hit the "Enable" button to set up an SSL certificate (to keep connections to your website secure) and turn on "Force SSL".

Screenshot of BunnyCDN's dashboard with magicpages.co as an additional linked hostname with SSL enabled and Force SSL turned on

And that's it! Your Ghost site and BunnyCDN are now working together. Visitors from anywhere in the world should see a speed boost when they visit your site.

Future Plans for Magic Pages: Boosting Performance for Everyone

Seeing such a huge improvement in speed, it's obvious that BunnyCDN is a game-changer, not just for me, but for everyone hosting their Ghost CMS websites on Magic Pages.

In the next few days, I'm want to figure out how to roll this out to all Ghost sites hosted with us. The main goal is to make sure it makes sense financially for the business and our customers. Stay tuned for more updates on this front!

A Quick Gotcha: Bunny Optimizer

BunnyCDN also offers "Bunny Optimizer" for any pull zones you create there. In their own words, this is what it does:

Bunny Optimizer helps maximize performance and reduce traffic usage. Automatically compress image sizes by up to 80%, optimize your images for desktop and mobile devices, minify CSS and JavaScript files and build your website with ease with on the fly image manipulation API.

So, that sounds cool, right? Automatically compressing images? I wanted to try how this works with Ghost, so I activated it.

Everything went smoothly – I didn't see any issues and images were indeed optimised. Only a few days later, I encountered a problem.

I wanted to log in on my Ghost site's admin panel. However, when visiting the /ghost route, I just got an endless loading animation. Upon inspecting the browser console, I saw that some Javascript files threw errors:

Uncaught SyntaxError: Unexpected token ':' (at vendor-f6856af9fcd8ab6533f2a4339ececbc8.js:1:99083)
chunk.761.5cfbe0d0f8ec7aefe7bc.js:1 Uncaught SyntaxError: Unexpected token ')' (at chunk.761.5cfbe0d0f8ec7aefe7bc.js:1:1739849)
ghost-0bd2fe0aa8d6ffee7bedfa95f6042159.js:1 Uncaught ReferenceError: define is not defined
    at ghost-0bd2fe0aa8d6ffee7bedfa95f6042159.js:1:14
(anonymous) @ ghost-0bd2fe0aa8d6ffee7bedfa95f6042159.js:1
ghost/:1 Unchecked runtime.lastError: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received

These were the errors that were thrown by Ghost, when enabling Bunny Optimizer and accessing the /ghost route

As a few days have passed since the activation of Bunny Optimizer, I didn't put one and one together right away, but a bit of trial and error put me in the right direction.

Bunny Optimizer isn't compatible with the /ghost route.

The solution is quite simple though. Go back to your Edge Rules and create a new one. This time, select "Disable Bunny Optimizer" as action and put */ghost* as request URL.

Now, I can access the Ghost CMS admin panel again 🎉


Links marked with * are affiliate links. Using these links to sign up at the individual services means that we get a commission. We always make sure there is no extra cost for you, though. Promise!

Built by Magic Pages customers

Magic Pages is proud to have helped so many amazing publications come to life. Here is a small selection of what our customers built on Magic Pages.

office laptop working

Ellie Mathieson

Digital Storefront
Google HQ

Big Idea Bible

Personal Blog
office laptops

Christine Trac

Newsletter