Resources required to deploy a SPA
Prerequisites
Before you start, make sure that you have IAM User with admin privileges and Remote Backend (How to create Remote Backend with S3 and DynamoDB with Terraform) for Terraform setup.
Terraform folder structure
Usually, you will want to create multiple environments for the app, and you will use more than one resource at the same time. To make sure that you cover all these cases, you should have this kind of folder structure. This allows you to run terraform apply for each environment with different settings.
build/
- modules/
- webapp/
- cert.tf
- dns.tf
- s3.tf
- cloudfront.tf
- route53.tf
- variables.tf
- env/
- dev/
- main.tf
- prod
- main.tf Step 1 (optional): Setup your remote backend
First thing first, create build folder within your project and within your main.tf file, where you will run modules. Inside of that main.tf, add the following
terraform {
backend "s3" {
encrypt = true
bucket = "bucket_name_where_you_store_state"
dynamodb_table = "dynamodb_for_locking_state"
region = "eu-west-2" <- region where your backend dynamodb is deployed
key = "key_within_dynamo/dev/terraform.tfstate" <- just use repo name as a key
}
} Step 2: Setup your S3 bucket for an app
To setup S3 bucket, you have to setup the following:
- create a bucket in S3
- attach a policy to only allow CloudFront to read from it
- add server side encryption with AES256 SSE algorithm
- Add website configuration where index and error pages point to an
index.htmlto allow client side router handle routing - (optional) add CORS if you use Microfrontends
Example of CloudFront for S3 with Static Website
Step 3: AWS Certificate Manager
Before you proceed, you have to create a certificate as it may take awhile to create it. For this, you need a domain as you can (but don’t have to) use a DNS to validate it.
https://us-east-1.console.aws.amazon.com/acm/home?region=us-east-1#/certificates/list
Example
resource "aws_acm_certificate" "cert" {
domain_name = var.domain
validation_method = "DNS"
}
resource "aws_route53_record" "cert" {
for_each = {
for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = local.dns_zone_id
}
resource "aws_acm_certificate_validation" "cert" {
depends_on = [aws_acm_certificate.cert, aws_route53_record.cert]
certificate_arn = aws_acm_certificate.cert.arn
validation_record_fqdns = [for record in aws_route53_record.cert : record.fqdn]
} Step 4: Setup CloudFront
To setup CloudFront CDN, you have to do the following:
- create CloudFront distribution with an origin id
- (optional) add domains
- enable ipv6
- price class to tell Cloudfront where it should be distributed
- add cache behaviour
- allowed, cached methods, viewer protocol policy and cache policy for origin requests and cache policy
- viewer certificate for your domain (the one that was created in step 3)
- custom error response (for 403 and 404) so it knows that it should respond with 200 and redirect to index.html
- (optional) restrictions, if there are any
Example of CloudFront for S3 with Static Website
Once all of it is deployed, you should have an app that is cheap to run and distributed across the world