Deploy Static website easily using AWS S3/Cloudfront with Terraform

Nicolas Lagier
Healint-Engineering&data
3 min readJan 27, 2021

The modern way of developing a website now mostly consists of developing an Html/js/CSS app on one side and some API (mostly restful) on the other side. The days of generating Html from some backend technology seem to be mostly behind us. This post describes a simple way to easily manage the Html app deployment on AWS using Terraform.

Architecture

The architecture is fairly simple it involves 2 main services:

  • AWS S3: this is the service on which the assets should be uploaded
  • AWS CloudFront: this is the service that will take care of caching in locations close to the final user, in order to ensure optimal latencies

And, if we want to have custom URLs, we will also use route 53. This will take care of pointing requests on specific URLs to the proper CloudFront instance.

Requirements:

As part of a well-architected deployment we would like to ensure the following:

  • Assets stored on s3 should be accessible only through CloudFront
  • Communications between CloudFront and s3 should be encrypted
  • Data stored on s3 should be encrypted (not so critical as it just public assets of a website, but it is available with no extra effort, so why not)
  • HTTP requests should be redirected automatically to HTTPS
  • handle CORS

All the above are fairly easy to achieve using AWS, but it is cumbersome to do through the AWS console and it is quite prone to errors. So using terraform we are simplifying the deployment of such a piece of infrastructure.

Terraform

Terraform is not exactly new anymore. But if you lived in a cave hermetic to cool tools that really simplify your life. Terraform is an open-source infrastructure as code software tool created by HashiCorp.

Through a system of “providers” it has support for many cloud platforms such AWS, GCP, Azure. And other tools that we frequently need to manage when deploying/handling software infrastructures.

We are using it to deploy our infrastructure.

Reusable deployment templates can be created through “modules”.

So we did create a module called CDN that allows us to do exactly that. It has 3 arguments:

  • name (string)*: This name is used when naming resources that supports naming.
  • tags (map(string)): Optional tags to be attached to any created resources that supports tags
  • dir (string): Optional path to the local directory holding the assets to be deployed.

Then we are using the module like this:

This will create the following resources on AWS:

  • s3 bucket
  • cloud front distribution
  • aws_cloudfront_origin_access_identity
  • bucket policy

And it will also sync the files in ../fe/dist with the bucket.

Terraform is of course incremental so every time one piece of the equation changes (deployment template, app code…) doing terraform apply will deploy the latest changes.

It cannot be simplier than this…🙂. We are using this pattern to deploy all our HTML apps easily.

The above does not handle custom url, so we also added the following 2 optional arguments:

  • certificate arn: arn of a certificate from certificate manager that supports the proper domain name(s).
  • aliases: List of domain name(s) that should be supported by this CloudFront distribution.

--

--