How to Create an S3 Bucket using Terraform

How to Create an S3 Bucket using Terraform

How to Create an S3 Bucket using Terraform with Example

AWS S3 or Simple Storage Service is one of the most used AWS services. When you are deploying your workload on AWS, there is a high chance that you are using S3 buckets directly or indirectly.

From a DevOps perspective, It always makes sense to automate your infrastructure as much as we can. In this post, I will show you how you can create an s3 bucket using one of the most popular IaC tools Terraform.

Related: How to Create S3 Bucket Policy using Terraform

Don’t want to miss any posts from us? join us on our Facebook group, and follow us on Facebook, Twitter, LinkedIn, and Instagram. You can also subscribe to our newsletter below to not miss any updates from us.

What is Terraform?

Terraform is an open-source Infrastructure as Code(IaC) tool by HashiCorp. It lets you provision your infrastructure as code.

  • It lets you provision, update and version your infrastructure in an efficient manner
  • You declare your required infrastructure in a configuration file and Terraform creates it in the correct order.
  • Configuration files are in a human-readable format using HashiCorp Configuration Language(HCL) or even JSON is supported.
  • Terraform is Cloud Agnostic and supports numerous cloud providers like AWS, Azure, GCP etc.

How Do You Create a Resource Using Terraform on AWS?

Unlike CloudFormation, you need to install Terraform in your system before you can use it to create a resource like an S3 bucket on your cloud provider(In our case AWS).

Once installed, you create your configuration file(filename.tf – they have .tf extension), and use the below set of commands to deploy your resources.

$ terraform init
$ terraform plan
$ terraform apply
$ terraform destroy

I highly recommended you check my step-by-step guide to help you get started with Terraform on AWS in the right way. Here is the link-

Once you go through that post you will already have idea on-

  • Installing Terraform
  • Creating a Terraform IAM user
  • Setting up AWS CLI to allow Terraform to authenticate to AWS
  • Setting up your workspace using Visual Studio Code(VS Code) IDE
  • Deploying Your First Resource on AWS using Terraform

By this time, I assume you already know how to deploy a resource on AWS using Terraform.

Alright, lets get started with S3 Bucket Creation.

Prerequisite:

Create a Simple S3 Bucket using Terraform

In this article, we’ll create a very simple bucket using Terraform. Later in this tutorial, we will update our bucket to enable some of the frequently used features like versioning, encryption etc.

Before we start, let me tell you that, to create an s3 bucket using Terraform, you will need an aws_s3_bucket resource. Feel free to refer official documentation for up-to-date properties.

Here is what a simple s3 bucket resource looks like-

resource "aws_s3_bucket" "resource_name"{
  bucket = "bucket_name"

  tags = {
    Name = "Bucket_Tag"
  }
}

Now later when you want to access a property of this resource like bucket name, you can do it like-

aws_s3_bucket.demo-bucket.bucket

Steps to Create an S3 Bucket using Terraform

  1. Create a Working Directory/Folder
  2. Create your Bucket Configuration File
  3. Initialize Your Directory to Download AWS Plugins
  4. Plan and Deploy

Step 1: Create a Working Directory/Folder

Create a folder in which you will keep your s3 bucket terraform configuration file.

Step 2: Create your Bucket Configuration File

Navigate inside the bucket and create your bucket configuration file. You can name it as per your wish, but to keep things simple, I will name it main.tf

I have started with just provider declaration and one simple resource to create a bucket as shown below-

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

#Provider profile and region in which all the resources will create
provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}

#Resource to create s3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket"

  tags = {
    Name = "S3Bucket"
  }
}

Copy this content and save it into a file with .tf extension. You can name it main.tf conventionally as well.

Step 3: Initialize Your Directory to Download AWS Plugins

You only do this step once per folder/directory. This basically means you are downloading relevant codes/plugins for your mentioned provider which in our case is aws.

terraform init
how to create s3 bucket using terraform

Step 4: Plan and Deploy

The configuration file is created and the directory is initialized. That means we are all ready to deploy our s3 bucket.

Now, if you want you can run the command terraform plan to see what’s actually being created.

terraform plan

However, to keep things simple, I just run terraform apply. Ideally, terraform runs terraform plan every time you hit the command terraform apply. Once you review the plan and confirm yes then only resources will be created.

Terraform will look for .tf file and show you what’s being created.

Review the output and if all is fine say yes to the bucket.

How to create s3 bucket using terraform action yes

Once you confirm, terraform starts creating your bucket.

If all is well your bucket is created. However, one of the common mistakes while creating an s3 bucket is choosing a name.

If the name you provided is not unique, you will get an error like below-

bucket creation error

It says-

Error creating S3 bucket: BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.

The reason is s3 bucket names are unique globally across AWS accounts. That means once someone has created a bucket “test”. Nobody else can create a bucket with the same name in any account.

Read More about this-

In case of successful creation, you will see a message like below-

That means your bucket is created and you can verify your s3 bucket in s3 console.

It was as simple as that. We are done with the creation of a simple s3 bucket 🙂

Happy now? 😛 😛

Let’s be happier by implementing some of the advanced things.

Enable Versioning on an S3 Bucket using Terraform

Enabling versioning enables multiple versions of all the objects in the bucket. You should consider enabling versioning-

  • To prevent an object from being deleted or overwritten by mistake.
  • To archive all versions so that you can retrieve any version you want at any time

In the latest versions of Terraform, you can use a resource of type aws_s3_bucket_versioning to enable versioning on your bucket.

If we modify our existing code, this is how the section will look like-

#Resource to create an S3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket-18th"

  tags = {
    Name = "S3Bucket"
  }


#A resource to enable versioning on bucket
resource "aws_s3_bucket_versioning" "versioning_demo" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  versioning_configuration {
    status = "Enabled"
  }
}

Explanation:

  • aws_s3_bucket_versioning resource needs a bucket name in the parameter bucket to enable versioning on that bucket
  • versioning_configuration status can be Enabled or Disabled to enable or disable versioning

Once the configuration file is updated, run terraform apply and versioning will be enabled on the bucket.

If you go to the S3 console and check your bucket properties. You can see that versioning is enabled on the bucket now.

Versioning is enabled on your bucket?

I guess yes !!!

That’s good progress !!! 🙂

Important Notes: To enable versioning on an S3 bucket, we have used a separate aws_s3_bucket_versioning resource. However, please note that you can still use versioning parameter on the resource aws_s3_bucket but it’s already deprecated. So it’s recommended to use separate resources as shown here. But, don’t use both at a time as it might result in consistency.

Let’s add another feature in our cap by enabling encryption.

Enable Encryption on S3 Bucket using Terraform

Enabling default encryption on a bucket will set the default encryption behaviour on a bucket. once set, all new objects are encrypted when you store them in the bucket.

In other terms, S3 encrypts an object before saving it to disk and decrypts it when you download the objects.

Well, there are two options of key when using server side encryption.

  • S3-managed keys (SSE-S3)
  • Customer master keys (CMKs) stored in AWS KMS.

In the latest terraform, similar to versioning, encryption also can be managed via a separate resource aws_s3_bucket_server_side_encryption_configuration like shown below-

resource "aws_s3_bucket_server_side_encryption_configuration" "demo-encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Important Note: Similar to versioning, to enable encryption on an S3 bucket, we have used a separate resource aws_s3_bucket_server_side_encryption_configuration. However, you can still use server_side_encryption_configuration in the aws_s3_bucket resource to enable encryption but it’s deprecated. So better to use this new way. But mind it, don’t use both together. It will cause inconsistencies.

Once you have updated your file with this configuration, run terraform apply again and you will see default encryption is enabled now.

By now we have enabled versioning and encryption. You can check your bucket property(In properties tab) to validate that as mentioned in the screenshot. Versioning and encryption are ticked here 🙂

Create an S3 Bucket using CloudFormation

Please note that we used s3 managed key here, however, if you need to have KMS managed key, you can have the below set of parameters. You will need to create a key in KMS first and then you need to provide the ARN as mentioned below.

resource "aws_kms_key" "demokey" {
  description             = "key to encrypt bucket objects"
  deletion_window_in_days = 7
}

resource "aws_s3_bucket_server_side_encryption_configuration" "demo_encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.demokey.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

Lastly, let’s try to configure our bucket in a way which will prevent any public access to our objects.

Prevent objects from becoming public using terraform

If you will notice the created s3 bucket access, you will see something like “Objects can be public”. What does that mean?

Well, it means that although by default the bucket is not public but can be public. Anyone with the proper permissions can make objects public.

Let’s make the bucket completely private.

We will use the property AccessControl(Canned ACL) as well as PublicAccessBlockConfiguration as mentioned in the template below.

resource "aws_s3_bucket_acl" "demo_bucket_acl" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  acl    = "private"
}
resource "aws_s3_bucket_public_access_block" "demo_public_block" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  block_public_acls   = true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}

Add these properties in the template, save it and run terraform apply again. After the successful update you will see, now your bucket access is not public.

Final Configuration File Example to Create S3 Bucket using Terraform

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}


#Resource to create s3 bucket
resource "aws_s3_bucket" "demo-bucket"{
  bucket = "ck-demo-bucket-18th"

  tags = {
    Name = "S3Bucket"
  }
}

#Resource to enable versioning 
resource "aws_s3_bucket_versioning" "versioning_demo" {
  bucket = aws_s3_bucket.demo-bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

#Resource to enable encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "demo-encryption" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

#Adds an ACL to bucket
resource "aws_s3_bucket_acl" "demo_bucket_acl" {
  bucket = aws_s3_bucket.demo-bucket.bucket
  acl    = "private"
}

#Block Public Access
resource "aws_s3_bucket_public_access_block" "demo_public_block" {
  bucket = aws_s3_bucket.demo-bucket.bucket

  block_public_acls   = true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}

Clean Up

Finally, if you are doing this exercise for learning purposes, you can clean up by destroying the created resource or bucket.

terraform destroy

Conclusion

In this article, we learnt how to create an S3 bucket using Terraform. We created the basic bucket and then updated our configuration file gradually to enable some of the features like

  • Versioning
  • Encryption
  • Preventing public access to the bucket

I know there are many other things like Cors configuration and others that we can do in a bucket.

But I wanted to keep it simple and limited to the most common requirements. You can ask me in the comment if you want me to cover other features as well.

I hope you were able to work up with me and able to create the s3 bucket. If you get stuck at any time feel free to add a comment. I will reply to your query asap.

Well, That was my take on “How to Create an S3 Bucket using Terraform“. Please feel free to share your feedback.

Enjoyed the content?

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

If you liked reading my post, you can motivate me by-

  • Adding a comment below on what you liked and what can be improved.
  • Follow us on
  • Subscribe to our newsletter to get notified each time we post new content.
  • Share this post with your friends and colleagues.

Suggested Read:

3 thoughts on “How to Create an S3 Bucket using Terraform

  1. This was a really helpful article on getting started with Terraform. I really appreciate it and spent a lot of time absorbing it. The “Final Configuration File” was extremely helpful and really got me started down the Terraform path.

  2. Hello, what a wonderful article. Absolutely hats off.

    By chance can you or have information on how I can include s3 server access logging?

Leave a Reply

Your email address will not be published. Required fields are marked *