Search code examples
amazon-web-servicesamazon-s3amazon-cloudfront

How do you set a default root object for subdirectories for a statically hosted website on Cloudfront?


How do you set a default root object for subdirectories on a statically hosted website on Cloudfront? Specifically, I'd like www.example.com/subdir/index.html to be served whenever the user asks for www.example.com/subdir. Note, this is for delivering a static website held in an S3 bucket. In addition, I would like to use an origin access identity to restrict access to the S3 bucket to only Cloudfront.

Now, I am aware that Cloudfront works differently than S3 and amazon states specifically:

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.

As such, even though Cloudfront allows us to specify a default root object, this only works for www.example.com and not for www.example.com/subdir. In order to get around this difficulty, we can change the origin domain name to point to the website endpoint given by S3. This works great and allows the root objects to be specified uniformly. Unfortunately, this doesn't appear to be compatable with origin access identities. Specifically, the above links states:

Change to edit mode:

Web distributions – Click the Origins tab, click the origin that you want to edit, and click Edit. You can only create an origin access identity for origins for which Origin Type is S3 Origin.

Basically, in order to set the correct default root object, we use the S3 website endpoint and not the website bucket itself. This is not compatible with using origin access identity. As such, my questions boils down to either

  1. Is it possible to specify a default root object for all subdirectories for a statically hosted website on Cloudfront?

  2. Is it possible to setup an origin access identity for content served from Cloudfront where the origin is an S3 website endpoint and not an S3 bucket?


Solution

  • UPDATE: It looks like I was incorrect! See JBaczuk's answer, which should be the accepted answer on this thread.

    Unfortunately, the answer to both your questions is no.

    1. Is it possible to specify a default root object for all subdirectories for a statically hosted website on Cloudfront?

    No. As stated in the AWS CloudFront docs...

    ... If you define a default root object, an end-user request for a subdirectory of your distribution does not return the default root object. For example, suppose index.html is your default root object and that CloudFront receives an end-user request for the install directory under your CloudFront distribution:

    http://d111111abcdef8.cloudfront.net/install/

    CloudFront will not return the default root object even if a copy of index.html appears in the install directory.

    ...

    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.)

    2. Is it possible to setup an origin access identity for content served from Cloudfront where the origin is an S3 website endpoint and not an S3 bucket?

    Not directly. Your options for origins with CloudFront are S3 buckets or your own server.

    It's that second option that does open up some interesting possibilities, though. This probably defeats the purpose of what you're trying to do, but you could setup your own server whose sole job is to be a CloudFront origin server.

    When a request comes in for http://d111111abcdef8.cloudfront.net/install/, CloudFront will forward this request to your origin server, asking for /install. You can configure your origin server however you want, including to serve index.html in this case.

    Or you could write a little web app that just takes this call and gets it directly from S3 anyway.

    But I realize that setting up your own server and worrying about scaling it may defeat the purpose of what you're trying to do in the first place.