Building a Next.js application with Terraform, S3, and CloudFront
In this blog post, I’ll walk you through how to build a portfolio website using Next.js, Terraform, AWS S3, and CloudFront. This setup ensures a scalable, secure, and globally distributed website for an optimal user experience.
Project Architecture
Frontend:
Built using Next.js.
Deployed as a static website using S3.
Infrastructure:
Automated with Terraform.
AWS services used:
S3: Stores static files (HTML, CSS, JS).
CloudFront: Provides a CDN for global distribution.
Origin Access Identity (OAI): Secures S3 content, making it accessible only through CloudFront.
Key Features
Infrastructure as Code:
Terraform provisions S3, CloudFront, and related resources.
Allows easy replication of the setup for future projects.
Performance Optimization:
CloudFront caches content globally, ensuring fast load times.
TTL settings manage efficient caching strategies.
Security:
S3 bucket configured with ownership controls, public access block, and an OAI for CloudFront.
HTTPS enabled through CloudFront’s default certificate.
Step-by-Step Implementation
1. Develop the Website
Using Next.js:
Create a static website:
npx create-next-app@latest my-portfolio cd my-portfolio npm run build
Output static files are in the
out/
directory.
2. Write Terraform Code
S3 Bucket
Configuring an S3 bucket for static website hosting:
resource "aws_s3_bucket" "website_bucket" {
bucket = "portfolio-website-bucket"
tags = {
Environment = "Production"
Project = "Portfolio"
}
}
CloudFront Distribution
Setting up CloudFront for global delivery:
resource "aws_cloudfront_distribution" "website_distribution" {
origin {
domain_name = aws_s3_bucket.website_bucket.bucket_regional_domain_name
origin_id = "S3-Website"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
}
}
default_cache_behavior {
target_origin_id = "S3-Website"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
3. Deploy with Terraform
Initialize Terraform:
terraform init
Plan Resources:
terraform plan
Apply Configuration:
terraform apply
Terraform will provision all AWS resources, including the S3 bucket, CloudFront distribution, and OAI.
4. Upload Static Files to S3
Use the AWS CLI to sync files to S3:
aws s3 sync ./out s3://portfolio-website-bucket
Lessons Learned
Managing Dependencies:
- Ensuring resources like the bucket policy and OAI are created in the correct order was crucial.
Debugging Terraform Issues:
- Dealing with common Terraform errors (e.g., invalid attributes or missing dependencies) helped reinforce my understanding of AWS services.
Global Reach and Performance:
- Testing the site after deploying through CloudFront demonstrated significant performance improvements compared to direct S3 hosting.
Conclusion
Building this portfolio project with Terraform, S3, and CloudFront was a rewarding experience. It allowed me to create a professional-grade website with scalability and performance in mind while learning more about AWS and Infrastructure as Code.
If you have any questions or suggestions, feel free to reach out in the comments or connect with me!