DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

LAB: Terraform EC2 with `user_data`

๐ŸŽฏ Goal

Provision an EC2 instance that:

  • Installs Nginx automatically
  • Starts the service
  • Serves a custom web page

๐Ÿ‘‰ All using user_data (bootstrapping)


๐Ÿ“ Project Structure

terraform-userdata-lab/
โ”œโ”€โ”€ main.tf
โ”œโ”€โ”€ variables.tf
โ”œโ”€โ”€ terraform.tfvars
โ”œโ”€โ”€ providers.tf
โ”œโ”€โ”€ versions.tf
โ”œโ”€โ”€ outputs.tf
โ””โ”€โ”€ user_data.sh.tpl
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ versions.tf

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ providers.tf

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

๐Ÿ“„ variables.tf

variable "aws_region" {
  type        = string
  description = "AWS region"
}

variable "instance_type" {
  type        = string
  description = "EC2 type"
}

variable "instance_name" {
  type        = string
  description = "Name of instance"
}

variable "web_message" {
  type        = string
  description = "Message shown on web page"
}

variable "common_tags" {
  type        = map(string)
  description = "Common tags"
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ terraform.tfvars

aws_region     = "us-east-2"
instance_type  = "t2.micro"
instance_name  = "userdata-lab"

web_message = "Hello from Terraform User Data!"

common_tags = {
  Project = "UserDataLab"
  Owner   = "Student"
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ user_data.sh.tpl (IMPORTANT)

#!/bin/bash
yum update -y
yum install -y nginx

systemctl start nginx
systemctl enable nginx

echo "${web_message}" > /usr/share/nginx/html/index.html
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ main.tf

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_security_group" "web_sg" {
  name        = "${var.instance_name}-sg"
  description = "Allow HTTP"

  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"]
  }

  tags = var.common_tags
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  vpc_security_group_ids = [aws_security_group.web_sg.id]

  user_data = templatefile("${path.module}/user_data.sh.tpl", {
    web_message = var.web_message
  })

  tags = merge(var.common_tags, {
    Name = var.instance_name
  })
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“„ outputs.tf

output "public_ip" {
  value = aws_instance.web.public_ip
}

output "url" {
  value = "http://${aws_instance.web.public_ip}"
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช STEP-BY-STEP


โœ… Step 1 โ€” Initialize

terraform init
Enter fullscreen mode Exit fullscreen mode

โœ… Step 2 โ€” Apply

terraform apply
Enter fullscreen mode Exit fullscreen mode

โœ… Step 3 โ€” Open browser

Use output:

terraform output url
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Open in browser
๐Ÿ‘‰ You will see:

Hello from Terraform User Data!
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”ฅ What is user_data (Important Explanation)

๐Ÿ‘‰ user_data is a script that runs:

  • Automatically when EC2 starts
  • Only on first boot (by default)

๐Ÿง  Real DevOps Usage

Used for:

  • Install packages (nginx, docker)
  • Configure apps
  • Pull code from Git
  • Start services

โš ๏ธ Important Notes


โ— Runs only once

If you change user_data:

๐Ÿ‘‰ Terraform does NOT re-run it


โ— To re-run:

You must:

terraform taint aws_instance.web
terraform apply
Enter fullscreen mode Exit fullscreen mode

OR change:

user_data_replace_on_change = true
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”ฅ Bonus (VERY IMPORTANT FOR INTERVIEW)

Add this:

user_data_replace_on_change = true
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Now:

  • Any change in user_data โ†’ instance recreated

๐ŸŽฏ Interview Answer

Q: What is user_data in Terraform?

๐Ÿ‘‰
user_data is a script passed to an EC2 instance that runs during the initial boot process, typically used to install software and configure the instance automatically.


๐Ÿš€ Summary

Feature Purpose
user_data Bootstrap EC2
templatefile Avoid hardcoding
runs On first boot
replace_on_change Forces recreation

Top comments (0)