Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save charlesroper/f2da6152d6789fa6f25e9d194a42b889 to your computer and use it in GitHub Desktop.
Save charlesroper/f2da6152d6789fa6f25e9d194a42b889 to your computer and use it in GitHub Desktop.
How to setup a practically free CDN

How to setup a practically free CDN using Backblaze B2 and Cloudflare

⚠️ Note 2023-01-21
Some things have changed since I originally wrote this in 2016. I have updated a few minor details, and the advice is still broadly the same, but there are some new Cloudflare features you can (and should) take advantage of. In particular, pay attention to Trevor Stevens' comment here from 22 January 2022, and Matt Stenson's useful caching advice. In addition, Backblaze, with whom Cloudflare are a Bandwidth Alliance partner, have published their own guide detailing how to use Cloudflare's Web Workers to cache content from B2 private buckets. That is worth reading, but I thought it important to note in particular this statement at the top of that article should there be any doubt as to whether using Cloudflare's CDN is permitted or not: "Please Note: Cloudflare can be used as a CDN for a B2 bucket without workers if the bucket is public, not private."

I've been using Backblaze for a while now as my online backup service. I have used a few others in the past. None were particularly satisfactory until Backblaze came along.

It is keenly priced at a flat $7 per month (or $70 a year) for unlimited backup (I've currently got just under half a terabyte backed-up). It has a fast, reliable client. The company itself is transparent about their operations and generous with their knowledge sharing. To me, this says they understand their customers well. I've never had reliability problems and everything about the outfit exudes a sense of simple, quick, solid quality. The service has even saved the day on a couple of occasions where I've lost files.

Safe to say, I'm a happy customer. If you're not already using Backblaze, I highly recommend you do.

Taking on the big boys with B2

So when Backblaze announced they were getting into the cloud storage business, taking on the likes of Amazon S3, Microsoft Azure, and Google Cloud, I paid attention. Even if the cost were the same, or a little bit more, I'd be interested because I like the company. I like their product, and I like their style.

What I wasn't expecting was for them to be cheaper. Much cheaper. How about 400% cheaper than S3 per GB? Don't believe me? Take a look. Remarkable.

What's more, they offer a generous free tier of 10 GB free storage and 1 GB free download per day.

If it were any other company, I might think they're a bunch of clowns trying it on. But I know from my own experience and following their journey, they're genuine innovators and good people.

Using B2

B2 is pretty simple. You can use their web UI, which is decent. Or you can use Cyberduck, which is what I use, is free, and of high quality. There is also a command-line tool and a number of other integrated tools. There is also a web API, of course.

Setting up a vanity URL

You can set up a "vanity" URL for your public B2 files. Do it for free using CloudFlare. There's a PDF [1.3 MB] documenting how.

Using CloudFlare CDN to cache B2 hosted files

You can also configure CloudFlare to aggressively cache assets served by your B2 service. It is not immediately obvious how to do this, and took a bit of poking around to set up correctly.

By default, B2 serves with cache-invalidating headers: cache-control:max-age=0, no-cache, no-store, which causes CloudFlare to skip caching of assets. You can see this happening by looking for the cf-cache-status:MISS header.

To work around this problem, you can use CloudFlare's PageRules specifying an "Edge cache expire TTL". I won't explain what that means here as it is covered in-depth on the CloudFlare blog.

So, to cache your B2 assets, you need to create a PageRule that includes all files on your B2 domain. For example:

files.silversuit.net/*

You then need to add your cache settings. I have Cache Level set to Cache Everything; Browser Cache TTL set to a year; Edge Cache TTL set to 7 days. I'm caching aggressively here, but you can tweak these settings to suit. Here's a screenshot:

Screenshot showing PageRules settings

To check that it's working correctly, use DevTools to look for the cf-cache-status:HIT header:

Screenshot showing a CloudFlare cache hit

Wrapping up

So, with that, you're making use of already very inexpensive B2 storage coupled with CloudFlare's free CDN to serve your assets almost entirely for free. And it's not like these are rinky-dink services that are going to fall over regularly; these are both high-quality, reputable companies.

What a time to be alive, eh?

@charlesroper
Copy link
Author

Glad you like it. The way it works is by adding your own domain in front of buckets using Cloudflare (as documented in the linked PDF). I'm not sure if it's possible to do the full setup via API (you'd need to use Cloudflare's API as well as B2's).

@jmonster
Copy link

jmonster commented Aug 7, 2021

I'm running into a gotcha with this after 60 seconds where CF is revalidating even though the object isn't stale. I've posted at https://community.cloudflare.com/t/im-seeing-revalidate-after-60-seconds-when-using-backblaze-regardless-of-headers/292652/7

Anyone else notice this?

It turns out I had a Worker configured for the same domain and it was causing all sorts of weirdness :| All good now!

@tstevens
Copy link

tstevens commented Jan 15, 2022

Did basically the same thing recently but came across a few tips that might be helpful to others.

First, you can configure the cache-control headers originating at the B2 on a per bucket basis (along with at the per file basis at upload). After doing this Cloudflare should respect the headers by default and use that to cache your content in the CDN without needing to use up a Page rule. Instructions do this can be found here. Also, it looks like Backblaze tweaked their cache header policy recently. Specifically buckets created after Sept 8, 2021 no longer include any cache control headers by default, those created before that date still do.

Next, the Backblaze instructions warn that you will want to configure Cloudflare to only allow your buckets to be fetched from your domain. They recommend using a page rule to accomplish this, which does work but I found another option which saves you a page rule. Instead I used a Transform rule, specifically a URL Rewrite configured to prefix the bucket path to all requests for the Backblaze B2 backed domain. The URLs change to only include the asset you want to retrieve from the B2 bucket, excluding the bucket path. For example, files.silversuit.net/file/silversuit/charles-roper.jpg becomes files.silversuit.net/charles-roper.jpg.

On the Cloudflare domain page under Rules > Transform Rules > URL Rewrite > Create transform rule > URL Rewrite

Name:
B2 Rewrite rule

When incoming requests match…
Enter the following:
Field:Hostname Operator:equals Value:[your domain name ex files.silversuit.net]

Path:
Select: Rewrite to...
Select: Dynamic
Enter: concat("/file/[your bucket name here ex silversuit]", http.request.uri.path)

Query
Preserve

@DotDotJames
Copy link

super solid use case / write up as big fan / user of both Backblaze & Cloudflare for multiple projects / companies - thanks for this!

@NWoodsman
Copy link

Pricing is $7 monthly, so you have to purchase 24 months to get the rate of $5.80/mo. Either way, you listed out of date pricing.

@Dom4n
Copy link

Dom4n commented Jan 15, 2022

Last revision of this gist is from Aug 19, 2019. I strongly believe that pricing was lower back then.

@eriklott
Copy link

eriklott commented Jan 16, 2022

I'm sure the folks on the Cloudflare community forum would tell you it's fine to use the Cloudflare CDN to serve Backblaze content, as long as that content is a static website or other html related files. If you're serving primarily media assets (images, audio, video) through the Cloudflare CDN from Backblaze, you're likely in violation of term 2.8 Limitation on Serving Non-HTML Content, and run the risk of having your account shut down if you generate any serious traffic.

https://www.cloudflare.com/en-ca/terms/

You can, however, use Cloudflare Workers to serve your Backblaze media content without issue.

@innerop
Copy link

innerop commented Jan 16, 2022

<<You can, however, use Cloudflare Workers to serve your Backblaze media content without issue.>>

I couldn't find any info on the Cloudflare EULA to determine if that's the case. I do know that Cloudflare's Workers+R2 won't let you serve video (not without shutting down your account when you generate serious traffic)

Cloudflare has a separate video serving solution that costs a lot more. I hope to be proven wrong. @eriklott

@eriklott
Copy link

Yes, with Workers you're okay to deliver media files other than video. If you're serving video, Cloudflare wants you to use the dedicated video streaming product

@oprtask-rb
Copy link

Are you saying you are allowed to cache files with Workers (everything other than video)?

@edwinosky
Copy link

concat

Thank you very much for your contribution

@learyjk
Copy link

learyjk commented Jan 17, 2023

Link for vanity URL in cloudflare is broken 😢.

@charlesroper
Copy link
Author

@learyjk I've fixed the broken link.

@charlesroper
Copy link
Author

@tstevens Thanks for the tips! I've just done this and it works great. Example:

https://cdn.charlesroper.com/Configuring%2BCloudflare%2Band%2BB2.pdf

Your link to Backblaze's article was broken, so I updated with an archived version. However, I think this is the same and more recent:

https://help.backblaze.com/hc/en-us/articles/360010017893-Delivering-Backblaze-B2-Content-Through-Cloudflare-CDN

@wassim0asaad
Copy link

Yes, with Workers you're okay to deliver media files other than video. If you're serving video, Cloudflare wants you to use the dedicated video streaming product

great info >i'm building movies website .using B2 backblaze bucket for files .is it possible to serve the files throw cloudflare R2 .it look like the cheapest option out there >searching for this for months ,,,hope if you can help with your knowledge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment