Point custom Netlify subdomain to S3 via CloudFront

I work on a hobby site, https://peepshowquot.es, which lets you search for your favourite quotes (in gif form) from Peep Show. Check it out!

I use Netlify for hosting the site, as it’s free, fast, and has great CLI tooling and GitHub integrations. But I use AWS S3 for hosting the gifs, as there are many gigabytes of them and they don’t need regular re-deployment.

I wanted to have these gifs available on the subdomain https://images.peepshowquot.es, rather than expose an obscure bucket URL in my application. It took a bit of wrangling – so here’s how I did it.

Create an S3 bucket

I already had an S3 bucket, but it needed to have the same name as the intended subdomain*. So I created one called images.peepshowquot.es and re-uploaded all my gifs into that. I also made it Public and readable by the world, though I can tighten up this security later.

* It’s possible this isn’t needed if you’re going down the CloudFront route – I originally just planned to point my subdomain to the S3 bucket directly, and this is a restriction I’d run into. But for SSL to work, I had to use CloudFront, which sits between my DNS and my S3 bucket, so possibly isn’t opinionated about the name of the bucket. Let me know in the comments if it wasn’t needed!

Create a certificate

Use AWS’ Certificate Manager to create your SSL certificate – you’ll need this to be able to connect via HTTPS. There’s some talk on the internet about this costing $600 per month, which gave me a heart attack, but that’s actually for private SSL certificates. All we need is a (free) public one.

Note that you MUST set your region to US East (N. Virginia) first, or you won’t be able to link it to your CloudFront distribution.

I used DNS for validation, taking the random code it gave me and appending .images to it, as my DNS provider would automatically append .peepshowquot.es to the end of that. So the Name ended up being _some-random-string.images.peepshowquot.es, and the Value was _some-other-random-string.jfrzftwwjs.acm-validations.aws. (note that there is a . at the end of the value – this may or may not be important so I made sure I kept it in).

It didn’t take long for the SSL certificate to go from Pending to Issued.

Create a CloudFront distribution

Go to CloudFront and create a new distribution, using mostly the default settings, but obviously selecting your S3 bucket for the Origin Settings, and your custom SSL certificate in the SSL section.

I also switched away from a couple of the defaults where it seemed to make sense, e.g. allow ‘Compress Objects Automatically’ (reduces data sent over the wire, which is what you’re charged for, so why wouldn’t you?) and ‘Use only U.S., Canada and Europe’ for Price Class (I don’t expect much traffic outside these countries).

Check it works

I visited https://my-random-distribution-ID.cloudfront.net/s1/e1/gifs/1.gif and verified that a) it connected over HTTPS and b) I was looking at a gif. 🎉

Now all that was left was to hook it up to a custom domain.

Point domain to CloudFront

This was surprisingly simple in the end – create a CNAME record with Name images.peepshowquot.es and Value my-random-distribution-ID.cloudfront.net. After waiting a few moments, I loaded up https://images.peepshowquot.es/s1/e1/gifs/1.gif successfully.