Terraform Commands Cheat Sheet: init, plan, apply, destroy, and More
Complete Terraform commands reference. Learn terraform init, plan, apply, destroy, state, import, output, workspace, fmt, validate
Cloud Computing
Step-by-step guide to terraform import. Import existing AWS, Azure, and GCP resources into Terraform state. Includes import blocks (Terraform 1.5+)
You have cloud resources running in production that weren't created with Terraform. Maybe they were created manually in the AWS console, or through a different tool. Now you want to manage them with Terraform without recreating them.
That's exactly what terraform import does — it brings existing infrastructure under Terraform management by adding it to the state file.
Import an existing AWS EC2 instance:
# 1. Write the resource block in your .tf file
# main.tf
resource "aws_instance" "web" {
# Configuration will be filled after import
}
# 2. Import the resource
terraform import aws_instance.web i-1234567890abcdef0
# 3. Verify the import
terraform state show aws_instance.web
# 4. Fill in the configuration to match the actual resource
# Run terraform plan — it should show "No changes"The classic approach — one resource at a time:
terraform import <resource_type>.<name> <resource_id>Examples:
# AWS EC2 instance
terraform import aws_instance.web i-1234567890abcdef0
# AWS S3 bucket
terraform import aws_s3_bucket.data my-bucket-name
# AWS Security Group
terraform import aws_security_group.web sg-0123456789abcdef0
# AWS VPC
terraform import aws_vpc.main vpc-0123456789abcdef0
# Azure Resource Group
terraform import azurerm_resource_group.main /subscriptions/SUB_ID/resourceGroups/my-rg
# GCP Compute Instance
terraform import google_compute_instance.web projects/my-project/zones/us-central1-a/instances/my-vmImport blocks are declarative — add them to your .tf files and run terraform plan:
# imports.tf
import {
to = aws_instance.web
id = "i-1234567890abcdef0"
}
import {
to = aws_s3_bucket.data
id = "my-bucket-name"
}
import {
to = aws_security_group.web
id = "sg-0123456789abcdef0"
}Then run:
terraform plan -generate-config-out=generated.tfTerraform generates the configuration automatically. Review generated.tf, clean it up, and merge it into your main configuration.
Advantages of import blocks:
aws ec2 describe-instances --filters "Name=tag:Name,Values=my-server" \
--query "Reservations[].Instances[].InstanceId" --output textOutput: i-0abc123def456789
Create a minimal resource block in your .tf file:
resource "aws_instance" "web" {
# Required attributes — we'll fill these after import
ami = "ami-placeholder"
instance_type = "t3.micro"
}terraform import aws_instance.web i-0abc123def456789Output:
aws_instance.web: Importing from ID "i-0abc123def456789"...
aws_instance.web: Import prepared!
Prepared aws_instance for import
aws_instance.web: Refreshing state... [id=i-0abc123def456789]
Import successful!terraform state show aws_instance.webThis prints all attributes. Copy the relevant ones into your resource block:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
subnet_id = "subnet-0123456789abcdef0"
key_name = "my-key"
vpc_security_group_ids = ["sg-0123456789abcdef0"]
root_block_device {
volume_size = 20
volume_type = "gp3"
}
tags = {
Name = "my-server"
}
}terraform planShould show:
No changes. Your infrastructure matches the configuration.If it shows changes, update your configuration to match the actual resource state.
# imports.tf — import your entire VPC setup
import {
to = aws_vpc.main
id = "vpc-0123456789"
}
import {
to = aws_subnet.public_a
id = "subnet-aaa111"
}
import {
to = aws_subnet.public_b
id = "subnet-bbb222"
}
import {
to = aws_internet_gateway.main
id = "igw-0123456789"
}
import {
to = aws_route_table.public
id = "rtb-0123456789"
}terraform plan -generate-config-out=generated_vpc.tfFor many resources of the same type:
#!/bin/bash
# Import all EC2 instances with a specific tag
INSTANCES=$(aws ec2 describe-instances \
--filters "Name=tag:Environment,Values=production" \
--query "Reservations[].Instances[].InstanceId" \
--output text)
i=0
for id in $INSTANCES; do
terraform import "aws_instance.prod[$i]" "$id"
((i++))
done# VPC
terraform import aws_vpc.main vpc-12345
# Subnet
terraform import aws_subnet.public subnet-12345
# Security Group
terraform import aws_security_group.web sg-12345
# RDS Instance
terraform import aws_db_instance.main my-database
# IAM Role
terraform import aws_iam_role.lambda my-lambda-role
# S3 Bucket
terraform import aws_s3_bucket.logs my-log-bucket
# Route53 Zone
terraform import aws_route53_zone.main Z1234567890# Resource Group
terraform import azurerm_resource_group.main \
/subscriptions/SUB_ID/resourceGroups/my-rg
# Virtual Network
terraform import azurerm_virtual_network.main \
/subscriptions/SUB_ID/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet
# Storage Account
terraform import azurerm_storage_account.main \
/subscriptions/SUB_ID/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount# Compute Instance
terraform import google_compute_instance.web \
projects/my-project/zones/us-central1-a/instances/my-vm
# GKE Cluster
terraform import google_container_cluster.primary \
projects/my-project/locations/us-central1/clusters/my-cluster
# Cloud Storage Bucket
terraform import google_storage_bucket.data my-bucketError: Resource already managed by TerraformThe resource is already in your state. Check with:
terraform state list | grep aws_instanceError: Cannot import non-existent remote objectThe resource ID is wrong or the resource was deleted. Verify it exists:
aws ec2 describe-instances --instance-ids i-1234567890abcdef0If terraform plan shows changes after import, your .tf configuration doesn't match the real resource. Update your config to match, or accept the drift by running apply.
cp terraform.tfstate terraform.tfstate.backup before importingLearn by doing with interactive courses on CopyPasteLearn:
terraform import bridges the gap between manually created infrastructure and Terraform management. Use the CLI command for quick one-off imports, and import blocks (Terraform 1.5+) for bulk imports with auto-generated configurations. Always verify with terraform plan after importing to ensure your configuration matches the real infrastructure.
Complete Terraform commands reference. Learn terraform init, plan, apply, destroy, state, import, output, workspace, fmt, validate
Learn how to use Terraform data sources to query existing resources, look up AMIs, reference remote state, and build dynamic configurations. Complete.
Enable Terraform debug mode with TF_LOG=DEBUG, save logs to file with TF_LOG_PATH, and troubleshoot terraform plan/apply errors.
Master Terraform version constraints for Terraform core and providers. Covers operators, lock files, required_version, required_providers, and upgrade...