Infrastructure on AWS (Terraform)
Relevant source files
The following files were used as context for generating this wiki page:
- terraform/infrastructure/main.tf
- terraform/infrastructure/modules/cloudfront/01-cdn.tf
- terraform/infrastructure/modules/static-website/main.tf
- terraform/infrastructure/versions.tf
- terraform/infrastructure/modules/cd-backend/main.tf
- terraform/infrastructure/modules/static-website/versions.tf
- terraform/dns-zone/versions.tf
The Collimator project's cloud infrastructure is defined and managed using HashiCorp Terraform. This approach enables infrastructure as code (IaC), providing a reproducible and version-controlled setup on Amazon Web Services (AWS). The infrastructure is modular, separating concerns such as networking, application hosting (frontend and backend), database, and content delivery.
The root Terraform configuration orchestrates the deployment of these modules, creating a cohesive environment that includes a VPC, Fargate services for the backend, S3 buckets for static frontends, an RDS database, and a CloudFront distribution to route traffic and serve content efficiently.
High-Level Architecture
The infrastructure is composed of several interconnected Terraform modules, each responsible for a specific part of the system. The main main.tf file acts as the central point for defining and connecting these modules.
The following diagram illustrates the dependencies between the main modules.
Sources: terraform/infrastructure/main.tf
Terraform Modules Summary
The table below summarizes the core modules instantiated in the root configuration.
| Module Name | Source Path | Purpose |
|---|---|---|
network | ./modules/network | Provisions core networking resources like the VPC, subnets, and ACM certificate. |
frontend | ./modules/static-website | Manages the S3 bucket and Lambda@Edge for the main Next.js frontend application. |
scratchapp | ./modules/static-website | Manages the S3 bucket and Lambda@Edge for the "Scratch" single-page application. |
database | ./modules/database | Provisions the application's database within the VPC. |
backend | ./modules/fargate | Deploys the backend application as a service on AWS Fargate, placing it in private subnets. |
cdn | ./modules/cloudfront | Configures a CloudFront distribution to act as the single entry point, routing traffic to the frontend, scratchapp, and backend origins. |
cd_backend | ./modules/cd-backend | Creates an S3 bucket for storing Terraform state, likely for CI/CD pipelines. |
Sources: terraform/infrastructure/main.tf:8-98
Core Components
Terraform State Management
Terraform's state is managed remotely in an AWS S3 bucket to ensure consistency and allow for collaboration. The configuration specifies a different key for each logical part of the infrastructure, such as the main infrastructure, DNS zone, and deployments. This prevents state conflicts and provides organizational clarity.
# terraform/infrastructure/versions.tf:9-13
backend "s3" {
bucket = var.tfstate_bucket_name
key = "infrastructure/infrastructure"
region = var.region
}
Sources: terraform/infrastructure/versions.tf:9-13, terraform/dns-zone/versions.tf:9-13, terraform/infrastructure/modules/cd-backend/main.tf:1-10
Frontend and Static Assets (static-website module)
The project serves two separate static web applications: the main frontend (a Next.js app) and scratchapp (a SPA). Both use the static-website module, which encapsulates the necessary resources.
Key features of this module include:
- Private S3 Bucket: An
aws_s3_bucketis created to store the static files. Public access is explicitly blocked at the bucket level. - Lambda@Edge for URL Rewrites: A Node.js Lambda function is packaged and deployed to Lambda@Edge. This function is triggered on origin requests to rewrite URLs, a common pattern for routing in Single-Page Applications (SPAs) and Next.js. The function runtime is
nodejs20.x. - Multi-Region Provider: The module configures an additional AWS provider with the alias
cloudfront_region_providerfor theus-east-1region. This is a requirement for creating Lambda@Edge functions that will be associated with CloudFront.
Sources: terraform/infrastructure/modules/static-website/main.tf:4-40, terraform/infrastructure/modules/static-website/versions.tf:18-23, terraform/infrastructure/main.tf:19-40
Backend Services (backend module)
The backend application is deployed using the fargate module. It is configured to run within the VPC created by the network module, utilizing private subnets for security. It receives its database connection string from the database module's output and other configuration details like service discovery ARNs and secrets via variables.
Sources: terraform/infrastructure/main.tf:54-73
Content Delivery Network (CloudFront)
A CloudFront distribution, managed by the cdn module, serves as the public-facing entry point for all traffic. It routes requests to the appropriate origin (backend, frontend, or scratchapp) based on the request path.
This diagram shows the request routing logic implemented in the CloudFront distribution.
Origins and Security
- S3 Origins (
frontend,scratchapp): These origins point to the S3 buckets for the static sites. Access to these buckets is restricted using Origin Access Control (OAC). The S3 bucket policies are configured to only allows3:GetObjectactions from the CloudFront service principal, ensuring files cannot be accessed directly. - Custom Origin (
backend): This origin points to the DNS name of the backend service running on Fargate. It's configured to behttp-onlysince TLS is terminated at CloudFront.
Sources: terraform/infrastructure/modules/cloudfront/01-cdn.tf:83-100, terraform/infrastructure/modules/cloudfront/01-cdn.tf:189-223
Cache Behaviors
The distribution has several ordered cache behaviors to handle different types of requests. Caching is generally disabled (Managed-CachingDisabled policy) for all dynamic paths to ensure users always receive the latest content from the origins.
| Path Pattern | Target Origin | Allowed Methods | Key Configurations |
|---|---|---|---|
/api/* | backend | DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT | Forwards all viewer headers (Managed-AllViewer policy). |
/socket.io/* | backend | DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT | Uses a custom origin request policy to allow WebSocket headers (Sec-WebSocket-*). |
/scratch* | scratchapp | GET, HEAD, OPTIONS | Associates the scratchapp Lambda@Edge function for URL rewriting. |
Default (*) | frontend | GET, HEAD, OPTIONS | Associates the frontend Lambda@Edge function for URL rewriting. All HTTP requests are redirected to HTTPS. |
Sources: terraform/infrastructure/modules/cloudfront/01-cdn.tf:121-177