Deploy Your First Cloud Server with Terraform
Use Terraform to provision a real AWS EC2 instance with code.
Introduction
30 Second Summary
Every time a team needs a new server, someone logs into a cloud console and clicks through dozens of settings. If that server needs to be rebuilt, they repeat the same manual process from memory. One missed checkbox can take down a production system.
In this project, you will use Terraform to deploy a cloud server on AWS entirely through code. You'll write configuration files that define your infrastructure, then create, modify, and destroy it with simple terminal commands.
What You'll Build
A complete Infrastructure as Code project that provisions an EC2 instance on AWS using Terraform configuration files.
By the end of this project, you'll have:
- A Terraform project with proper file structure (main.tf, variables.tf, outputs.tf, terraform.tf).
- A live EC2 instance on AWS with a security group allowing HTTP access.
- Hands-on experience with the full Terraform lifecycle: init, plan, apply, and destroy.
- Secret Mission: Add an S3 bucket to your infrastructure and configure IAM access for your EC2 instance.
Are there any prerequisites?
None. This project includes full setup instructions for Terraform, the AWS CLI, and your AWS account. No prior cloud experience is required.
Install Terraform and AWS CLI
Before you can deploy cloud infrastructure with code, you need two command-line tools installed on your machine. Terraform reads your configuration files and translates them into real cloud resources.
The AWS CLI lets Terraform authenticate with your AWS account so it has permission to create those resources. In this step, you will install both tools and connect them to your AWS account.
In this step, get ready to:
- Install and verify Terraform.
- Install and verify AWS CLI v2.
- Configure AWS credentials for Terraform to use.
Download and install Terraform
Terraform is a command-line tool that you run from a terminal. On Windows, you can install it using a package manager called Chocolatey or by downloading the binary directly.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type PowerShell and press Enter to open it.
What is Terraform?
Terraform is an Infrastructure as Code (IaC) tool made by HashiCorp. Instead of clicking around a cloud console to create servers, databases, or networks, you write configuration files that describe what you want.
Terraform reads those files and handles creating, updating, or deleting your cloud resources automatically. This means your infrastructure is versioned, repeatable, and shareable.
- Install Terraform by choosing one of the methods below:
Chocolatey (package manager)
Chocolatey is a package manager for Windows that handles downloads and PATH setup for you. If you already have Chocolatey installed, this is the fastest option.
- Right-click the Windows PowerShell icon in your taskbar and select Run as Administrator.
- Install Terraform by running this command:
choco install terraform
- When prompted to run the install script, type Y and press Enter to confirm.
Don't have Chocolatey?
If you see an error saying choco is not recognized, switch to the Binary download tab instead.
Binary download
This method works on any Windows machine without requiring extra tools.
- Open your browser and go to the Terraform downloads page:
https://developer.hashicorp.com/terraform/install
- Under the Windows section, click the AMD64 download link (version 1.15.5).
- Extract the downloaded zip file. Inside you will find a file called terraform.exe.
- Move terraform.exe to a folder like C:\terraform.
- Add that folder to your system PATH by searching for Environment Variables in the Windows search bar, clicking Edit the system environment variables, then Environment Variables.
- Under System variables, select Path and click Edit.
- Click New and type C:\terraform.
- Click OK on all open dialogs to save.
- Close and reopen PowerShell so it picks up the new PATH.
- Verify Terraform is installed by running this command:
terraform version
✔️ I see version 1.2 or higher
You should see output starting with Terraform v followed by a version number like 1.15.5. Terraform is ready to go.
ⓧ I see an older version
If you see a version below 1.2, you need to upgrade.
- If you installed with Chocolatey, run:
choco upgrade terraform
- If you used the binary download, download the latest version from the Terraform install page and replace your existing terraform.exe file.
ⓧ Command not found
This means your system cannot find the terraform executable.
- If you used Chocolatey, close PowerShell completely and reopen it. Chocolatey adds Terraform to PATH but the current session may not have picked it up.
- If you used the binary download, double-check that the folder containing terraform.exe is added to your system PATH (not user PATH).
- After fixing the PATH, close and reopen PowerShell, then run terraform version again.
Install AWS CLI v2
The AWS CLI is a command-line tool that lets you interact with AWS services from your terminal. Terraform uses the credentials stored by the AWS CLI to authenticate with your AWS account.
- Download and install the AWS CLI by running this command in PowerShell:
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
What does this command do?
msiexec.exe is Windows' built-in installer tool. It downloads the AWS CLI installer from Amazon's servers and runs the setup wizard automatically.
- The installer wizard will open. Click Next through each screen, accept the license agreement, and click Install.
- Once installation completes, click Finish.
- Close PowerShell completely and reopen it so it recognizes the new AWS CLI installation.
- Verify the AWS CLI is installed by running this command:
aws --version
✔️ I see aws-cli/2.x.x
You should see output starting with aws-cli/2. followed by a version number. The AWS CLI is ready.
ⓧ I see aws-cli/1.x.x
You have an older version of the AWS CLI installed. This project requires version 2.
- Uninstall the old version through Settings > Apps > Installed apps. Search for AWS CLI and uninstall it.
- Re-run the msiexec.exe command above to install version 2.
- Close and reopen PowerShell, then run aws --version again.
ⓧ Command not found
The installer may not have completed successfully.
- Make sure you closed and reopened PowerShell after installation.
- If it still does not work, download the installer manually from https://awscli.amazonaws.com/AWSCLIV2.msi and double-click it to run the setup wizard.
- After installation, close and reopen PowerShell, then try aws --version again.
Configure your AWS credentials
Terraform needs permission to create resources in your AWS account. You provide this by giving it an Access Key ID and Secret Access Key that link to your AWS account.
What are AWS access keys?
Access keys are like a username and password for programmatic access to AWS. They consist of two parts: an Access Key ID (which identifies who you are) and a Secret Access Key (which proves it).
You create them in the AWS Console, and tools like Terraform and the AWS CLI use them to authenticate on your behalf.
If you do not have an AWS account yet, sign up at https://aws.amazon.com. The Free Tier covers everything in this project.
- Sign in to the AWS Management Console.
- In the top-right corner, click your account name, then select Security credentials.
- Scroll down to the Access keys section and click Create access key.
- On the best practices page, select Command Line Interface (CLI) as your use case.
- Check the confirmation box at the bottom, then click Next.
- Click Create access key.
- You will see your Access Key ID and Secret Access Key on screen. Copy both values to a safe location or click Download .csv file.
Save your Secret Access Key now
AWS only shows your Secret Access Key once at creation time. If you lose it, you will need to delete the key and create a new one. Save it somewhere secure before continuing.
- Back in PowerShell, configure the AWS CLI with your credentials by running:
aws configure
- The command will prompt you for four values. Enter them one at a time:
- AWS Access Key ID: Paste your Access Key ID.
- AWS Secret Access Key: Paste your Secret Access Key.
- Default region name: Type us-east-1.
- Default output format: Press Enter to accept the default (blank).
Why us-east-1?
us-east-1 (Northern Virginia) is AWS's oldest and most feature-complete region. It is also where most AWS Free Tier tutorials are tested, so using it avoids unexpected service availability issues.
- Verify your credentials are working by running:
aws sts get-caller-identity
- You should see a JSON response showing your Account ID, User ID, and ARN. This confirms Terraform will be able to authenticate with AWS.
Seeing an error about invalid credentials?
- Double-check that you pasted the Access Key ID and Secret Access Key without any extra spaces.
- Make sure you copied the Secret Access Key (not the Access Key ID) into the second prompt.
- If you accidentally closed the credentials page, delete the key in the AWS Console and create a new one.
Help me troubleshoot my AWS credentials configuration.
- Finally, open VS Code so it is ready for the next step.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code and press Enter to open it.
Your tools are installed and your AWS credentials are configured. Next up, you will create your Terraform project structure and write your first configuration files.
Set Up Your Terraform Project
Your tools are installed and your AWS credentials are configured. Now it is time to create the actual project where your infrastructure code will live.
Terraform projects follow a specific file structure. Each file has a dedicated responsibility: one file locks down versions, another defines variables, and others describe your actual infrastructure. This keeps your configuration organized and readable as it grows.
In this step, get ready to:
- Create your project directory and the Terraform configuration file.
- Define input variables for flexible configuration.
- Initialize Terraform and download the AWS provider plugin.
Create your project directory and terraform.tf
Every Terraform project starts with a configuration file that declares which version of Terraform to use and which providers (cloud platform plugins) your project depends on. This prevents breaking changes from sneaking in when providers release updates.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir terraform-server
cd terraform-server
- Confirm the folder exists by running:
ls
You should see the terraform-server folder listed on your Desktop. The folder is empty for now.
- Open the terraform-server folder in VS Code by clicking File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the terraform-server folder, then click Open.
- Create a new file by clicking the new file icon in the Explorer sidebar (or press Cmd+N on macOS or Ctrl+N on Windows).
- Name the file terraform.tf.
- Paste the following code into terraform.tf:
terraform {
# Pin the AWS provider to any 6.x version
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
# Require Terraform 1.2 or newer
required_version = ">= 1.2"
}
What does this code do?
This is the terraform block. It tells Terraform two things about your project's requirements.
- required_providers declares that this project uses the AWS provider from HashiCorp's registry. The ~> 6.0 constraint means any 6.x version is acceptable, but not 7.0 or higher.
- required_version ensures anyone running this project has Terraform 1.2 or newer installed.
- Save terraform.tf by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- You should see terraform.tf appear in the Explorer sidebar on the left.
File not showing in the sidebar?
- Make sure you opened the terraform-server folder (not a parent folder like Desktop). The Explorer sidebar should show TERRAFORM-SERVER at the top.
- Check that the file is named exactly terraform.tf (not terraform.tf.txt or similar).
Help me troubleshoot my terraform.tf file not appearing in VS Code
Create variables.tf for flexible configuration
Variables let you change values (like the AWS region or instance name) without editing the core infrastructure code. This makes your configuration reusable across different environments.
- Create another new file in VS Code by clicking the new file icon in the Explorer sidebar.
- Name the file variables.tf.
- Paste the following code into variables.tf:
variable "aws_region" {
description = "AWS region to deploy resources"
type = string
default = "us-east-1"
}
variable "instance_name" {
description = "Name tag for the EC2 instance"
type = string
default = "my-terraform-server"
}
What does this code do?
Each variable block defines an input your configuration can accept.
- aws_region controls which AWS region your resources deploy to. The default is us-east-1 (the same region you configured in Step 1).
- instance_name sets the Name tag on your EC2 instance. Tags help you identify resources in the AWS Console.
- The default values mean you can run Terraform without passing any arguments. You can override them later if needed.
- Save variables.tf.
- You should now see both terraform.tf and variables.tf listed in the Explorer sidebar.
Seeing a syntax error underline?
- If VS Code highlights parts of the file, it may not recognize .tf files yet. This is cosmetic and will not affect Terraform. You can optionally install the HashiCorp Terraform extension for syntax highlighting.
Help me fix syntax issues in my variables.tf file
✔️ Awesome, I've got everything!
Great. Make sure both files are saved before moving on to the next substep.
ⓧ I'd like to double check the full code
Here is the complete terraform.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
required_version = ">= 1.2"
}
Here is the complete variables.tf:
variable "aws_region" {
description = "AWS region to deploy resources"
type = string
default = "us-east-1"
}
variable "instance_name" {
description = "Name tag for the EC2 instance"
type = string
default = "my-terraform-server"
}
Run terraform init to download the AWS provider
Before Terraform can do anything with your configuration, it needs to download the provider plugin you declared. The terraform init command reads your terraform.tf file, downloads the AWS provider, and sets up your working directory.
- Open a terminal inside VS Code by pressing Ctrl+` (backtick key, works on both macOS and Windows).
- Make sure the terminal shows you are inside the terraform-server folder. If not, run cd ~/Desktop/terraform-server.
- Initialize your Terraform workspace by running this command:
terraform init
Terraform will download the AWS provider plugin. You should see a message saying Terraform has been successfully initialized!
What did terraform init do?
- Created a .terraform/ directory containing the downloaded AWS provider plugin.
- Created a .terraform.lock.hcl file that records the exact provider version installed. This locks the version so future runs use the same provider.
- Confirm the new files were created by running:
ls -a
You should see .terraform, .terraform.lock.hcl, terraform.tf, and variables.tf in the output.
Seeing a provider error?
- If the error mentions credentials, double check that you ran aws configure in Step 1 with valid Access Key ID and Secret Access Key values.
- If it says the provider could not be found, check that terraform.tf has source = "hashicorp/aws" spelled exactly as shown.
- Make sure your terminal is inside the terraform-server folder (not a parent folder). Terraform looks for .tf files in the current directory.
Help me debug my terraform init error
Your Terraform workspace is initialized and ready to go. Next up, you will define the actual cloud infrastructure (an EC2 instance and security group) that Terraform will create for you.
Define Your Infrastructure
Your Terraform workspace is initialized and ready to accept infrastructure definitions. Now comes the exciting part: writing the code that tells AWS exactly what to create.
In this step, you will define a cloud server, configure network access rules, and set up outputs that display useful connection information after deployment. Everything lives in simple text files that Terraform reads and executes.
In this step, get ready to:
- Define the AWS provider and look up the latest Ubuntu AMI.
- Create a security group allowing HTTP traffic and an EC2 instance.
- Set up outputs to display your server's public IP and instance ID.
Create main.tf with the provider and AMI lookup
The main.tf file is where your actual infrastructure lives. It starts with the provider configuration (which cloud to use) and a data source that finds the right server image.
- In VS Code, press Cmd+N (macOS) or Ctrl+N (Windows) to create a new file.
- Save it as main.tf in your project folder by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Add the AWS provider and AMI data source by pasting this code:
provider "aws" {
region = var.aws_region
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
}
owners = ["099720109477"]
}
What does this code do?
The provider "aws" block tells Terraform to communicate with AWS. The region value comes from the variable you defined in variables.tf earlier.
The data "aws_ami" block is a data source. Instead of hardcoding a server image ID (which changes by region), it searches AWS for the most recent Ubuntu 24.04 AMI published by Canonical (owner 099720109477).
- Save main.tf.
- Verify the syntax is correct by running this command in your terminal:
terraform validate
You should see Success! The configuration is valid. in the output.
Seeing a validation error?
- Check that your main.tf file is saved in the same folder as terraform.tf and variables.tf.
- Make sure all opening braces { have matching closing braces }. HCL is strict about bracket pairing.
- Confirm the filter value string uses square brackets: ["ubuntu/images/..."].
Help me fix my terraform validate error
Add a security group and EC2 instance
Your server needs network rules controlling what traffic can reach it. In AWS, a security group acts as a virtual firewall for your instance.
- In main.tf, add the security group resource below the data source by pasting this code:
resource "aws_security_group" "web" {
name = "terraform-web-sg"
description = "Allow HTTP inbound traffic"
ingress {
description = "HTTP from anywhere"
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 = {
Name = "terraform-web-sg"
}
}
What does this security group do?
The ingress block allows inbound HTTP traffic on port 80 from any IP address (0.0.0.0/0). This means anyone on the internet can send web requests to your server.
The egress block allows all outbound traffic (protocol -1 means any protocol). This lets your server respond to requests and download updates.
- Save main.tf.
You won't see a visible change yet. The next chunk uses this security group in the EC2 instance definition.
Now you have the network rules ready. The final piece of main.tf is the EC2 instance itself.
- Add the EC2 instance resource at the bottom of main.tf by pasting this code:
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = var.instance_name
}
}
What does this resource do?
This defines your actual cloud server. The ami pulls the Ubuntu image ID from your data source. The instance_type is t2.micro, which qualifies for the AWS Free Tier (750 hours per month in your first 12 months).
The vpc_security_group_ids line attaches the security group you just created. The Name tag uses your instance_name variable so you can identify this server in the AWS Console.
- Save main.tf.
- Run the validation command again in your terminal:
terraform validate
You should see Success! The configuration is valid. confirming all three blocks work together.
Validation failing after adding the instance?
- Make sure data.aws_ami.ubuntu.id matches the data source name exactly ("ubuntu" in both places).
- Confirm aws_security_group.web.id matches the resource name "web" in your security group block.
- Check that the instance resource sits after the security group in the file. Terraform resolves dependencies by name, not by file position, but having them in order helps you spot typos.
Help me fix my Terraform instance configuration
✔️ Awesome, I've got everything!
Great. Double check you have saved main.tf before moving on.
ⓧ I'd like to double check the full code
Here is the complete main.tf file at this point:
provider "aws" {
region = var.aws_region
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
}
owners = ["099720109477"]
}
resource "aws_security_group" "web" {
name = "terraform-web-sg"
description = "Allow HTTP inbound traffic"
ingress {
description = "HTTP from anywhere"
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 = {
Name = "terraform-web-sg"
}
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = var.instance_name
}
}
Create outputs.tf for connection information
After Terraform creates your server, you will want to know its public IP address so you can connect to it. Outputs are Terraform's way of surfacing useful values after deployment.
- Create a new file called outputs.tf in the same project folder.
- Add the output definitions by pasting this code:
output "instance_public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.app_server.public_ip
}
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.app_server.id
}
What do outputs do?
Each output block tells Terraform to print a specific value after running terraform apply. Here you are asking for the server's public IP (so you can visit it) and its instance ID (useful for AWS Console lookups).
The value field references attributes of the aws_instance.app_server resource. Terraform resolves these after the instance is created.
- Save outputs.tf.
- Run the validation one more time to confirm everything works together:
terraform validate
You should see Success! The configuration is valid. confirming all four files are correct.
Seeing a reference error for app_server?
- Make sure outputs.tf is in the same folder as main.tf. Terraform loads all .tf files in the same directory together.
- Confirm the resource name in main.tf is "app_server" (not "app-server" with a hyphen).
Help me fix my outputs.tf references
✔️ Awesome, I've got everything!
Great. Double check you have saved outputs.tf before moving on.
ⓧ I'd like to double check the full code
Here is the complete outputs.tf file:
output "instance_public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.app_server.public_ip
}
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.app_server.id
}
Your infrastructure is fully defined in code. Next up, you will run terraform plan to preview exactly what Terraform will create, then deploy it live to AWS.
Plan and Deploy Your Server
Your Terraform configuration is complete. Four files define everything your cloud server needs, from the provider and AMI lookup to the security rules and output values.
Now it is time to bring that configuration to life. Terraform separates planning from execution, so you will first preview exactly what will change before committing to real infrastructure.
In this step, get ready to:
- Preview your execution plan with terraform plan.
- Deploy your EC2 instance and security group with terraform apply.
- Verify the running instance in the AWS Console.
Preview your execution plan
The terraform plan command is Terraform's dry run. It reads your configuration files, compares them against the current state (which is empty right now), and shows you exactly what it intends to create.
- Preview the resources Terraform will create by running this command:
terraform plan
Terraform reads your files, queries the AWS API for the latest Ubuntu AMI, and outputs a detailed execution plan. This may take a few seconds.
What does this output mean?
The plan output uses a + symbol to indicate that a resource will be created. You should see aws_security_group.web and aws_instance.app_server listed as resources to be created.
At the bottom, a summary line reads Plan: 2 to add, 0 to change, 0 to destroy. confirming two resources will be created and nothing will be modified or removed.
No real resources have been created yet. This is only a preview of what Terraform intends to do.
What is an execution plan?
An execution plan is Terraform's proposal for reaching your desired state. It compares your configuration against reality (tracked in state) and calculates the minimum set of changes needed.
This safety mechanism means you always review changes before they touch real infrastructure.
- Confirm the plan summary shows 2 resources to add and 0 to change or destroy.
Seeing an error instead of a plan?
- If you see a credentials error, double-check that aws configure completed successfully in Step 1. Run aws sts get-caller-identity to verify your credentials are working.
- If you see a provider error, make sure you ran terraform init successfully in Step 2. The .terraform directory should exist in your project folder.
Help me debug my terraform plan error
Deploy your infrastructure
The terraform apply command performs the same planning step, then actually creates the resources on AWS. It asks for your explicit confirmation before making any changes.
- Deploy your server and security group by running this command:
terraform apply
What happens during apply?
Terraform first shows you the same execution plan you saw with terraform plan. It then displays a confirmation prompt before proceeding.
You will see a message stating Only 'yes' will be accepted to approve. followed by Enter a value: waiting for your input. Type the full word yes (not just "y") and press Enter to confirm.
- When Terraform shows the confirmation prompt, type yes and press Enter.
Terraform begins creating your resources. You will see status updates as each resource is provisioned. The EC2 instance may take 30-60 seconds to finish.
- Wait for the process to complete. You should see Apply complete! Resources: 2 added, 0 changed, 0 destroyed. in your terminal.
- Below that, Terraform displays your output values: instance_public_ip (the server's public IP address) and instance_id (the unique AWS identifier for your instance).
Save your public IP
Note down the instance_public_ip value from the output. This is the public address of your new server. You can always retrieve it later by running terraform output.
Apply failed or timed out?
- If you see a permissions error, your IAM user may not have EC2 or VPC permissions. Verify that your AWS user has the required policies attached.
- If the command times out, your network connection to AWS may be unstable. Run terraform apply again. Terraform picks up where it left off thanks to the state file.
Help me fix my terraform apply error
Verify the instance in the AWS Console
The terminal output confirms your resources exist. Let's also verify in the AWS Console to see your server with your own eyes.
- Open your browser and go to the AWS Management Console at https://console.aws.amazon.com.
- In the search bar at the top, type EC2 and select the EC2 service.
- Click Instances in the left sidebar.
- Confirm the region in the top-right corner is set to US East (N. Virginia) us-east-1. If it shows a different region, select us-east-1 from the dropdown.
- You should see an instance named my-terraform-server with a state of Running.
What should I see?
Your instance list shows one entry with the Name tag my-terraform-server, instance type t2.micro, and a status of Running. The public IP address should match the instance_public_ip output from your terminal.
Don't see your instance?
- Check that your region is set to us-east-1 in the top-right corner of the console. Instances only appear in the region where they were created.
- If the instance shows a status other than Running, wait a minute and refresh the page. New instances take a moment to fully start.
Help me find my EC2 instance in the AWS Console
Your server is live. You just deployed real cloud infrastructure entirely through code. Next up, you will modify your configuration to see how Terraform handles changes, then cleanly tear everything down.
Modify and Destroy Infrastructure
Your server is live on AWS, deployed entirely through code. But real-world infrastructure evolves constantly. Servers get renamed, configurations shift, and eventually resources need to be retired.
In this step, you will experience the full lifecycle of Infrastructure as Code. You will modify your running server's configuration, watch Terraform handle the update in-place, and then cleanly destroy everything with a single command.
In this step, get ready to:
- Update your EC2 instance's Name tag and apply the change.
- Destroy all infrastructure with a single command.
- Review Terraform's state file to understand how it tracks resources.
Update your instance's Name tag
Changing a tag on an EC2 instance is an in-place update. Terraform does not need to destroy and recreate the server. It simply modifies the tag on the existing instance.
- In variables.tf, find this line:
default = "my-terraform-server"
- Replace "my-terraform-server" with "my-updated-server", so the line now looks like this:
default = "my-updated-server"
- Save variables.tf.
- Preview the change by running this command:
terraform plan
You should see output indicating an in-place update. Look for the ~ symbol and a line showing your Name tag changing from my-terraform-server to my-updated-server.
What does ~ update in-place mean?
The ~ prefix in Terraform's plan output means the resource will be updated without being destroyed and recreated. Tags on an EC2 instance can be changed in-place because AWS supports modifying tags on a running instance.
If a change required recreation (like switching to a different instance type family), you would see -/+ instead, meaning Terraform would destroy and then create a replacement.
- Apply the change by running:
terraform apply
- Terraform shows the plan again and asks for confirmation. Type yes and press Enter.
You should see output ending with something like: Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
Seeing an error about credentials?
If Terraform reports authentication errors, your AWS credentials may have expired. Run aws configure again to re-enter your Access Key ID and Secret Access Key, then retry the command.
help me fix this Terraform authentication error
- Now that you have seen how Terraform handles updates, restore the original name. In variables.tf, change "my-updated-server" back to "my-terraform-server":
default = "my-terraform-server"
- Save variables.tf.
Destroy all your infrastructure
When you no longer need your infrastructure, Terraform can remove everything it created with a single command. This is the inverse of terraform apply.
- Tear down all your AWS resources by running:
terraform destroy
- Terraform shows a destroy plan listing every resource it will delete. You will see a confirmation prompt that says: "Do you really want to destroy all resources?" along with "There is no undo. Only 'yes' will be accepted to confirm."
- Type yes and press Enter to confirm.
Terraform destroys each resource in the correct dependency order. You should see output ending with: Destroy complete! Resources: 2 destroyed.
Why does Terraform destroy in a specific order?
Terraform builds a dependency graph of your resources. It knows the EC2 instance depends on the security group, so it destroys the instance first and the security group second. This prevents errors from trying to delete resources that others still reference.
- Verify your resources are gone by checking the AWS Console. Navigate to the EC2 dashboard. Your instance should show as terminated or be absent entirely.
Destroy seems stuck?
EC2 instances can take 30-60 seconds to fully terminate. If you see lines like "Still destroying..." with a timer, this is normal. Wait for the final confirmation message.
help me troubleshoot my terraform destroy command
Review the Terraform state file
Every time you run terraform apply or terraform destroy, Terraform updates a local file called terraform.tfstate. This file is how Terraform knows what exists in the real world.
- Open terraform.tfstate in VS Code by clicking on it in the Explorer sidebar.
You should see a JSON file with an empty resources array. This is because terraform destroy removed all tracked resources from the state.
What is the state file for?
The state file is Terraform's memory. It maps the resource blocks in your .tf files to real infrastructure in AWS. Without it, Terraform would not know which EC2 instance corresponds to aws_instance.app_server in your code.
Before you destroyed everything, this file contained the instance ID, public IP, security group ID, and every other attribute of your resources. Now it is empty, confirming that no infrastructure is managed.
In production, teams store state remotely (in S3 or HCP Terraform) so multiple people can collaborate safely. The local file works for learning, but should never be committed to version control because it can contain sensitive values.
You can always recreate
Your .tf configuration files are still intact. If you ever want this infrastructure again, just run terraform apply and Terraform will recreate everything from scratch.
✔️ Awesome, I've got everything!
Great. Make sure you have saved all your files.
ⓧ I'd like to double check the full code
Here is the full variables.tf (the only file with a change in this step, now restored to original):
variable "aws_region" {
description = "AWS region to deploy resources"
type = string
default = "us-east-1"
}
variable "instance_name" {
description = "Name tag for the EC2 instance"
type = string
default = "my-terraform-server"
}
All other files (main.tf, outputs.tf, terraform.tf) remain unchanged from the previous step.
Secret mission
Add S3 Storage with IAM Access
Your EC2 server is deployed, but it is isolated from other AWS services. Real-world servers almost always need access to storage. Can you extend your Terraform configuration to add an S3 bucket and grant your EC2 instance permission to read and write objects in it?
Clean Up Your Resources
Clean Up Your Resources
You already ran terraform destroy during this project, so your AWS cloud resources are not running. Decide whether to keep your local project files for future use or delete them entirely.
Cost warning
If you re-deploy your infrastructure by running terraform apply again, the t2.micro instance is covered under the AWS Free Tier for 750 hours per month in your first 12 months. After that, standard EC2 charges apply.
If you re-deploy, always run terraform destroy when you are done experimenting to avoid unexpected charges.
Resources you used:
- AWS cloud resources (EC2 instance, security group, S3 bucket, IAM role, IAM policy, IAM instance profile). Already destroyed.
- Local Terraform project files (main.tf, variables.tf, outputs.tf, terraform.tf, .terraform/ directory, terraform.tfstate, .terraform.lock.hcl).
- AWS CLI (installed via MSI).
- AWS account (if created for this project).
Keep everything running
No action needed. Choose this if you plan to keep experimenting with Terraform or want to re-deploy your infrastructure later.
- Your local .tf files stay on your Desktop, ready to use with terraform apply whenever you want.
- Your AWS cloud resources are already destroyed from running terraform destroy earlier, so nothing is costing you money.
- Terraform CLI remains installed on your machine. It is a lightweight standalone binary that takes minimal space.
- AWS CLI remains installed on your machine. This is useful for any future AWS projects.
Pause - I'll come back to this later
Your cloud resources are already destroyed. Your local files cost nothing to keep on disk. No further action is required to pause.
- Your Terraform project folder stays on your Desktop with all configuration files intact.
- When you are ready to come back, open your terminal, navigate to the project folder, and run terraform apply to re-create everything.
- No running cloud resources means no charges while you are away.
Delete - I don't want to use this again
Remove all project files and tools from your machine. Follow each step below that applies to you.
If you re-deployed your infrastructure after the earlier destroy, run this to remove all cloud resources:
terraform destroy
- Type yes when prompted to confirm the destruction of all resources.
Remove your local project folder. On macOS or Linux:
cd ~/Desktop
rm -rf terraform-project
On Windows (PowerShell):
cd ~\Desktop
Remove-Item -Recurse -Force terraform-project
- Replace terraform-project with whatever you named your project folder.
To uninstall the AWS CLI on Windows:
- Open Settings.
- Select Apps, then Installed apps.
- Find AWS Command Line Interface and select Uninstall.
To remove your stored AWS credentials:
Remove-Item -Recurse -Force ~\.aws
On macOS or Linux:
rm -rf ~/.aws
What about Terraform CLI?
Terraform is a standalone binary with no formal uninstaller. If you installed it via Chocolatey, you can run choco uninstall terraform in an elevated terminal. If you downloaded the binary manually, locate and delete the terraform.exe file from whatever directory you placed it in.
That's a Wrap!
That's a Wrap!
Nice work! You just deployed real cloud infrastructure with nothing but code.
You've learned how to:
- Written HCL configuration files that define cloud infrastructure as code, including providers, resources, data sources, variables, and outputs.
- Used the full Terraform lifecycle (init, plan, apply, destroy) to create, modify, and tear down infrastructure on demand.
- Deployed a live EC2 instance with a security group using declarative configuration that can be versioned, shared, and repeated.
- Secret Mission: Added an S3 bucket with IAM-based access control to your infrastructure, granting your EC2 instance secure read/write access to cloud storage.
Ready to quiz yourself?