Skip to main content

Prerequisites

Before you begin, ensure you have:
  • Terraform >= 1.5.7 installed
  • AWS CLI configured with appropriate credentials
  • An AWS account with permissions to create S3 buckets and IAM policies

Create your first bucket

1

Create your Terraform configuration

Create a new directory and a main.tf file with the following content:
main.tf
terraform {
  required_version = ">= 1.5.7"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 6.37"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

module "s3_bucket" {
  source  = "terraform-aws-modules/s3-bucket/aws"
  version = "~> 4.0"

  bucket = "my-s3-bucket-unique-name"
  acl    = "private"

  control_object_ownership = true
  object_ownership         = "ObjectWriter"

  versioning = {
    enabled = true
  }

  tags = {
    Environment = "dev"
    Terraform   = "true"
  }
}

output "bucket_id" {
  value = module.s3_bucket.s3_bucket_id
}

output "bucket_arn" {
  value = module.s3_bucket.s3_bucket_arn
}
2

Initialize Terraform

Download the module and provider:
terraform init
You should see output confirming the module was downloaded from the Terraform Registry.
3

Preview the plan

Review what Terraform will create:
terraform plan
Terraform will show you a plan to create an S3 bucket with versioning enabled and public access blocked by default.
4

Apply the configuration

Create the bucket:
terraform apply
Type yes when prompted. Terraform will create the bucket and output the bucket ID and ARN.
5

Verify the bucket

Confirm the bucket exists using the AWS CLI:
aws s3 ls s3://my-s3-bucket-unique-name
Or check the Terraform outputs:
terraform output bucket_id
terraform output bucket_arn

Common configurations

Private bucket with versioning

The simplest production-ready configuration:
module "s3_bucket" {
  source = "terraform-aws-modules/s3-bucket/aws"

  bucket = "my-s3-bucket"
  acl    = "private"

  control_object_ownership = true
  object_ownership         = "ObjectWriter"

  versioning = {
    enabled = true
  }
}

Bucket for ELB access logs

Configure a bucket to receive Classic Load Balancer access logs:
module "s3_bucket_for_logs" {
  source = "terraform-aws-modules/s3-bucket/aws"

  bucket = "my-s3-bucket-for-logs"
  acl    = "log-delivery-write"

  # Allow deletion of non-empty bucket
  force_destroy = true

  control_object_ownership = true
  object_ownership         = "ObjectWriter"

  attach_elb_log_delivery_policy = true
}

Bucket for ALB/NLB access logs

Configure a bucket to receive Application or Network Load Balancer logs:
module "s3_bucket_for_logs" {
  source = "terraform-aws-modules/s3-bucket/aws"

  bucket = "my-s3-bucket-for-logs"

  # Allow deletion of non-empty bucket
  force_destroy = true

  control_object_ownership = true
  object_ownership         = "ObjectWriter"

  attach_elb_log_delivery_policy = true  # Required for ALB logs
  attach_lb_log_delivery_policy  = true  # Required for ALB/NLB logs
}

Bucket for WAF logs

Configure a bucket to receive AWS WAF logs:
module "s3_bucket_for_waf_logs" {
  source = "terraform-aws-modules/s3-bucket/aws"

  bucket = "my-s3-bucket-for-waf-logs"

  # Allow deletion of non-empty bucket
  force_destroy = true

  control_object_ownership = true
  object_ownership         = "ObjectWriter"

  attach_waf_log_delivery_policy = true
}

Available outputs

After terraform apply, the following outputs are available:
OutputDescription
s3_bucket_idThe bucket name
s3_bucket_arnThe bucket ARN
s3_bucket_bucket_domain_namebucketname.s3.amazonaws.com
s3_bucket_bucket_regional_domain_nameRegion-specific bucket domain name
s3_bucket_hosted_zone_idRoute 53 Hosted Zone ID for the bucket’s region
s3_bucket_regionThe AWS region of the bucket
s3_bucket_website_endpointWebsite endpoint (if website hosting is configured)
s3_bucket_website_domainWebsite domain (for Route 53 alias records)
aws_s3_bucket_versioning_statusVersioning status: Enabled, Suspended, or Disabled

Next steps

All input variables

Browse every configuration option with types and defaults.

Encryption guide

Configure SSE-S3 or SSE-KMS server-side encryption.

Security policies

Enforce TLS, block public access, and control encryption.

Full examples

Complete working configurations for every use case.

Build docs developers (and LLMs) love