Quickstart Hosting Static Site on AWS Part 1: Infrastructure

I don’t know about you, but when I get bored I like to read AWS whitepapers, it’s a very relaxing Sunday teatime activity.

One of the more recently read ones was the whitepaper on hosting static websites on aws, it covers pretty in-depth the best practices to hosting static sites, including CI/CD processes. Highly recommend it to anyone with a couple of minutes to spare.

dryrun.cloud is a static site generated using Jekyll and hosted on AWS. Up until now the setup was fairly rudimentary, manually created Route53 DNS records, s3 bucket, and CloudFront distribution. The deployment process was also manual using jekyll build and aws s3 sync.

I can’t really be writing about automation if my own infrastructure is not automated end to end. As I embark on this journey, I figured I’d share my experiences and create a possible quickstart guide. Buckle up and here we go!

This first part of the article will cover creating the infrastructure backbone, and Part 2 will be about CI/CD.

The github repo includes a master CloudFormation template that bundles up independent stacks:

  • CloudFront distribution with s3 bucket as origin
  • [Optional] WebACL with a suite of security automations
  • [Optional] IP restricted staging environment

Additionally includes separate template for:

  • ACM SSL certificate


  • Route53 hosted zone for the domain you want your static site to be hosted on. [1]
  • Means to verify e-mail sent out by ACM. [2]


Deploy the acm-certificate.template stack first, make sure you do it in US East (N. Virginia).

Certificate parameters

This will issue a certificate for both www.{domainName} and {domainName}

Grab the CertificateArn from Outputs tab and save it for the next step.

Now onto deploying the master.template

Quite a few parameters are needed, the defaults should be fine for most of them (if you want the full setup with WAF included)

Master parameters

Use the ACM Certificate ARN obtained from previous step.

If you don’t want to use WAF then set Configure WAF to no and keep in mind that the CloudFront Access Log Bucket has to exist before deploying this stack.

If you already have a WebACL with security automations configured, set Provision Security Atuomations to no and use the id of the WebACL that you want to re-use.

To read more about the WAF Security Automations I recommend giving aws security automation quickstart a read through.

Once you launch the stack it can take up to 40 minutes for all the resources to create.

Depending whether you selected to also create a staging environment you will end up with 2 buckets:

  • live.{DomainName}
  • staging.{DomainName}

Both of them have been configured with default IndexDocument: index.html

If you want to be more autonomous I recommend forking this repo and adjusting the parameter files under /parameters/ folder.

Then you can just use the Makefile to deploy/update the stack:

# To create stack
make STACK_NAME=staticsite-demo STACK=master PARAM_PATH=`pwd`/parameters REGION=us-west-1 create
# To poll for events
make STACK_NAME=staticsite-demo STACK=master REGION=us-east-1 watch
# To see the stack outputs
make STACK_NAME=staticsite-demo STACK=master REGION=us-east-1 output
# To update the stack
make STACK_NAME=staticsite-demo STACK=master PARAM_PATH=`pwd`/parameters REGION=us-east-1 update
# To delete the stack
make STACK_NAME=staticsite-demo REGION=us-east-1 delete

This works with any template that has an associated parameter file. Alternatively, you can keep the parameters in a completely separate repository and just point PARAM_PATH to the right place.

Tips & gotchas

If you visit the live site before the DNS has fully propagated within AWS CloudFront, you might get a 307 Temporary Redirect, so I recommend waiting 20-30 minutes before visiting the site after the stack has been deployed.

If you do end up with 307 and don’t want to wait 24h for cloudfront cache to clear you will have to Create a CloudFront invalidation for * to forceclear the DNS cache.

WAF can be a bit expensive if all you really host is a static site. Please make sure you check out the Pricing model before deploying anything.

[1] http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/creating-migrating.html

[2] http://docs.aws.amazon.com/acm/latest/userguide/setup-email.html