DevOps

Sample Next.js application using Terraform in AWS

I got tired of manually provisioning EC2 instances through the AWS console. Click here, fill that, wait, click again. One wrong setting and you're debuggi...

5 May 2024

Sample Next.js application using Terraform in AWS

I got tired of manually provisioning EC2 instances through the AWS console. Click here, fill that, wait, click again. One wrong setting and you're debugging for an hour. Terraform replaces all of that with a config file you can version, review, and reproduce.

Here's how I deploy a dockerized Next.js app to an EC2 instance using Terraform — step by step.

Step 1: AWS CLI setup

Create an IAM user with programmatic access. Save the Access Key ID and Secret Access Key. Then configure your local machine:

Bash
aws configure

Enter the key, secret, region, and output format when prompted. This gives Terraform the credentials it needs to talk to AWS.

Step 2: Install and configure Terraform

Download Terraform from the official install page. Drop the binary somewhere in your PATH. Verify it works:

Bash
terraform version

Step 3: Write the Terraform config

Create a project directory with a main.tf file. This defines the infrastructure you want:

Hcl
provider "aws" {
  region = "us-east-1"
}

resource "aws_security_group" "http_sg" {
  name        = "http_sg"
  description = "Allow HTTP inbound traffic"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "nextjs_instance" {
  ami             = "ami-xxxxxxxxx"  # Replace with your desired AMI
  instance_type   = "t2.micro"
  security_groups = [aws_security_group.http_sg.name]

  tags = {
    Name = "Next.js Instance"
  }
}

Initialize the project and deploy:

Bash
terraform init
terraform apply

Terraform shows you exactly what it will create before it does anything. Type yes to confirm.

Step 4: Dockerize the Next.js app

Create a Dockerfile in your Next.js project:

Dockerfile
FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]

Build and push the image:

Bash
docker build -t nextjs-app .
docker tag nextjs-app your-docker-username/nextjs-app:latest
docker push your-docker-username/nextjs-app:latest

Step 5: Deploy to the EC2 instance

SSH into the instance:

Bash
ssh -i /path/to/your/key.pem ec2-user@ec2-instance-ip

Pull and run the container:

Bash
docker pull your-docker-username/nextjs-app:latest
docker run -d -p 80:3000 your-docker-username/nextjs-app:latest

Hit the instance's public IP in your browser. Your Next.js app is live.

The trade-off

Terraform gives you reproducible, version-controlled infrastructure. You can tear down and rebuild environments in minutes. That's a massive win over clicking through the console.

The cost: Terraform has a learning curve. State management (where Terraform tracks what it created) adds complexity — remote state, locking, and drift detection are things you'll need to solve for production use. And if someone changes infrastructure manually while Terraform expects to own it, things get messy.

Start small. Use it for one service. Once you feel the confidence of terraform plan showing you exactly what will change, you won't go back to manual provisioning.

Keep reading