How to Install Terraform and Create Your First Resource (Step-by-Step)
A hands-on, zero-assumptions guide to getting Terraform running and building your first piece of real infrastructure—no experience required.
📅 Published: Feb 2026
⏱️ Estimated Reading Time: 12 minutes
🏷️ Tags: Terraform, Installation, Hands-On, Beginner Tutorial, AWS, S3
🎯 Before We Begin: What You'll Need
This guide makes no assumptions about your experience level. We'll start from absolute zero and build up, step by step. By the end of this tutorial, you will have:
✅ Terraform installed on your computer
✅ Your first Terraform configuration file written and understood
✅ Real infrastructure created in the cloud (an S3 bucket on AWS)
✅ Cleaned up and destroyed everything so you don't get charged
Time required: 10-15 minutes
Cost: Free (AWS Free Tier covers everything we do)
Difficulty: Beginner—no prior Terraform or cloud experience needed
📥 Step 1: Install Terraform
First, Check if You Already Have It
Open your terminal (Command Prompt on Windows, Terminal on Mac/Linux) and type:
terraform version
If you see something like this:
Terraform v1.5.0 on darwin_amd64
Congratulations! Terraform is already installed. Jump to Step 2.
If you see command not found or similar, follow the instructions below for your operating system.
💻 Windows Installation (3 Ways)
Method 1: Chocolatey (Easiest)
# Install Chocolatey first (if you don't have it) Set-ExecutionPolicy Bypass -Scope Process -Force [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) # Install Terraform choco install terraform
Method 2: Scoop (Also Easy)
# Install Scoop first (if you don't have it) Set-ExecutionPolicy RemoteSigned -Scope CurrentUser irm get.scoop.sh | iex # Install Terraform scoop install terraform
Method 3: Manual Download (Works Everywhere)
Download the Windows 64-bit ZIP file
Extract the ZIP to
C:\terraform\Add
C:\terraform\to your System PATH:Press Windows key, type "environment variables"
Click "Edit the system environment variables"
Click "Environment Variables"
Under "System variables", find "Path" and click Edit
Click "New" and add
C:\terraform\Click OK on all windows
Open a new Command Prompt and verify:
terraform version
🍎 macOS Installation (2 Ways)
Method 1: Homebrew (Recommended)
# Install Homebrew if you don't have it /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Install Terraform brew tap hashicorp/tap brew install hashicorp/tap/terraform # Verify terraform version
Method 2: Manual Download
# Download the Intel or Apple Silicon version from terraform.io # Then unzip and move to /usr/local/bin unzip terraform_*.zip sudo mv terraform /usr/local/bin/ # Verify terraform version
🐧 Linux Installation (Ubuntu/Debian)
# Add HashiCorp GPG key wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg # Add HashiCorp repository echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list # Install Terraform sudo apt update && sudo apt install terraform # Verify terraform version
🐧 Linux Installation (RHEL/CentOS/Fedora)
# Install yum-config-manager sudo yum install -y yum-utils # Add HashiCorp repository sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo # Install Terraform sudo yum -y install terraform # Verify terraform version
✅ Verify Your Installation
No matter which method you used, open a fresh terminal and run:
terraform version
You should see output similar to:
Terraform v1.5.0 on linux_amd64
If you see this, you're ready to proceed! If not, pause here and troubleshoot. The most common issues are:
Forgetting to open a new terminal after installation
PATH not set correctly (Windows manual install)
Permission issues (Linux/macOS)
☁️ Step 2: Get Your Cloud Ready
For our first resource, we'll create an S3 bucket on Amazon Web Services (AWS). S3 is cloud storage—like Google Drive or Dropbox, but programmable.
Create an AWS Account (If You Don't Have One)
Click "Create a Free Account"
Follow the registration process
You will need to enter credit card information, but everything we do in this tutorial is covered by the Free Tier and will cost you $0.00
Create Your First IAM User (Security Credentials)
Important: Never use your root account credentials with Terraform. Always create a dedicated IAM user.
Log into AWS Console (https://console.aws.amazon.com)
Search for IAM in the top search bar
Click Users → Create user
Username:
terraform-beginnerCheck "Provide user access to the AWS Management Console"
Choose "I want to create an IAM user" (not the workforce identity option)
Set a password (check "Autogenerated password" or set your own)
Click Next
On permissions screen:
Select "Attach policies directly"
Search for and check: AmazonS3FullAccess
Click Next
Review and click Create user
IMPORTANT: Click "Show" and copy the password somewhere safe. You'll need it to sign in. Also copy the Console sign-in URL (looks like:
https://123456789012.signin.aws.amazon.com/console)
Create Access Keys (For Terraform)
Click on the user you just created
Go to Security credentials tab
Scroll to Access keys → Click Create access key
Choose "Command Line Interface (CLI)"
Check the acknowledgement box
Click Next and then Create access key
CRITICAL: This is your only chance to see these keys! Click Download .csv file and save it somewhere safe. The file contains:
Access key ID: AKIAXXXXXXXXXXXXXXXX Secret access key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Never share these keys. Never commit them to Git. Never email them. Treat them like passwords.
🔑 Step 3: Configure AWS Credentials for Terraform
Terraform needs to know how to authenticate with AWS. There are several ways to do this. We'll use the environment variables method—it's the simplest for beginners.
macOS / Linux
export AWS_ACCESS_KEY_ID="AKIAXXXXXXXXXXXXXXXX" export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" export AWS_DEFAULT_REGION="us-east-1"
Make it permanent (so you don't have to type every time):
echo 'export AWS_ACCESS_KEY_ID="AKIAXXXXXXXXXXXXXXXX"' >> ~/.bashrc echo 'export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"' >> ~/.bashrc echo 'export AWS_DEFAULT_REGION="us-east-1"' >> ~/.bashrc source ~/.bashrc
Windows (Command Prompt)
set AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX set AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY set AWS_DEFAULT_REGION=us-east-1
Windows (PowerShell)
$env:AWS_ACCESS_KEY_ID = "AKIAXXXXXXXXXXXXXXXX" $env:AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" $env:AWS_DEFAULT_REGION = "us-east-1"
✅ Verify Your AWS Credentials
Before proceeding, let's confirm AWS can authenticate you:
aws sts get-caller-identity
If you see output like this, you're authenticated:
{ "UserId": "AIDAXXXXXXXXXXXXXXXXX", "Account": "123456789012", "Arn": "arn:aws:iam::123456789012:user/terraform-beginner" }
If you get an error, check:
Did you export the variables in the same terminal you're running Terraform in?
Are the access key and secret key copied correctly?
Did you wait a minute or two for AWS to propagate the new credentials?
📁 Step 4: Create Your Project Directory
Organization matters. Even for your first project, create a dedicated directory:
# Create a new directory mkdir ~/terraform-first-project # Move into it cd ~/terraform-first-project # Verify you're in the right place pwd # Should show: /home/yourusername/terraform-first-project
Why? Terraform creates files and state in your current directory. Keeping projects isolated prevents accidental mixing of configurations.
📝 Step 5: Write Your First Terraform Configuration
Create a file called main.tf in your project directory:
touch main.tfNow open it in your text editor. If you don't have a preference, these commands work:
VS Code:
code main.tf
Vim:
vim main.tfNano:
nano main.tfNotepad (Windows):
notepad main.tf
Copy and paste this entire configuration into your file. Every line is explained below.
# main.tf # My first Terraform configuration! # This creates an S3 bucket on AWS. terraform { # Terraform version constraint - ensures compatibility required_version = ">= 1.5.0" # Required providers required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } # Configure the AWS provider provider "aws" { region = "us-east-1" # Virginia, USA - Free Tier eligible } # Generate a random suffix for globally unique bucket names resource "random_string" "bucket_suffix" { length = 8 special = false upper = false } # This is the actual resource we're creating resource "aws_s3_bucket" "my_first_bucket" { # Bucket names must be globally unique across all AWS accounts! bucket = "terraform-first-bucket-${random_string.bucket_suffix.result}" # Tags help organize resources tags = { Name = "My First Terraform Bucket" Environment = "Learning" ManagedBy = "Terraform" CreatedBy = "Your Name Here" # ← Put your name here! Purpose = "Learning Terraform" } } # Output the bucket name so we can see it output "bucket_name" { description = "The name of our S3 bucket" value = aws_s3_bucket.my_first_bucket.bucket } output "bucket_arn" { description = "The ARN (Amazon Resource Name) of our bucket" value = aws_s3_bucket.my_first_bucket.arn } output "bucket_url" { description = "The URL to access the bucket" value = "https://${aws_s3_bucket.my_first_bucket.bucket}.s3.amazonaws.com/" }
Save the file. That's it. You've just written Infrastructure as Code.
📖 What Did We Just Write?
Line-by-line explanation (so you actually understand):
| Line | What it does | Why it matters |
|---|---|---|
terraform { ... } | Terraform configuration block | Configures Terraform itself, not the infrastructure |
required_version | Specifies Terraform version | Prevents using incompatible versions |
required_providers | Lists needed providers | Tells Terraform what plugins to download |
aws provider | AWS plugin configuration | Terraform uses this to talk to AWS APIs |
source = "hashicorp/aws" | Official AWS provider | Verified, trusted provider from HashiCorp |
version = "~> 5.0" | Provider version constraint | "Use any 5.x version but not 6.0" |
provider "aws" { region } | AWS region setting | Where in the world to create resources |
resource "random_string" | Generate random characters | Makes bucket names unique |
aws_s3_bucket | An S3 bucket resource | The actual infrastructure we're creating |
bucket = | The bucket's name | Must be globally unique across all AWS! |
${random_string...} | String interpolation | Inserts the random suffix into the name |
tags = { ... } | Metadata labels | Helps track and organize resources |
output "bucket_name" | Display after apply | Shows us the bucket name at the end |
⚡ Step 6: Initialize Terraform
Now we tell Terraform to download the providers and set up the working directory:
terraform init
You should see:
Initializing the backend... Initializing provider plugins... - Finding hashicorp/aws versions matching "~> 5.0"... - Finding latest version of hashicorp/random... - Installing hashicorp/aws v5.0.0... - Installed hashicorp/aws v5.0.0 (signed by HashiCorp) - Installing hashicorp/random v3.5.0... - Installed hashicorp/random v3.5.0 (signed by HashiCorp) Terraform has been successfully initialized!
What just happened:
Terraform created a
.terraformdirectory (this is where providers live)It downloaded the AWS and Random providers
It created a
.terraform.lock.hclfile (records exact provider versions)
Never delete the .terraform directory. If you do, just run terraform init again.
🔍 Step 7: Preview Your Changes (The Terraform Plan)
This is the most important step. Before creating anything, Terraform shows you exactly what it will do:
terraform plan
Read the output carefully. It should show something like:
Terraform will perform the following actions:
# random_string.bucket_suffix will be created
+ resource "random_string" "bucket_suffix" {
+ id = (known after apply)
+ length = 8
+ lower = true
+ result = (known after apply)
+ special = false
+ upper = false
}
# aws_s3_bucket.my_first_bucket will be created
+ resource "aws_s3_bucket" "my_first_bucket" {
+ bucket = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ tags = {
+ "CreatedBy" = "Your Name Here"
+ "Environment" = "Learning"
+ "ManagedBy" = "Terraform"
+ "Name" = "My First Terraform Bucket"
+ "Purpose" = "Learning Terraform"
}
+ tags_all = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.The + symbol means "add" or "create". There's no - or ~ symbols, so nothing will be deleted or modified.
If you see errors at this stage, they're usually:
AWS credentials not configured → Check your environment variables
Invalid bucket name → Did you edit the bucket name? Remove special characters
Provider version mismatch → Make sure your Terraform version is >=1.5
🚀 Step 8: Create Your Infrastructure
Now the exciting part—actually creating real infrastructure:
terraform apply
Terraform will show you the plan again and wait for confirmation:
Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value:
Type yes and press Enter.
random_string.bucket_suffix: Creating... random_string.bucket_suffix: Creation complete after 0s [id=n4x7k2p9] aws_s3_bucket.my_first_bucket: Creating... aws_s3_bucket.my_first_bucket: Creation complete after 3s [id=terraform-first-bucket-n4x7k2p9] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: bucket_arn = "arn:aws:s3:::terraform-first-bucket-n4x7k2p9" bucket_name = "terraform-first-bucket-n4x7k2p9" bucket_url = "https://terraform-first-bucket-n4x7k2p9.s3.amazonaws.com/"
🎉 CONGRATULATIONS! You just created real cloud infrastructure with Terraform!
👀 Step 9: Verify It Actually Worked
Method 1: AWS Console
Log into AWS Console (https://console.aws.amazon.com)
Search for S3 in the top search bar
Click S3
Look for a bucket named
terraform-first-bucket-xxxxxxClick on it—you'll see it's empty, but it exists!
Method 2: AWS CLI
aws s3 ls | grep terraform-first-bucket
You should see your bucket listed.
Method 3: Terraform State
terraform state list
This shows every resource Terraform is managing:
random_string.bucket_suffix aws_s3_bucket.my_first_bucket
🔧 Step 10: Make a Change (Optional)
Let's modify our bucket to see how Terraform handles changes.
Open main.tf and add this block right after the aws_s3_bucket resource:
# Add versioning to our bucket resource "aws_s3_bucket_versioning" "my_first_bucket_versioning" { bucket = aws_s3_bucket.my_first_bucket.id versioning_configuration { status = "Enabled" } }
Save the file. Now run:
terraform plan
Notice Terraform now shows 1 to add (the versioning configuration). It doesn't need to recreate the bucket—it just adds the new setting.
terraform apply
# Type 'yes'Now your bucket has versioning enabled! You just made an infrastructure change safely, predictably, and with a full preview before execution.
🧹 Step 11: Clean Up (Critical!)
This is not optional. If you don't destroy your resources, AWS will bill you (though S3 buckets are very cheap—pennies per month). But forming good habits now will save you hundreds of dollars later.
terraform destroy
Terraform will show you everything it will destroy:
Plan: 0 to add, 0 to change, 2 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value:
Type yes and press Enter.
random_string.bucket_suffix: Destroying... [id=n4x7k2p9] random_string.bucket_suffix: Destruction complete after 0s aws_s3_bucket_public_access_block.my_first_bucket: Destroying... aws_s3_bucket_public_access_block.my_first_bucket: Destruction complete aws_s3_bucket_versioning.my_first_bucket: Destroying... aws_s3_bucket_versioning.my_first_bucket: Destruction complete aws_s3_bucket.my_first_bucket: Destroying... aws_s3_bucket.my_first_bucket: Destruction complete Destroy complete! Resources: 3 destroyed.
✅ Your infrastructure is gone. No orphaned resources. No surprise bills. Clean as a whistle.
🎓 What You've Learned
In just 15 minutes, you have:
✅ Installed Terraform on your computer
✅ Configured AWS credentials securely
✅ Written your first Infrastructure as Code configuration
✅ Understood every line of Terraform code you wrote
✅ Created real cloud infrastructure (S3 bucket)
✅ Verified it existed in the cloud
✅ Made a change to your infrastructure
✅ Cleaned up everything with terraform destroy
This is the exact same workflow that companies like Netflix, Shopify, and Airbnb use to manage millions of dollars of cloud infrastructure. The only difference is scale.
🚨 Troubleshooting: What If Something Went Wrong?
"terraform: command not found"
Cause: Terraform isn't installed or not in your PATH
Fix: Revisit Step 1. Open a new terminal after installation.
"No valid credential sources found"
Cause: AWS credentials not configured
Fix: Check your environment variables:
echo $AWS_ACCESS_KEY_ID echo $AWS_SECRET_ACCESS_KEY
If empty, re-export them or use aws configure.
"BucketAlreadyExists"
Cause: Someone else already used that exact bucket name
Fix: This shouldn't happen with our random suffix. If it does, the random suffix might not have been applied. Check your configuration.
"AccessDenied" when creating bucket
Cause: Your IAM user doesn't have S3 permissions
Fix: Go back to IAM console and attach AmazonS3FullAccess policy
"Invalid bucket name"
Cause: Bucket names can only contain lowercase letters, numbers, and hyphens
Fix: Check for underscores or uppercase letters in your bucket name
"Error acquiring the state lock"
Cause: Another Terraform process is running
Fix: Wait a moment, or if no other process exists, force unlock:
terraform force-unlock LOCK_ID
📁 Your Project Directory After All Steps
terraform-first-project/ │ ├── main.tf # Your infrastructure code ├── terraform.tfstate # State file (DO NOT EDIT!) ├── terraform.tfstate.backup # Previous state backup ├── .terraform.lock.hcl # Provider version lock file ├── .terraform/ # Provider plugins (auto-generated) │ └── providers/ └── README.md # (Optional) Your notes
Which files to commit to Git:
✅ main.tf - YES, this is your code
✅ .terraform.lock.hcl - YES, this ensures consistent provider versions
❌ terraform.tfstate - NO, never commit state (contains secrets)
❌ .terraform/ - NO, this is auto-generated
Add this to your .gitignore:
.terraform/ *.tfstate *.tfstate.backup *.tfvars
🏆 Your Next Challenges
Now that you've mastered the basics, try these:
Challenge 1: Change the region to us-west-2 (Oregon)
Challenge 2: Add tags like Project = "My Learning"
Challenge 3: Create two buckets instead of one (hint: copy the resource block)
Challenge 4: Add a second output for bucket_regional_domain_name
Challenge 5: Upload a file to your bucket using Terraform (search for aws_s3_object)
Each challenge reinforces what you learned today. Try them—you won't break anything, and terraform destroy will clean up any mess!
🔗 Continue Your Terraform Journey
This was your first step. You've proven you can install Terraform, configure it, write configurations, create real infrastructure, and clean up after yourself. That's more than many professionals who've been "using the cloud" for years.
👉 Master Terraform with 50+ hands-on exercises and real cloud projects at:
https://devops.trainwithsky.com/
What you'll get:
Free AWS sandbox account (no credit card required!)
Guided projects: web servers, databases, Kubernetes clusters
Real-time validation of your configurations
Step-by-step video walkthroughs
Certification of completion
Start your next lab now—you already have the foundation. 🚀
📋 Quick Reference: Terraform Command Cheat Sheet
# Setup and initialization terraform version # Check Terraform version terraform init # Initialize working directory terraform fmt # Format code consistently terraform validate # Check configuration validity # Daily workflow terraform plan # Preview changes terraform apply # Apply changes (prompts for yes) terraform apply -auto-approve # Apply without prompting (scripts) terraform destroy # Destroy everything # State management terraform state list # List managed resources terraform state show ADDRESS # Show details of specific resource terraform output # Show output values # Advanced terraform console # Interactive console for testing terraform refresh | Update state with real infrastructure terraform import # Import existing resources terraform workspace # Manage multiple environments
Questions? Stuck somewhere? Every Terraform expert was once exactly where you are now. Post your question in the comments below—our community is friendly and loves helping beginners! 💬
Comments
Post a Comment