Swiftory project, I needed an easy place to host 200+ images and several Javascript source files while optimizing for fast delivery performance.
Most services like Vercel (the platform this website is hosted on) have a Content Delivery Network (CDN) built-in. One of my goals was to keep the project’s deploys as light as possible and offload resources to an external bucket on Backblaze’s B2 cloud storage service.
Unfortunately, buckets are limited to a singular geographical location and don’t have any caching layer to reduce bandwidth consumption. Backblaze already has this covered though, with a complete tutorial on how to connect their storage service with Cloudflare’s CDN.
It missed one thing, though: Setting proper caching headers on the B2 bucket.
Without those headers, every time I loaded resources through the Cloudflare-proxied URLs, they wouldn’t be included in Cloudflare’s cache and still load directly from the B2 bucket. Useful for development mode, but missing my ultimate goal.
I’ll go over the basic steps to set up B2 and Cloudflare properly, with that ✨cache header config spice✨ at the end.
I recommend following Cloudflare’s official guide for this, they cover the most up-to-date steps to make sure your domain is properly set up with their service.
Ensure that the “SSL/TLS encryption mode” for the domain is at least set to Full
. I’ve had success with Full (strict)
as well.
public-cdn
.https://f000.backblazeb2.com
. Hold on to this for the next part.f000.backblazeb2.com
.cdn
, which will result in cdn.ansonlichtfuss.com
.One gotcha with this setup is that any B2 bucket is now accessible through this new CDN URL. Let’s lock that down.
https://DOMAIN/file/BUCKET_NAME/*
, where DOMAIN is your custom domain (mine is cdn.ansonlichtfuss.com
), and BUCKET_NAME is the name of your B2 bucket (mine is public-cdn
). The setting should be “Cache Level” and set to “Standard”.https://DOMAIN/file/*/*
, where DOMAIN is your domain name.302 - Temporary Redirect
option selected, and forwards users to https://secure.backblaze.com/404notfound
.Important: Once both rules are created, make sure the first rule with the “Cache Level” setting is above the wildcard rule, to ensure it is executed first.
This is the one missing piece that ties it all together. Without setting a proper caching header, the Cloudflare CDN will never cache any of the files it serves and instead will pull from the B2 bucket every time. Once the cache header is set, Cloudflare reads the header and will immediately start caching the files to be served more efficiently from its geographically optimized CDN.
{"cache-control":"max-age=7200"}
Once these settings are saved and propagated, the new header will appear on responses from the bucket and will trigger Cloudflare to begin caching your files.
Using that file you previously uploaded in the bucket in Step 2, navigate to it at your new custom CDN domain URL. After a couple of refreshes, you should see the response header “cf-cache-status” value set to HIT
, signaling the global cache is now working properly.