How to Create an AWS S3 Bucket with Terraform
Creating an S3 bucket in Terraform is the aws_s3_bucket resource. Since AWS provider v4 the extra settings (versioning, encryption) moved to their own resources - here's the working setup and the errors that block apply.
The basic bucket
resource "aws_s3_bucket" "analytics" {
bucket = "my-company-analytics" # globally unique name
}
That's the whole resource. bucket is the (globally unique) name. Run it with:
terraform init
terraform apply -auto-approve
"Unsupported argument" - the v4+ gotcha
Before AWS provider v4 you set versioning, server_side_encryption_configuration, etc.
inside the bucket resource. In v4+ those are separate resources, so old-style
arguments now error:
Error: Unsupported argument
on main.tf: an argument named "versioning" is not expected here.
The fix is to break them out:
resource "aws_s3_bucket_versioning" "analytics" {
bucket = aws_s3_bucket.analytics.id
versioning_configuration { status = "Enabled" }
}
resource "aws_s3_bucket_server_side_encryption_configuration" "analytics" {
bucket = aws_s3_bucket.analytics.id
rule {
apply_server_side_encryption_by_default { sse_algorithm = "AES256" }
}
}
(A plain typo - buckkket = "..." - produces the same "Unsupported argument" error;
read the line number Terraform prints and fix that argument.)
Lock it down (you almost always want these)
resource "aws_s3_bucket_public_access_block" "analytics" {
bucket = aws_s3_bucket.analytics.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
How to debug a failing apply
- Read the error - Terraform names the argument and the line.
terraform validatecatches syntax/arg errors before you hit AWS.terraform planshows exactly what will be created beforeapply.
Common aws_s3_bucket errors
BucketAlreadyExists/BucketAlreadyOwnedByYou- S3 bucket names are globally unique across every AWS account. Pick a name nobody has taken (add a suffix), or usebucket_prefixto let AWS append randomness.Unsupported argument- on provider v4+,versioning,server_side_encryption_configuration,acl, and lifecycle rules moved out ofaws_s3_bucketinto their own resources (aws_s3_bucket_versioning, and so on). Split them out.BucketNotEmptyon destroy - Terraform will not delete a bucket with objects in it. Setforce_destroy = trueif you wantterraform destroyto empty it first.- Invalid name - bucket names must be lowercase, 3-63 characters, DNS-compliant, with no underscores.
Run terraform plan after every change - the AWS provider validates most of these before any API call, so you catch them locally instead of mid-apply.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Writing a valid aws_s3_bucket resource
- Splitting versioning/encryption into their own v4+ resources
- Reading terraform apply errors to fix the argument
FAQ
How do I create an S3 bucket in Terraform?
Use the aws_s3_bucket resource with a globally-unique bucket name, then terraform init and terraform apply. Versioning and encryption are now separate resources (aws_s3_bucket_versioning, aws_s3_bucket_server_side_encryption_configuration).
Why does Terraform say 'Unsupported argument' on aws_s3_bucket?
Since AWS provider v4, settings like versioning and encryption moved out of the bucket resource into their own resources - or it's a plain typo. Read the named argument + line number and either move it to its own resource or fix the typo.
How do I enable versioning on an S3 bucket in Terraform?
Add an aws_s3_bucket_versioning resource pointing at the bucket id, with versioning_configuration { status = "Enabled" }.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →