Skip to main content

Command Palette

Search for a command to run...

πŸš€ Terraform Series – Day 8

Published
β€’5 min read
πŸš€ Terraform Series – Day 8

Automating AWS EC2 Setup with Terraform and user_data

Welcome back to our Terraform journey. In infrastructure as code, setting up a server is just the beginning. After your EC2 instance is running, you need to set it up, install what it needs, and start your apps. Doing this by hand goes against the idea of automation.

In this post, we will demonstrate how to completely automate your server bootstrapping process using Terraform and the AWS user_data feature.

🎯 Objective

By the end of this guide, you will learn how to automatically install and configure an Nginx web server on a newly provisioned AWS EC2 instance using a Terraform user_data script.

🧩 Step 1: Understanding the Power of user_data

The Problem with Manual Configuration

Imagine you just used Terraform to spin up a fresh EC2 instance. Without an automation script, your next steps would look like this:

  1. SSH into the instance.

  2. Manually run package updates.

  3. Install Nginx.

  4. Start the service.

  5. Create a custom HTML page.

This approach is time-consuming, prone to human error, and most importantly, not scalable. If you need to spin up 100 web servers behind a load balancer, logging into each one manually is impossible.

The Solution: Bootstrap Scripts

AWS provides a feature called user_data that allows you to pass a script to your instance at launch.

  • βœ”οΈ Runs automatically the very first time the instance boots.

  • βœ”οΈ Fully automates software installation and configuration.

  • βœ”οΈ Scales infinitely across as many instances as you deploy.

In short: user_data is your EC2 bootstrapping engine.

πŸ“„ Step 2: Create the Bootstrapping Script (nginx.sh)

First, we need to define the commands we want our server to run on startup. We will create a simple bash script that installs Nginx and creates a custom landing page.

Create a new file named nginx.sh:3

touch nginx.sh

Add the following content to the file:-

#!/bin/bash

# Update package lists
sudo apt-get update

# Install Nginx silently (-y prevents the prompt)
sudo apt-get install nginx -y

# Start the Nginx service
sudo systemctl start nginx

# Enable Nginx to start automatically if the server reboots
sudo systemctl enable nginx

# Create a custom HTML landing page
echo "<h1> Terraform testing with scripting </h1>" > /var/www/html/index.html

πŸ”— Step 3: Attach the Script in Terraform

Now, we need to tell Terraform to pass this script to our EC2 instance during creation. We do this by utilizing the file() function within the user_data argument of our aws_instance resource.

Open your ec2.tf file and configure your instance block:-

resource "aws_instance" "my_instance" {
  ami           = var.ec2_ami_id
  instance_type = var.ec2_instance_type

  # Attach your SSH key pair
  key_name = aws_key_pair.my_key.key_name

  # Attach the security group (make sure port 80 is open!)
  vpc_security_group_ids = [aws_security_group.my_groups.id]

  # Inject the bootstrap script here
  user_data = file("nginx.sh")

  # Define root storage
  root_block_device {
    volume_size = var.ec2_root_storage_size
    volume_type = "gp3"
  }

  tags = {
    Name = "terraform-ec2-nginx"
  }
}
πŸ’‘
Note: Using file("nginx.sh") keeps your Terraform code clean by separating the bash logic from the HCL infrastructure definitions.

βš™οΈ Step 4: Execute the Pipeline

With the script created and Terraform configured, it's time to deploy. Run the following commands in your terminal:

Bash

terraform init
terraform apply -auto-approve

What happens internally?

Once you hit apply, an elegant automated workflow kicks off:

  1. Infrastructure Provisioned: Terraform calls the AWS API to launch a new EC2 instance.

  2. Script Passed: The contents of nginx.sh are passed to the instance metadata.

  3. Bootstrapping Execution: As the EC2 instance boots up, the OS executes the script as the root user.

  4. App Deployed: Packages are updated, Nginx is installed, the service is started, and your custom HTML page is generated.

Within minutes, you can grab the public IP of your new EC2 instance, paste it into your browser, and see your custom HTML pageβ€”zero SSH required.

πŸ§ͺ Testing: Verify NGINX on EC2 Instance

After provisioning the EC2 instance using Terraform, we need to test whether NGINX is properly installed and running.

πŸ”Ή Step 1: Connect to EC2 via SSH

ssh -i "your-key.pem" ubuntu@<EC2-PUBLIC-IP>

βœ” Replace:

  • your-key.pem β†’ your private key

  • <EC2-PUBLIC-IP> β†’ instance public IP

πŸ”Ή Step 2: Check NGINX Status

sudo systemctl status nginx

βœ” Expected Output:

  • active (running) β†’ βœ… NGINX is working

  • inactive / failed β†’ ❌ issue needs fixing

πŸ”Ή Step 3: Test via Browser

Open your browser and hit:

http://<EC2-PUBLIC-IP>

βœ” Expected:

  • Default NGINX Welcome Page

πŸ”Ή Step 5: Test via Curl (CLI Testing)

curl http://localhost

OR from your local system:

curl http://<EC2-PUBLIC-IP>

βœ” If HTML response comes β†’ βœ… Server is working

πŸ”Ή Step 6: Check Port 80 (Important for DevOps)

sudo netstat -tulpn | grep :80

OR

sudo ss -tulpn | grep :80

βœ” Confirms:

  • NGINX is listening on port 80

πŸ’‘ Key Takeaways

  • No More Manual SSH: Bootstrapping completely eliminates the need to manually configure infrastructure after it is provisioned.

  • Separation of Concerns: By using the file() function, you keep your shell scripts separate from your Terraform code, making both easier to maintain.

  • Idempotency and Scale: A script guarantees that every server you provision will be configured exactly the same way, every single time.

πŸ‘¨β€πŸ’» About the Author

β€œA complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”

πŸ“¬ Let's Stay Connected

Terraform

Part 1 of 8

πŸš€ Terraform Series – Automate Your Infrastructure Starting a complete **Terraform series** where I’ll cover everything from **basic to advanced level** with real-world practicals. In this series, you will learn: β€’ What is Infrastructure as Code (IaC) & why it matters β€’ Terraform fundamentals (providers, resources, state) β€’ Writing and managing Terraform configurations β€’ Variables, outputs & modules β€’ Remote state & state management β€’ Provisioning infrastructure on AWS β€’ Automation & real-world use cases β€’ Advanced concepts like workspaces, modules, and best practices 🎯 Goal: Help you automate infrastructure and become job-ready in DevOps. Perfect for **beginners, students, and DevOps learners** who want hands-on experience. Stay tuned and let’s build infrastructure the smart way βš‘πŸ’» #Terraform #DevOps #Cloud #AWS #InfrastructureAsCode #Automation

Up next

πŸš€ Terraform Series – Day 7

Variables & Outputs (Make Your Code Smart πŸ”₯) In real-world DevOps, writing flexible and reusable code is very important.Today, we will learn how to use Variables and Outputs in Terraform to make our