-
We get the following question from customers fairly often, so I'll post the question here, and then add an answer below: How should I create the backend (e.g., S3 bucket) for storing Terraform state? |
Beta Was this translation helpful? Give feedback.
Replies: 11 comments 2 replies
-
There are several different ways to handle this, each with various pros and cons: Option 1: create the backend manually (ClickOps)OverviewOne option is to create your backend manually. For example, if you're using S3 as a backend, you'd login to the AWS Console, and click around for a while to create an S3 bucket and DynamoDB table. Pros
Cons
Option 2: create the backend using TerraformOverviewAnother option is to write a Terraform module to set up your backend. For example, if you're a Gruntwork customer, you can use the s3-bucket module to create a secure, best-practices S3 bucket. As for the DynamoDB table, it's a single resource (example). The chicken & egg problemOne catch here is that you have a bit of a chicken & egg problem: you want to store all your Terraform state in a backend, but here, the Terraform code you're deploying is what creates the backend, which doesn't exist initially, so you can't store state in it. Working around this is pretty simple, but does involve some manual steps:
Note that you have to do these steps before you can run Pros
Cons
Option 3: let Terragrunt create your backendOverviewFor a few popular backend types (S3 and GCS), if you're using the remote_state block, Terragrunt can automatically create the backend for you. That is, when you run Pros
Cons
Option 4: use a SaaS managed backendOverviewSome SaaS tools for Terraform, such as Terraform Cloud and Terraform Enterprise, manage backend for you "magically." That is, you don't have to think about the backend at all: the SaaS tool just does it automatically, transparently, behind the scenes. Pros
Cons
|
Beta Was this translation helpful? Give feedback.
-
I've always used Option 2, I like to control the bucket creation, for it I already have a module that setup everything that I need. For me, the states are the most important part of the Terraform. |
Beta Was this translation helpful? Give feedback.
-
I use Option 1 in simple cases, and Option 2 in all other cases, BUT I understand that Option 2 is the most correct in all cases. |
Beta Was this translation helpful? Give feedback.
-
For options 1 & 3, I'd enhance them by adding a terraform config that matches the backend, with import blocks to bring the pre-created resources into tfstate. I think it's particularly powerful in combination with option 3... no more chicken-egg problem! |
Beta Was this translation helpful? Give feedback.
-
Another option, which would be an extension of the option 1 is to create the bucket via cloud native tool, e.g. AWS CloudFormation/CDK |
Beta Was this translation helpful? Give feedback.
-
I detailed my way of setting up the backend through Terragrunt and Terraform using option 2 in this blog post while learning how to use Terragrunt. This contains the initial set of steps. This way you get to set the state bucket parameters with Terraform. |
Beta Was this translation helpful? Give feedback.
-
For some past projects, mostly done with the bare Terraform, I've preferred to use AWS Cloudformation for the initial S3 bucket and DynamoDB lock table creation. It allowed me to keep the IaC approach without having headaches about local state management. For newer AWS projects where I have to use Terragrunt wherever possible, I prefer to let Terragrunt manage S3 state bucket creation. But I still have a dedicated Terraform module that sets the correct access permissions to the state bucket as a part of my general Terragrunt live infrastructure. So, I vote for Option 3. |
Beta Was this translation helpful? Give feedback.
-
Can you show us an example how you do option 3 for AWS? Unfortunately I get an error:
This is my terragrunt.hcl file
terragrunt version v0.52.7 |
Beta Was this translation helpful? Give feedback.
-
What about if I want to deploy with github workflow and terraform with backend in S3 ? then once all the pipeline is finish delete the bucket ? |
Beta Was this translation helpful? Give feedback.
-
I'm struggling with this too. Coming from Azure you would specify it in your Terraform init and it automaticaly creates the resource group with a storage for the tf state. Found it weird that its not the same for AWS |
Beta Was this translation helpful? Give feedback.
-
I manage by creating a bucket thanks to s3cmd github actions: jobs:
backend:
name: Backend
runs-on: ubuntu-latest
steps:
- name: Set up S3cmd cli tool
uses: s3-actions/s3cmd@main
with:
provider: digitalocean
region: FRA1
access_key: ${{secrets.DIGITALOCEAN_SPACES_ACCESS_TOKEN}}
secret_key: ${{secrets.DIGITALOCEAN_SPACES_SECRET_KEY}}
- name: Create Space Bucket
run: |
sed -i -e 's/signature_v2.*$/signature_v2 = True/' ~/.s3cfg
buck="github-action-${{ github.run_id }}"
s3cmd mb s3://$buck
sleep 10
continue-on-error: true You can also do it manually: # install
sudo pip install s3cmd
# config
s3cmd --configure
# Create if does not already exist
s3cmd info s3://terraform-backend-test || s3cmd mb s3://terraform-backend-test -v -d then use this bucket in terraform: terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
backend "s3" {
skip_region_validation = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
use_path_style = true
skip_s3_checksum = true
endpoints = {
s3 = "https://fra1.digitaloceanspaces.com"
}
region = "fra1"
// bucket = "terraform-backend-github"
key = "terraform.tfstate"
}
} |
Beta Was this translation helpful? Give feedback.
There are several different ways to handle this, each with various pros and cons:
Option 1: create the backend manually (ClickOps)
Overview
One option is to create your backend manually. For example, if you're using S3 as a backend, you'd login to the AWS Console, and click around for a while to create an S3 bucket and DynamoDB table.
Pros
Cons