I Built My Own Content Delivery Network

I wanted to consolidate content while keeping everything under my control as much as possible. And who doesn’t need an excuse to geek out a little bit?

Background

I use weblog.lol, part of the fabulous omg.lol family of services provided by Neatnik, to host several blogs (including this one). At present I am using three different services to host content online: Flickr for photographs, some.pics for other image files, and Amazon S3 for everything else (PDFs mostly, but also some audio and video).

There are a few problems with this arrangement.

  1. Flickr doesn’t really like to be your CDN. Their terms of service forbid using “Flickr as a generic image hosting service for banner advertisements, graphics, etc.” Does that mean it’s okay to use it as a generic photo hosting service? I don’t know, I’m no lawyer.
  2. Although Flickr does automatically resize photos to a variety of sizes, it’s a pain in the butt to grab all the distinct URLs that Flickr generates for each one.
  3. Using some.pics as a generic image hosting platform violates the spirit of that service, which is to be a sort of lightweight photo sharing service à la Instagram (in the old days).
  4. Managing content on some.pics is clunky, to say the least. File names have abstruse names and there’s virtually no structure to how content is stored. It wasn’t designed for this.
  5. Neato, a new content management system from Neatnik, is coming soon and will succeed weblog.lol. There are no details yet, but I want to be prepared for a significant amount of disruption when it arrives. I’d like my content to be in some neutral place.
  6. I don’t like having content spread out across three different platforms.

Why build your own?

Setting up my own CDN seemed like a good idea. So why build my own when there are services like Cloudflare and Bunny that do this for cheap? I’m a nerd who also happens to be certified as an AWS architect and this is just the kind of thing that’s fun for me.

What does it need to do?

The problem I was trying to solve was pretty simple:

How?

I started with an AWS blog post, which pretty much spells out all the details. I first needed to obtain or create some requisite resources:

Then there was the matter of creating and configuring the Amazon CloudFront Distribution itself, which includes:

How does it work?

  1. It starts with an HTTP request for some content, e.g. https://cdn.mihobu.lol/img/demo.png?width=500.
  2. The URL rewrite function converts the requested location into a path the CDN can use: /img/demo.png/width=500.
  3. Since this is a request for an image, a Behavior that maps paths match /img/* to an Origin Group.
  4. The Origin Group tells the CDN to look in the image transform bucket to see whether the requested object (/img/demo.png/width=500) already exists. If it does, the CDN serves it up.
  5. If the transformed image does NOT exist, the Origin Group fails over to the second Origin in the list. This is the image transformer Lamdba Function.
  6. The Lambda Function receives the request and looks in the original content bucket for the original image (/img/demo.png). If found, the image is resized to match the requested dimension(s). The resized image is stored in the transform bucket using the converted path (/img/demo.png/width=500) and then returned to the requester.

Requests for content other than images are straightforward:

  1. HTTP request for a file.
  2. If the file exists in the original content bucket, it is served up.

What will this cost?

As long as my traffic volume remains very small like it is today, this should cost next to nothing. S3 storage is suuuuuuuuuper cheap, and the CloudFront costs don’t really begin to pile up until you get into many thousands of requests and many gigibytes of data transfers. I’ll keep an eye on it an report back in a few months.

What’s next?

I’ve begun the process of migrating content, but it’ll take me some time to update all my blog pages and posts. There’s also the X-factor that is Neato. I expect some change then, so I don’t intend to move too fast until I know more about the extent of the impact.

This is admittedly a pretty advanced (and let's face it, totally unnecessary) thing for me to have done. I didn’t intend this as a tutorial so much as a description. Besides, I don't recommend this to most people. But it was fun and if you’d like to know more I’d be glad to chat with you about it.