Created: Apr, 2016
This tutorial shows the work flow of building a HTTPS-enabled static website hosted on AWS S3, with the option of using a continous integration (CI) service like Wercker. Different from a previous post, I need to use Amazon CloudFront for content delivery.
// Beginning of TL;DR
There may be a few questions to be answered before you are convinced that this is a tutorial for you.
The first question is why I should have a HTTPS-enabled static website in the first place. While a static website has much less potential security issues compared with a dynamic site (which is one of the reasons behind the revival of static websites in recent years), I give two major benefits:
The second is why to pay the money and host on AWS S3 instead of simply hosting with a free service like Github Pages. There is nothing wrong with Github Pages which I loved and used (and still do) for a long time. Github Pages has the advantage of being much easier to bring it up and working compared to the AWS S3 solution. In fact this site is still hosted on Github Pages. But there are several things to notice:
The third is why to use a CI service. This one is obvious: the process chain to be described below is still non-trivial, and use a CI service like Wercker can save lots of process overhead and make you focus on the content in long run. In some sense, CI service is a must for AWS S3 static website hosting.
To conclude, there are pros and cons on both sides. Make the decision based on your needs.
// End of TL;DR
Obviously, you need to register for an AWS account if you haven’t. AWS provides a bunch of services and the number is growing, but below is a subset for this tutorial:
Here I build a static website with the domain name “example.com”.
Some part of the this step is similar to the instructions in this example. The difference is the use of Route 53 is optional.
Pricing-wise, you will be charged for storage in S3 and traffic from CloudFront. This pricing model favors sites with high traffic because HTTP requests are much cheaper for CloudFront than S3.
The steps are:
Create buckets “example.com” similar to the previous post.
Upload a test index page “index.html” to the root directory of bucket “example.com”.
Add bucket policy
{
"Version":"2012-10-17",
"Statement":[{
"Sid":"PublicReadGetObject",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::example.com/*"
]
}
]
}
It is optional to enable website hosting for the S3 bucket, but it is still a good idea to do so in some circumstances (see Step 2).
Log in AWS Certificate Manager (ACM) to request a SSL certificate as described in this post. Amazon will send email to the administrative email address in the whois information of example.com, and to [email protected] for domain owernship verification. So make sure at least one of these emails works.
I usually request a SSL certificate for the “naked” domain example.com
, and the first-level wildcard subdomains *.example.com
. The SSL certificate can be quickly granted.
After the SSL certificate is granted, log in the CloudFront and add a web distribution. In the “SSL certificate” section, select “Custom SSL Certificate” and select the SSL certifcate just created in ACM. And set “Default Root Object” to “index.html”. Also, set viewer protocol policy as “redirect HTTP to HTTPS” to enforce SSL connection.
At last, enable this distribution, and wait for a while as the files being deployed to different CDN data centers, till the status turns “Deployed”. While waiting, proceed to the next step.
There are many ways:
Use Route 53. After delegating “example.com” to Route 53, create an A record of “@” with alias pointing to the CloudFront endpoint. And then create a CNAME record of “www” pointing to “example.com”. The result is, all of https://example.com/
, https://www.example.com/
, http://example.com/
and http://www.example.com/
will be visitable as is.
Or, use custom DNS. Create a CNAME record “www” and point it to the cloudfront URL (something like abcde12345.cloudfront.net). Set a redirect rule to redirect example.com
to www.example.com
. The problem with this approach is https://example.com/
can not be correctly redirected to https://www.example.com/
.
However, there is a caveat about CloudFront CDN service: CloudFront cannot resolve the default root object of subdirectories as index.html
. For example, if there is a webpage at https://www.example.com/project/index.html
, this link https://www.example.com/project/
will return “access denied” error. To circumvent this quirk, enable web hosting on the source S3 bucket, and use its full URL (something like www.example.com.s3-website-us-east-1.amazonaws.com
) as the origin. In that way, visiting https://www.example.com/project/
will actually go to www.example.com.s3-website-us-east-1.amazonaws.com/project/
first and fetch the index.html (since S3 support the default root object resolving of index.html). However, to some degree, this reduce the effectiveness of using a CloudFront CDN. But this is a work-around for AWS S3 + CloudFront solution.
Note that CloudFront supports GZip compression, so don’t forget to enable it for better loading speed.
The above steps should already give you a working HTTPS-enabled website. This step is about continuous integration which makes developing and deploying the website easier. This step is identical to Step 2 and Step 3 in the previous post.