Setting up cloudfront with S3

I received 25$ from amazon for taking a survey and wanted to experiment with setting up a content delivery network (CDN) with cloudfront. Those who aren't familiar, a CDN enables the ability to deliver web content based on geographic locations of request or users which should enable speedier response times. Being a software guy, I wasn't quite sure on how amazon's S3 interacts with cloudfront and the effect it would have on my deployment process. I ran across amazon's article hosting static websites and the image below cleared things up on how the infrastructure works together.

Cloudfront S3 Infrastructure

Setting up cloudfront

Following the how set up cloudfront and S3 step by step instructions and within thirty minutes or so I had a distribution set up. I specified the default root object to be index.html and assumed it had the same behavior as S3. Navigating to custom cloudfront domain [abc.cloudfront.net] the main page rendered while each subfolder received the following access denied error:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
   <Code>AccessDenied</Code>
   <Message>Access Denied</Message>
   <RequestId>178F955646D32DA3</RequestId>
   <HostId>G5K2aiCnFd1DaKZMdE+9mbsOxsbOsk2dGHVEZCWocIRvQyP8YGC2CKsoj4UZyU3t</HostId>
</Error>

First instinct was a permissions issue between cloudfront and S3 but after a little investigation I was able to provide the full path to the index.html page and it rendered as expected. LUL is generated with jekyll which supports flexible ways to build your site's URLs with permalinks. Just about every page has a clean URL where I want the index document to be rendered by default. The test results look something like this:

http://<cloudfrontURL>/ <- works
http://<cloudfrontURL>/index.html <- works
http://<cloudfrontURL>/java/examples/ <- didn't work
http://<cloudfrontURL>/java/examples/index.html <- works

CloudFront default root objects

After some research cloudfront handles default root objects a bit different than S3.

The behavior of CloudFront default root objects is different from the behavior of Amazon S3 index documents. When you configure an Amazon S3 bucket as a website and specify the index document, Amazon S3 returns the index document even if a user requests a subdirectory in the bucket. (A copy of the index document must appear in every subdirectory.) For more information about configuring Amazon S3 buckets as websites and about index documents, see the Hosting Websites on Amazon S3 chapter in the Amazon Simple Storage Service Developer Guide.

Custom origin vs S3 bucket

To fix this, there was a thread on how to render S3 subfolders but it wasn't completely clear. I first deleted the cloudfront distribution and set up a custom distribution that would point directly at the S3 website URL which looks something like www.example.com.s3-website-1.amazonaws.com. Setting up a custom distribution allows you to leverage S3's default index/error object while not needing to set up a CloudFront default root object. That did the trick!

The configuration looks similar to the screenshots below. You will notice once you provide the URL it will append "custom" to origin name.

Pointing directly to S3 bucketCustom origin
Cloudfront S3 Bucket Distribution Cloudfront Custom Bucket Distribution