Terraform Remote State - S3 Backend with DynamoDB Locking
Configure Terraform remote state with AWS S3 and DynamoDB locking. Complete setup with encryption, versioning, IAM permissions, and team access patterns.
DevOps
Step-by-step guide to importing existing cloud resources into Terraform state. Import blocks, generate config, import CLI, and avoid common pitfalls.
Use terraform import CLI or import blocks (Terraform 1.5+) to bring existing cloud resources under Terraform management without recreating them. Write the matching HCL config first, then import. Always run terraform plan after importing to check for drift.
Organizations often have resources created manually via console, CLI, or other tools. Terraform import lets you manage these existing resources as code — gaining version control, change tracking, and reproducibility.
# main.tf
import {
to = aws_s3_bucket.data
id = "my-existing-bucket"
}
resource "aws_s3_bucket" "data" {
bucket = "my-existing-bucket"
}# Generate config automatically
terraform plan -generate-config-out=generated.tf
# Review the generated config, then apply
terraform applyBenefits of import blocks:
generate-config-out writes the HCL for youterraform plan before applyinglocals {
existing_buckets = {
data = "my-data-bucket"
logs = "my-logs-bucket"
backup = "my-backup-bucket"
}
}
import {
for_each = local.existing_buckets
to = aws_s3_bucket.imported[each.key]
id = each.value
}
resource "aws_s3_bucket" "imported" {
for_each = local.existing_buckets
bucket = each.value
}# Format: terraform import <resource_address> <cloud_id>
# AWS examples
terraform import aws_instance.web i-1234567890abcdef0
terraform import aws_s3_bucket.data my-bucket-name
terraform import aws_vpc.main vpc-abc123
terraform import aws_iam_role.lambda my-lambda-role
terraform import aws_security_group.web sg-12345678
# Azure examples
terraform import azurerm_resource_group.main /subscriptions/SUB_ID/resourceGroups/my-rg
terraform import azurerm_virtual_network.main /subscriptions/SUB_ID/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet
# GCP examples
terraform import google_compute_instance.web projects/my-project/zones/us-central1-a/instances/my-vm
terraform import google_storage_bucket.data my-project/my-bucket# Write a minimal config that matches the existing resource
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}terraform import aws_instance.web i-1234567890abcdef0terraform plan
# Review what Terraform wants to change
# Update your config to match the actual resourceKeep adjusting your HCL until terraform plan shows no changes:
# Common drift: tags, security groups, IAM policies
terraform plan
# Adjust config → plan again → repeat until clean| Resource | Import ID Format | Example |
|---|---|---|
aws_instance | Instance ID | i-1234567890abcdef0 |
aws_s3_bucket | Bucket name | my-bucket |
aws_vpc | VPC ID | vpc-abc123 |
aws_subnet | Subnet ID | subnet-abc123 |
aws_security_group | SG ID | sg-12345678 |
aws_iam_role | Role name | my-role |
aws_iam_policy | Policy ARN | arn:aws:iam::123:policy/my-policy |
aws_db_instance | DB identifier | my-database |
aws_route53_record | Zone + name + type | Z1234_example.com_A |
# After import, plan shows changes
# FIX: Update config to match actual resource state
terraform show # See what was imported# Import without config = error
terraform import aws_instance.web i-123
# Error: resource address "aws_instance.web" does not exist in configImporting an EC2 instance doesn't import its security groups, subnets, or IAM role. Import each resource separately.
Passwords, secrets, and some sensitive attributes may not be imported. You'll need to set them manually:
resource "aws_db_instance" "main" {
# After import, set the password manually
password = var.db_password # Import can't read this from AWS
}terraform plan show zero changes after import?generate-config-out to avoid writing config from scratchterraform plan after every import — catch drift immediatelyTerraform import bridges the gap between existing infrastructure and infrastructure as code. Use import blocks (1.5+) with generate-config-out for the easiest workflow, or the CLI for older versions. Always write config first, import, then iterate on plan until you have a clean state with no drift.
Configure Terraform remote state with AWS S3 and DynamoDB locking. Complete setup with encryption, versioning, IAM permissions, and team access patterns.
Import dozens of existing AWS resources into Terraform at once using import blocks, for_each, and generate-config-out.
Use Terraform import blocks to bring existing AWS resources under management. Code-based import without CLI commands, generate config automatically
Install and run Terraform on Ubuntu 26.04 LTS Resolute Raccoon. Covers sudo-rs as default, APT 3.2 rollback, Kernel 7.0, Wayland-only, ROCm, and building...