Kirby loves CDN
Set up custom components to deliver assets and files through a CDN.
In this recipe we will look into using a CDN with Kirby to deliver static assets and files. This is particularly relevant for website owners who address a worldwide audience.
Usually, all your assets live on your own web server and are thus served from a single location. This is fine as long as your website visitors all come from the same region where your webserver is located. However, if your site is intended for an international audience, the latency caused by long distances between webserver and visitor will hurt your website's performance massively.
A CDN––the acronym stands for Content Distribution Network––takes your assets and stores them on servers in different locations around the world. When a visitor requests your site, the CDN will locate the nearest available server and load all assets from there. This significantly reduces request times and your site will load faster no matter where your visitors come from.
CDNs work with so-called Zones, either Push or Pull Zones.
If you use a Push Zone, you upload all your assets via FTP or SSH to the CDN's servers and the CDN will spread them from there for you. This is great for static assets that don't change very often, or if you use a custom deploy script that automates the uploads for you when something changes. Once the Push Zone is created, you will get a public URL for your assets from the CDN, for example
Push Zones are often recommended or even required if you want to host files beyond a certain size.
A Pull Zone is the most common Zone type and easier to set up. With this method, the CDN automatically pulls content from your web server and caches it on the CDN's servers. Once the content is cached, visitor requests will be routed and delivered from the nearest possible server location.
So for example if your logo is located at
it will be requested from your Pull Zone like this:
The Pull Zone will fetch the logo on the first request and spread it across the network.
In this recipe, we will look at using a Pull Zone approach with KeyCDN, the CDN provider we also use on the Kirby website. However, this approach should also work similarly with other CDN providers.
The first step is to create a Pull Zone in your CDN provider's account settings. For KeyCDN you can find the instructions in their documentation in the chapter Create a Pull Zone.
Optionally, you can create a Zone Alias. Zone Aliases allow you to use your own custom CDN URL (e.g.
cdn.yourdomain.com) instead of the KeyCDN URL. For this to work, you have to add the Zone Alias as CNAME record in your DNS.
Head over to Create a Zone Alias if you want to do this and follow the instructions.
Once you have set up your Zone and an optional Zone Alias, you are ready to start working on the Kirby side of things.
On the Kirby side, we now have to make sure that the assets we want to serve from the CDN use the CDN's Zone URL instead of the ones linked to the website's domain, and this without us having to manually change each URL. We can achieve this with the
url component extension, which will take care of rerouting the relevant paths.
On a Kirby site there are typically two folders with files for which we would need to change the URL to point to a CDN:
Let's start with configuring the options for the CDN plugin in
config.php (if this file doesn't exist, create it in
Here we set two options: With the
cdn option we control if the plugin should route our assets through the plugin or not, so that we can easily disable it. With the
cdn.domain option, we set the domain for the Pull Zone we created above.
Let's start with the URL component for the static assets, leaving alone files from the media folder for the moment.
Without any limitations, the URL component would modify all Kirby URLs. Therefore, we first check if the
cdn option is enabled, and if that's the case, we want limit the routes to URLs in the
/assets path. We therefore check if the path matches the given regex pattern (i.e. if it begins with the
All other paths remain untouched. We use the original native
url component for all other paths, retrieving it via
Almost there! But hold on: you will notice that we added the original path after the CDN domain. However, what if our assets are updated? How will the CDN know that it has to fetch a new file? Keep on reading!
A problem when using CDNs is the lifespan of the assets on the network. When you upload a new
js file, it may take some time until the new file is updated across the network and this could result in unwanted effects.
This is where cache-busting is used to force the CDN to load the new version of a files once it has changed. The most common way of doing this is to add a version number or timestamp to the filename. There are different ways to achieve this. On the getkirby.com website, we do it with a plugin you can grab from the getkirby.com repo. If we put this plugin into the
/site/plugins folder, we can then modify the code above like this:
Cachebuster::path($path) method adds a hash to each asset, which will then look something like this:
Let's extend the plugin code in order to route the URLs to these files automatically through KeyCDN as well.
For this purpose, we have to create the
file::url components, and we also need a helper method that we use in both components. Here is the complete code with annotations for better understanding:
KeyCDN offers image processing via URL parameters. That means KeyCDN fetches the original file on first load and returns either the original (if we do not request a file version) or a modified version according to the parameters we pass along when requesting a thumb.
With this plugin in place, you can now use all image processing features supported by KeyCDN, by passing those parameters to the
thumb() method, which will give you a lot more options than Kirby's native processing.
<?php echo $page->image()->thumb(['width' => 300, 'negate' => true]); echo $page->image()->thumb(['width' => 300, 'height' => 300, 'crop' => true', 'blur' => 2]);
Using Kirby's shortcuts
bw() etc. is also still possible.