π 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)
π Step-by-Step Breakdown
1. β Initialize AWS Provider
provider "aws" {
region = "us-east-1"
}
2. π¦ Create S3 Bucket
resource "aws_s3_bucket" "web_backup" {
bucket = var.bucket_name
}
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"]
}
}
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
}
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}/*"
}]
})
}
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
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.