Five minute website hosting with Amazon S3 and CloudFront

Poplatek
Poplatek Blog
Published in
5 min readMar 7, 2018

--

by Jaakko Sipari

A cloud native from the Amazon

It’s trivial and fast to combine two Amazon services to get industry grade web hosting. And once it’s up, it just works. No servers to maintain.

Amazon’s first public service S3 is a robust key-value store. It provides an HTTP API and organizes the stored values (files) in so-called buckets. CloudFront is Amazon’s content delivery network. It currently has 103 edge locations in 24 countries all over the world.

If you have an Amazon Web Services account, you’re almost there already. It only takes a few commands with the AWS CLI tool. You can get there with AWS Console as well, but the command line makes the process repeatable via scripting.

Ok, I lied about the five minutes. It takes about 15 minutes for the CloudFront distribution to come online. You should be up and running after a few minutes of typing and 15 minutes of does-it-work-yet curling.

Prerequisites

To use AWS CLI you need to download it and run aws configure. It will ask for your access key, which you'll be able to create in the AWS Console (IAM -> Users -> [User] -> Security credentials -> Create access key).

The command line scripts have been tested with MacOS, but should work as-is with most Unix shells.

TL;DR

If you really only have five minutes, grab the commands below — just replace “my-website-bucket” with a unique S3 bucket name. This gives you an HTTPS-enabled website with all available AWS edge locations.

# Create the index page and another page for testing
mkdir website-files
echo Hello > website-files/index.html
echo Another page > website-files/another-page.html

# Make a bucket to host your files
aws s3 mb s3://my-website-bucket

# Copy the previously created files to the bucket with public access
aws s3 sync website-files s3://my-website-bucket/ --acl public-read

# Finally make the bucket available as a website
aws cloudfront create-distribution \
--origin-domain-name my-website-bucket.s3.amazonaws.com \
--default-root-object index.html

# Grab Distribution.DomainName from output of the previous command
# (have some patience, it can take some time for the site to pop up)
curl https://123abc123abc.cloudfront.net/

If you require a custom domain, check the end of this blog post for pointers.

The longer read

1) Prepare the content for the website

The minimalist’s website requires at least an index page, but we’ll add one extra page for testing. It doesn’t matter where the index page is located or how it’s named — the path inside the source bucket can be specified when creating the CloudFront distribution. Feel free to use a local directory which contains your existing website.

mkdir website-files
echo Hello > website-files/index.html
echo Another page > website-files/another-page.html

2) I has a bucket

The name of the S3 bucket needs to be globally unique across all buckets in Amazon S3. Otherwise the name isn’t too important — with CloudFront the name of the bucket is not visible to the website users. The S3 bucket is still accessible from the internet with a direct S3 URL. So don’t use anything too offending for the name :)

aws s3 mb s3://my-website-bucket

3) A bucketful of content

A whole website can be uploaded with the sync command — it also supports an ACL parameter for making the files publicly accessible. The default for all S3 uploads is to make the files private (accessible only for the owner of the bucket).

Note that it’s recommended to use the Bucket Policy for managing access control. Unfortunately it didn’t make a nice one-liner so we’ll be using the legacy ACL feature. Don’t worry, this doesn’t make your website insecure — though it will make your website’s files world readable also via the S3 URLs.

aws s3 sync my-website s3://my-website-bucket/ --acl public-read

4) Webify the bucket with CloudFront

Turning the S3 bucket into a website using CloudFront doesn’t require heavy lifting either. Just remember to point at an existing index file. The creation command doesn’t check for the existence of the file.

The command below will create a CloudFront distribution with the default values, which you might want to change later.

aws cloudfront create-distribution \
--origin-domain-name my-website-bucket.s3.amazonaws.com \
--default-root-object index.html

Make note of the fields Distribution.Id and Distribution.DomainName in the JSON object returned by the create-distribution command. You'll need the id for modifying the distribution.

AWS CLI provides means for changing the values with cloudfront get-distribution-config and cloudfront update-distribution commands. The catch is to only upload back the contents of the DistributionConfig JSON object. Naturally AWS Console also makes editing the distribution easy.

Some interesting default values to look into:

  • Price Class: Use All Edge Locations (Best Performance)
  • Use Default CloudFront Certificate
  • Viewer Protocol Policy: HTTP and HTTPS
  • Minimum TTL: 0
  • Maximum TTL: 31536000 (365d)
  • Default TTL: 86400 (24h)

5) Accessing the website

Use the Distribution.DomainName field from the output of the creation command to access your shiny new website.

curl https://123abc123abc.cloudfront.net/
curl https://123abc123abc.cloudfront.net/another-file.html

The index page should pop up when accessing the root path of the website, but any file in the bucket should be accessible given it’s full name. Note that accessing a non-existing page brings up an ugly XML error page — luckily we can create custom error responses for specific error codes.

Here’s an example of a populated CustomErrorResponses object for a CloudFront distribution configuration JSON:

"CustomErrorResponses": {
"Quantity": 1,
"Items": [
{
"ErrorCode": 404,
"ResponsePagePath": "/error.html",
"ResponseCode": "404",
"ErrorCachingMinTTL": 300
}
]
}

So that’s it! Or is it?

What’s missing

You probably noticed the hard-to-remember URL for our website. Getting and setting up a domain name and certificate for CloudFront are beyond the scope of this blog post. However, the steps required are:

  1. Purchase a domain name from your registrar or directly from Amazon Route 53
  2. Request a certificate with AWS Certificate Manager (it’s free!)
  3. Configure your DNS (preferrably Amazon Route 53) with a CNAME/ALIAS pointing at the generated CloudFront domain name
  4. Configure your CloudFront distribution with the domain name and certificate

If you need professional cloud native software development, don’t hesitate to contact us!

--

--