DEV Community

Joseph Sutton
Joseph Sutton

Posted on • Edited on

A Faster Setup for Remote Terraform States

Ever wonder if there's a quicker way to initialize your infrastructure with Terraform on a remote state? My go-to is the S3 backend, but manually setting that up can take more time versus making a script to do the work for us.

Assuming you already have your AWS credentials setup already, we need to create two files. The first file is our S3 policy to let Terraform view the items, and to get and update our Terraform state.

Our S3 policy, s3_policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-bucket",
      "Principal": {
        "AWS": "ARN"
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/terraform.tfstate",
      "Principal": {
        "AWS": "ARN"
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

So, if you're wondering about the ARN, that's okay. Our script will handle that. You can even go as far as abstracting the Resource out for each Statement item as well!

The second file is our actual bash script, let's say tf-setup.sh (remember to chmod +x this file so you can execute it!):

#!/bin/bash

# Create S3 Bucket
MY_ARN=$(aws iam get-user --query User.Arn --output text 2>/dev/null)
aws s3 mb "s3://tf-remote-bucket" --region "us-east-1"
sed -e "s/RESOURCE/arn:aws:s3:::tf-remote-bucket/g" -e "s/KEY/terraform.tfstate/g" -e "s|ARN|${MY_ARN}|g" "$(dirname "$0")/s3_policy.json" > new-policy.json
aws s3api put-bucket-policy --bucket "tf-remote-bucket" --policy file://new-policy.json
aws s3api put-bucket-versioning --bucket "tf-remote-bucket" --versioning-configuration Status=Enabled
rm new-policy.json

# Create DynamoDB Table
aws dynamodb create-table \
  --table-name "tf-lock-table" \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \
  --region "us-east-1"
Enter fullscreen mode Exit fullscreen mode

Now, let's configure our main.tf:

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.29"
    }
  }

  backend "s3" {
    encrypt        = true
    bucket         = "tf-remote-bucket"
    dynamodb_table = "tf-lock-table"
    region         = "us-east-1"
    key            = "terraform.tfstate"
  }
}

provider "aws" {
  region = "us-east-1"
}
Enter fullscreen mode Exit fullscreen mode

A terraform init outputs:

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Enter fullscreen mode Exit fullscreen mode

You should be all set to run terraform plan and terraform apply! If you have any questions or run into any problems, please let me know in the comments!

Top comments (0)