DEV Community

Tej Tandel
Tej Tandel

Posted on

"Automate EC2 Web Server Deployment on AWS with Terraform and Remote S3 State: true

πŸš€ Automate EC2 Web Server Deployment on AWS with Terraform and Remote S3 State

Managing infrastructure manually is error-prone and inefficient. In this project, I use Terraform to automate the provisioning of an EC2 instance that serves a static website β€” with terraform state pushed to S3.


πŸ”§ What This Project Does

This Terraform project sets up:

  • βœ… An EC2 instance
  • βœ… Security Group allowing HTTP & SSH
  • βœ… User-data to install and serve a website
  • βœ… S3 bucket for Terraform state storage
  • βœ… IAM Role & Policy for EC2 access to S3

πŸ“ Project Structure

terraform-ec2-web-s3/
β”œβ”€β”€ ec2.tf                # EC2 instance + User data
β”œβ”€β”€ iam.tf                # IAM role and policy for S3 access
β”œβ”€β”€ outputs.tf            # Useful outputs
β”œβ”€β”€ provider.tf           # AWS provider config
β”œβ”€β”€ s3.tf                 # S3 bucket setup
β”œβ”€β”€ securitygroup.tf      # SG for HTTP (80) & SSH (22)
β”œβ”€β”€ variables.tf          # Input variables
└── website/              # HTML template (from tooplate)
Enter fullscreen mode Exit fullscreen mode

πŸ“œ Step-by-Step Breakdown

1. βœ… Initialize AWS Provider

provider "aws" {
  region = "us-east-1"
}
Enter fullscreen mode Exit fullscreen mode

2. πŸ“¦ Create S3 Bucket

resource "aws_s3_bucket" "web_backup" {
  bucket = var.bucket_name
}
Enter fullscreen mode Exit fullscreen mode

Used to store Terraform state.


3. πŸ›‘ Security Group

resource "aws_security_group" "web_sg" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["your-ip/32"]
  }

  ingress {
    from_port   = 80
    to_port     = 80
    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

4. πŸ’» Launch EC2 Instance + User Data Script

resource "aws_instance" "web_server" {
  ami                    = var.ami
  instance_type          = var.instance_type
  key_name               = var.key_name
  security_groups        = [aws_security_group.web_sg.name]
  user_data              = file("web_install.sh")
  iam_instance_profile   = aws_iam_instance_profile.s3_profile.name
}
Enter fullscreen mode Exit fullscreen mode

The web_install.sh script:

  • Installs Apache
  • Deploys static site from website/ directory
  • Uploads a backup to S3 using AWS CLI

5. πŸ” IAM Role to Access S3

resource "aws_iam_role_policy" "s3_access" {
  name = "s3-access-policy"
  role = aws_iam_role.ec2_role.name

  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [{
      Action   = ["s3:PutObject"],
      Effect   = "Allow",
      Resource = "arn:aws:s3:::${var.bucket_name}/*"
    }]
  })
}
Enter fullscreen mode Exit fullscreen mode

This gives the EC2 instance permission to upload files to your bucket.


🌍 How to Deploy

Run the following commands:

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

After deployment, Terraform will output:

  • Public IP of the EC2 instance
  • S3 bucket name
  • Live website hosted on EC2 (via Apache)

πŸ’‘ What I Learned

  • βœ… Terraform resource structuring for real-world infrastructure
  • βœ… Using user-data to bootstrap EC2 after provisioning
  • βœ… Connecting EC2 and S3 securely with IAM
  • βœ… Uploading backups automatically to S3
  • βœ… Practical usage of AWS CLI in automation scripts

πŸ“Ž GitHub Repository

πŸ”— https://github.com/tej6667/terraform-ec2-web-s3

Clone it, customize it, and deploy your own cloud-hosted website in minutes.


πŸ‘‹ About Me

I'm Tej Tandel, a Cloud & DevOps enthusiast building hands-on AWS projects and sharing my journey.

Let’s build the cloud β€” one project at a time ☁️

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.