DEV Community

Cover image for Part-4: Automating EC2 Infrastructure using Terraform | Amazon Web Services (AWS)
M. Oly Mahmud
M. Oly Mahmud

Posted on

Part-4: Automating EC2 Infrastructure using Terraform | Amazon Web Services (AWS)

Earlier, we created an EC2 instance by hand in the AWS Console. Now we’ll do the same thing with Terraform.

In this guide, we will walk through how to use Terraform to create an EC2 instance on AWS, generate an SSH key, and install Nginx when the server boots. All of it is automated using code.

Prerequisites

You should have:

  • An AWS account

  • Terraform installed on your machine

  • An IAM user with an access key and secret key

  • A general idea of how EC2 works

  • A basic understanding of Terraform (providers, resources, variables, outputs)

Directory Structure

Here’s the Terraform project layout we will use:

.
├── instance.tf
├── key_pair.tf
├── output.tf
├── provider.tf
├── terraform.tfvars
└── variables.tf
Enter fullscreen mode Exit fullscreen mode

Each file handles a specific part of the deployment.

Provider Configuration

Start with the provider definition in provider.tf:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "6.15.0"
    }
  }
}

provider "aws" {
  region     = var.region
  access_key = var.access_key
  secret_key = var.secret_key
}
Enter fullscreen mode Exit fullscreen mode

This tells Terraform to use the AWS provider and defines how to authenticate.
In practice, you should avoid storing credentials in code or tfvars files — use the AWS CLI (aws configure) or environment variables for safer authentication.

Defining Variables

In variables.tf, define the parameters Terraform will use.

variable "access_key" {
  type = string
}

variable "secret_key" {
  type = string
}

variable "region" {
  type    = string
  default = "eu-north-1"
}

variable "file_name" {
  description = "Local file name for private key"
  type        = string
}
Enter fullscreen mode Exit fullscreen mode

These variables make the configuration reusable. For example, you can switch AWS regions or key names without touching the main code.

Creating an SSH Key Pair

key_pair.tf handles SSH key generation and registration with AWS.

resource "tls_private_key" "rsa-4096-key" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "local_file" "tf_key" {
  content  = tls_private_key.rsa-4096-key.private_key_pem
  filename = var.file_name
}

resource "aws_key_pair" "demo-key-pair-tf" {
  key_name   = "demo-key-pair-tf"
  public_key = tls_private_key.rsa-4096-key.public_key_openssh
}
Enter fullscreen mode Exit fullscreen mode
  • The TLS provider generates a 4096-bit RSA key.
  • The local_file resource writes the private key locally as a .pem file.
  • The aws_key_pair resource uploads the public key to AWS.

Once deployed, you’ll use the .pem file for SSH access to your EC2 instance.

Defining the EC2 Instance

instance.tf defines both the EC2 instance and the security group.

resource "aws_instance" "web-server" {
  ami             = "ami-0a716d3f3b16d290c"
  instance_type   = "t3.micro"
  key_name        = aws_key_pair.demo-key-pair-tf.key_name
  security_groups = [aws_security_group.demo-sg.name]

  user_data = <<-EOF
  #!/bin/bash
  apt update -y
  apt install nginx -y
  systemctl enable nginx
  systemctl start nginx
EOF

  tags = {
    Name = "web-server"
  }
}
Enter fullscreen mode Exit fullscreen mode

What happens here

  • Terraform launches an Ubuntu 24.04 EC2 instance using the AMI ID above.
  • A user_data script runs automatically on boot:

    • Updates packages
    • Installs and starts Nginx
    • Enables it to start on boot
  • By the time Terraform finishes, Nginx is already serving traffic.

Security Group

resource "aws_security_group" "demo-sg" {
  name = "demo-sg"

  ingress {
    description = "SSH access"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

  ingress {
    description = "HTTPS access"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Enter fullscreen mode Exit fullscreen mode

It allows:

  • SSH (22) for remote access
  • HTTP (80) and HTTPS (443) for web traffic
  • All outbound traffic for updates and package installations

Outputting Useful Information

In output.tf, display key connection details after provisioning:

output "aws_instance_public_ip" {
  value = aws_instance.web-server.public_ip
}

output "aws_instance_public_dns" {
  value = aws_instance.web-server.public_dns
}
Enter fullscreen mode Exit fullscreen mode

After terraform apply, you’ll see the public IP and DNS name printed on your terminal.

Deploying the Infrastructure

Create a terraform.tfvars file to provide variable values:

region = "eu-north-1"

access_key = "YOUR_ACCESS_KEY"
secret_key = "YOUR_SECRET_KEY"
file_name  = "demo-key.pem"
Enter fullscreen mode Exit fullscreen mode

You can also use environment variables to assign values for access_key and secret_key.

export TF_VAR_access_key="YOUR_ACCESS_KEY"
export TF_VAR_secret_key="YOUR_SECRET_KEY"
Enter fullscreen mode Exit fullscreen mode

Once all files are in place, run:

terraform init
terraform plan
terraform apply
Enter fullscreen mode Exit fullscreen mode

Terraform will:

  1. Generate a key pair
  2. Create a security group
  3. Launch the EC2 instance
  4. Run the Nginx installation script
  5. Print the public IP and DNS

Open the public IP in your browser.
You should see the Nginx welcome page — that confirms a successful automated deployment.

Verifying from the Instance

You can SSH in if you want to verify Nginx status:

chmod 400 demo-key.pem
ssh -i demo-key.pem ubuntu@<public_ip>
sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode

Cleaning Up

When you’re done testing:

terraform destroy
Enter fullscreen mode Exit fullscreen mode

This removes the instance, key pair, and security group.
Terraform tracks all managed resources, so cleanup is safe and predictable.

Conclusion

We've automatically deployed a secure, Nginx-powered EC2 instance using Terraform.

Top comments (0)