Hosting static Website with S3 bucket and CloudFront CDN

2 minute read , Oct 31, 2016

Amazon AWS offers convenient way for hosting static website via S3 bucket providing CDN caching and SSL encryption using CloudFront.

S3 bucket

First we need to create S3 Bucket for the files and bucket access policy for public read access. Create the policy.json file with following content:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

We also enable the Static website hosting feature on the bucket, select Enable website hosting and set index.html in the Index document field. If we create the following website.json file:

{
  "IndexDocument": {
      "Suffix": "index.html"
  }
}

and put the above policy into policy.json file then we can do all this from the command line using AWS CLI tools:

$ aws s3api create-bucket --bucket my-bucket --region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1
$ aws s3api put-bucket-policy --region eu-west-1 --bucket my-bucket \
--policy file://policy.json
$ aws s3api put-bucket-website --region eu-west-1 --bucket my-bucket \
--website-configuration file://website.json
$ aws s3api put-bucket-versioning --region eu-west-1 --bucket my-bucket \
--versioning-configuration Status=Enabled
$ aws s3 ls

We also enable versioning on the S3 bucket so we can roll back if necessary.

CloudFront CDN

Next is the CloudFront CDN setup. For the General Section first:

Distribution ID: XXXXXXXXXXXXXX
ARN: arn:aws:cloudfront::xxxxxxxxxxxx:distribution/XXXXXXXXXXXXXX
Log Prefix: -
Delivery Method: Web
Cookie Logging: Off
Distribution Status: Deployed
Comment: -
Price Class: Use All Edge Locations (Best Performance)
AWS WAF Web ACL: -
State: Enabled
Alternate Domain Names (CNAMEs): myapp.mydomain.com
SSL Certificate: <SSL_CERT_ARN>
Domain Name: xxxxxxxxxxxxxx.cloudfront.net
Custom SSL Client Support: Only Clients that Support Server Name Indication (SNI)
Supported HTTP Versions: HTTP/2, HTTP/1.1, HTTP/1.0
IPv6: Disabled
Default Root Object: -
Last Modified: 2016-10-31 13:59 UTC+11
Log Bucket: - 

Replace the <SSL_CERT_ARN> with a valid certificate ARN already uploaded for the account.

The Origins Section:

Origin Domain Name: my-bucket.s3-website-eu-west-1.amazonaws.com
Origin Path:
Origin ID: S3-my-bucket/static
Origin Type: Custom Origin
Origin Access Identity: -
Origin Protocol Policy: HTTP Only
HTTPS Port: 443
HTTP Port: 80

The Default Cache Behavior Settings:

Path Pattern: Default (*)
Origin: S3-my-bucket/static   
Viewer Protocol Policy: Redirect HTTP to HTTPS
Allowed HTTP Methods: GET, HEAD   
Cached HTTP Methods: GET, HEAD (Cached by default)

Forward Headers: Whitelist
Whitelist Headers:
3 header(s) whitelisted:
Access-Control-Allow-Origin
Authorization
Origin
 
Object Caching: Use Origin Cache Headers
Minimum TTL: 0   
Maximum TTL: 31536000       
Default TTL: 86400
 
Forward Cookies: None
Query String Forwarding and Caching: None
Smooth Streaming: No
Restrict Viewer Access
(Use Signed URLs or
Signed Cookies): No
Compress Objects Automatically: No

The forwarded headers will be needed in case we want to setup CORS on the bucket to tighten up our website security.

Route53 DNS Record

Create an A ALIAS Record cdn.mydomain.com pointing to the domain name of the CloudFront Distribution xxxxxxxxxxxxxx.cloudfront.net.

Application Changes

Edit the app so it loads all assets from cdn.mydomain.com and set that URL as default path for all static content.

CORS

If we need CORS support in the S3 bucket, we need to add some CORS rules under Permissions -> CORS Configuration, for example:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>https://mydomain.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>https://*.mydomain.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>

On the CloudFront side we select OPTIONS under Cached HTTP Methods and configure CloudFront in the Whitelist Headers section to forward the Origin, Access-Control-Request-Headers and Access-Control-Request-Method headers.

Tags: ,

Categories:

Updated:

Leave a Comment