Skip to main content
Moving from Terraform to ubx doesn’t require a big-bang rewrite or a maintenance window. The migration path is incremental: convert one module at a time, import the existing resources into Pulumi state so nothing gets recreated, and keep the rest of Terraform running until you’re ready to cut over entirely. ubx convert --from terraform handles the mechanical conversion — it reads your .tf files and generates equivalent .iac source. The converter handles the obvious cases automatically: variableinput, outputoutput, resourceunit. The cases that require manual attention — Terraform resource type names that differ from Pulumi’s, versioning sub-resources that become sub-blocks, multi-resource patterns that collapse to a single block — are flagged in the MIGRATION.md the converter produces alongside the converted files.

What you’ll learn

  • How ubx convert --from terraform converts .tf files to .iac
  • The common manual fixups required after conversion
  • How to import existing Terraform-managed resources into Pulumi state

Why this matters

You don’t need to migrate everything at once. Convert one module, import its resources, verify it validates and plans correctly, then move on to the next. The rest of your Terraform configuration keeps running unchanged during the migration — ubx and Terraform can coexist in the same account, managing separate resources.

The source code

// Post-migration .iac — result of ubx convert + manual fixups.
// See terraform-before/main.tf for the original Terraform source.

unit "aws_s3_bucket_v2" "assets" {
  bucket     = input.bucket_name
  tags       = { Environment = input.env, ManagedBy = "ubx" }
  versioning = { enabled = true }   // collapsed from separate aws_s3_bucket_versioning resource
}

unit "aws_rds_instance" "db" {
  engine                  = "postgres"
  instance_class          = "db.t3.micro"
  identifier              = "${input.env}-db"
  username                = "admin"
  password                = "changeme"
  storage_encrypted       = true
  backup_retention_period = 7
}

How it works

1

Run ubx convert to generate .iac files

ubx convert --from terraform ./terraform-before/ --out ./ reads all .tf files in the source directory and generates .iac equivalents. The converter handles variableinput, outputoutput, resourceunit, and basic expression translation (var.xinput.x, resource.type.name.attrunit.type.name.attr).
2

Apply manual fixups from MIGRATION.md

The converter produces a MIGRATION.md alongside the .iac files listing cases it couldn’t handle automatically. Common fixups: aws_s3_bucketaws_s3_bucket_v2 (Pulumi naming differs from Terraform), separate aws_s3_bucket_versioning resource → versioning sub-block inside the bucket, aws_db_instanceaws_rds_instance.
3

Import existing resources into Pulumi state

Add import "aws_s3_bucket_v2" "assets" { id = "myapp-assets" } blocks for each resource that already exists in AWS. The first ubx apply adopts them into Pulumi state without recreating them. Remove the import blocks after the first successful apply.

Common conversion patterns

Terraformubx .iacNotes
variable "x" {}input "x" {}Direct mapping
output "x" {}output "x" {}Direct mapping
resource "aws_s3_bucket" "x" {}unit "aws_s3_bucket_v2" "x" {}Provider naming differs
var.xinput.xReference syntax
resource.type.name.attrunit.type.name.attrPending ref syntax
aws_s3_bucket_versioning resourceversioning {} sub-blockSub-resource → sub-block
aws_db_instanceaws_rds_instancePulumi vs Terraform naming

Common mistakes

Terraform resource type names often differ from Pulumi’s. aws_s3_bucket in Terraform is aws_s3_bucket_v2 in Pulumi. aws_db_instance is aws_rds_instance. Always check ubx docs <type> after conversion to verify the correct Pulumi resource type name before importing.
Keep your Terraform state file accessible during migration. Use from = "terraform://s3/..." on input blocks (tutorial 17) to consume Terraform outputs in your new ubx stacks while the rest of the infrastructure is still Terraform-managed. This allows gradual migration without a forced cutover.

Run it

# Convert
ubx convert --from terraform ./terraform-before/ --out ./

# Review MIGRATION.md and apply manual fixups

# Validate
ubx validate

# Add import blocks for existing resources, then apply
ubx apply    # requires AWS credentials; imports existing resources
# Remove import blocks after successful apply

What you learned

ubx convert --from terraform converts .tf files to .iac automatically
MIGRATION.md lists fixups that require manual attention after conversion
import blocks adopt existing resources into Pulumi state without recreating them

Next steps

Migrate from Pulumi

Convert existing Pulumi TypeScript programs to .iac

Input from Terraform state

Consume Terraform outputs during incremental migration