Everyone wants to host their web application on a reliable host, and you don’t get much more reliable than AWS. As well as their generous free tier, it’s possible to host a single-page application (SPA) using their architecture for very little money.
A few years ago, I started using AWS’s own Cloud Development Kit (CDK) to deploy Hugo websites like this to Amazon S3. I like that I could write the constructs using Typescript, and it was much easier than writing Cloud Formation Templates.
Roll forward a few years, and I decided to learn and use Terraform to do the same. I found Terraform to be faster and simpler to engage with, plus it was a great addition to my CV. Despite having to learn HCL (HashiCorp Configuration Language), using it to deploy and host my client websites on Amazon S3 was a breeze. I’ve just deployed a new website using the Typescript version of their infrastructure as a code tool CDKTF or Cloud Development Kit for Terraform, which is a CDK based much on AWS’s own CDK. Using Typescript and all its bells and whistles meant I could return to using the same programming language as I used to code (CDKTF is also available in a few other languages).
Using CDKTF has a considerable advantage from the point of view of a learning curve, as developers can use constructs and terminology, linters and test frameworks with which they are already familiar to write the code that will eventually deploy the infrastructure that their applications will use.
In this guide, I want to run through the process steps, the tools you’ll need and the code you can use to deploy your own IaC.
TL;DR If you want to jump straight to the code and dig in, go here
What is Terraform, and why use it
HashiCorp built Terraform, which it is their most famous and most used product; Terraform allows you to manage and deploy infrastructure resources to many cloud providers, including, but not limited to, Amazon Web Services.
If you visit the Terraform Registry, you can find all the major players in the cloud infrastructure space. Using these providers, you can deploy the same infrastructure across these providers. Using one product to deploy assets to AWS, Azure, Google Cloud, and many more is feasible in a multi-cloud setup.
What is Terraform CDK
Terraform CDK (CDKTF) is their Cloud Development Kit that allows you to use familiar programming languages to write IaC for your resources.
CDKTF is available in Typescript, Python, Go, C# and Java. CDKTF translates your code into HCL configuration files needed for Terraform to work.
Terraform State
Terraform stores the state
of your current deployment. It keeps track of metadata and changes to deployed resources. When developing as a single developer, it is usual to begin storing the Terraform state files on your local computer. Storing ‘state’ locally becomes unmanageable if you change computers or work with a team. At that point, storing the state files somewhere other people can access them or you can access them from multiple machines as usual.
Storing state files in the cloud is referred to as using a remote backend
. There are many remote backends that you can use to store your state files, including Amazon S3 or Terraform Cloud, among others. It’s important to keep state files secure and updated. It’s also important to note that when deploying resources using Terraform, keep the state updated by making changes in the code, not in the UI or console, as this can cause inconsistencies.
Terraform Providers
Providers are pre-built plugins that give Terraform access to external APIs. They act as translators, allowing Terraform to interact with many service providers.
Terraform Stacks
Stacks represent a collection of resources that are deployed to your cloud. You can separate state management using stacks for different environments See this example
Tools and Resources
We will use a couple of things to get this project underway. Before getting into that, though, I will explain the resources we will deploy and why we need them to run our SPA.
AWS Route53
Route53 is the AWS Domain Name Service (DNS). Even if you don’t host or register your primary domain on AWS, it is still possible to use Route53 for this project. This guide assumes that you are hosting your nameservers on Route53, but even if you’re not, it doesn’t prevent you from utilising this guide; you have to make a few adjustments.
AWS Certificate Manager
Using AWS certificate manager is simple in itself. This cloud service helps you create and manage SSL/TLS certificates for AWS services and resources.
- at no cost to you
- renewal of your certificates is managed
- frictionless
Using this guide, you will provision certificates for cloudfront, which will be the front door to your application.
AWS Cloudfront
The global Content Delivery Network (CDN) that is AWS Cloudfront is what we use as the way into our application for visitors. Due to the worldwide nature of the CDN, users all over the world can access your SPA with low latency and get a high-speed response. What’s more, we can utilise caching of frequently accessed pages and data.
Like many CDNs, you can block access from specific geographical regions and host origins on different providers but route traffic from CloudFront to these origins efficiently.
Origin Access Control (OAC)
Origin Access Identity preceded OAC. Both provide secure access to the objects stored in your S3 Bucket, but OAC gives you more security and control and supports more access methods, encrypted objects, and access to S3 in all AWS regions.
AWS S3
AWS Simple Storage Solution (S3) is a cloud object storage solution, which basically means it’s a place to store files in the cloud.
Prerequisites
To successfully deploy your application, there are a couple of things you’ll need and a couple of things you will need to set up to fly. They are
- An AWS account.
- An IAM user that has an active programmatic access key and secret
- A Route53 Hosted Zone
- Your SPA
This guide is for SPA using a node/javascript application.
Steps
Install the CDKTF CLI and Setup the project
What we will do will involve using the command line interface (CLI) for CDKTF. You could install it globally because once you’ve done this for one project, you’ll want to use it all the time.
|
|
Once installed and you’ve checked it using cdktf --version
, we can begin by creating a new project directory. Now, it’s a debate as to whether to keep the terraform code close to your application or not; you will make that decision for yourself; for now, let’s keep it adjacent so it’s always close to the application. In the future, you can keep it in the same repository as your application, especially if you use a monorepo.
|
|
These commands will start setting up your project for you, asking you a few questions:
|
|
Terraform will start building out your project package.json
and will install all the dependencies needed for your project.
Let’s get into the code
Once the installation has finished, you will see main.ts
in your project folder. Most of what we will do will live here, starting off looking like this.
|
|
First, we will tell it that we want to use the AWS provider. Replace the code in your main.ts
with the following:
|
|
Because we will use Cloudfront, we will use ACM to create SSL certificates in the us-east-1
region as Cloudfront only uses certificates created in that region. We need to set up a second provider in this region for this to work. We do this by repeating the provider block, but with this new region, so add:
|
|
We will use this in the next section.
Setup SSL Certificates
We will create a bunch of certificates for your domain with AWS Certificates Manager (ACM). We will use example.com
in this guide but replace it with your domain. We will create certificates that will cover the apex example.com
and also, using a wildcard, we will also cover any subdomains at the next level, e.g. blog.example.com
or crm.example.com
To take advantage of ACM-issued certificates, I suggest setting up and managing your domain from AWS Route53; if you are hosting your domain elsewhere and already have SSL certificates, skip this section. However, I am still determining how Cloudfront will react (I have not investigated this).
Firstly, import the ACM and Route53 classes.
|
|
…
|
|
Then, import the zone information.
|
|
We need this zoneId to create the validation records for the certificates to enable DNS validation, which we do use the following code, so insert this into main.ts
|
|
Finally, add the following code that will trigger the DNS validation.
|
|
S3 Bucket
The S3 bucket is what will hold your SPA files. All the assets that you build will be contained and delivered from her to the CDN Cloudfront.
|
|
|
|
Cloudfront distribution
|
|
Now it’s time to add the Cloudfront distribution.
|
|
Create a record in Route53 with an alias to our CloudFront distribution domain name.
|
|
We use Origin Access Control (OAC) to access our private S3 Bucket
|
|
Once created, we want to grant access to our S3 bucket using this identity. We make a policy document and attach this to our bucket.
|
|
That’s it!
Plan, Apply & Destroy
To deploy this code, run cdktf plan
, cdktf apply
. When you’ve finished admiring what you’ve created and you want to pull it all down again, use cdktf destroy.
Additional Steps to Upload Your SPA
I created a Next boilerplate and configured it to export a static SPA with the build command. We then uploaded the static files to S3.
|
|
Conclusion
I hope you’ve found this guide helpful and that it starts you on the road to deploying the infrastructure for your SPA easily using Terraform and Typescript.
Feature image generated using Adobe Firefly