Let’s say you have a Template file (.yaml) that provisions resources to support Terraform Remote state backed by S3 and DynamoDB for consistency locking as below
AWSTemplateFormatVersion: "2010-09-09"
Description: Description is here
...
Parameters, Metadata, REsources are defined here
...
TerraformRemoteStateS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref TerraformRemoteStateS3BucketName
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: 'aws:kms'
KMSMasterKeyID: !Ref TerraformRemoteStateKMSKey
VersioningConfiguration:
Status: Enabled
Tags:
-
Key: Name
Value: terrraform-remote-state-s3-bucket
TerraformRemoteStateLockDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Ref TerraformRemoteStateTableName
AttributeDefinitions:
-
AttributeName: LockID
AttributeType: S
KeySchema:
-
AttributeName: LockID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
SSESpecification:
SSEEnabled: true
Tags:
-
Key: Name
Value: terrraform-remote-state-lock-table
You can create AWS S3 bucket and DynamoDB table using Designer Template in AWS CloudFormation. Go to AWS Cloud Formation page and click Design template.

Copy and paste the content of the yaml file to the template section and create stack.

After stack creation is done, go to the Resources section to check the status. The Physical Id section is the name of the resources that we are going to specify in the terraform commands section.

Check DynamoDB table
Assuming that you are in eu-west-2 zone, go to your AWS account and search the table. Table details looks like that.

Check S3 bucket
You can check the bucket in your AWS zone.

Terraform commands
terraform init
The terraform init
command is used to initialize a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control. It is safe to run this command multiple times.
We will use the config file, config.tfvars, to run terraform init command.
encrypt = true
bucket = "my-terraform-remote-state"
key = "state/state.tfstate"
dynamodb_table = "my-terraform-remote-state-lock-table"
region = "eu-west-2"
access_key = "your_access_key"
secret_key = "your_secret_key"
kms_key_id = "your_kms_id" --> Go to Resources and copy the Physical ID of AWS::KMS::KEY in your stack
If you don’t specify kms_key_id correctly, you will get following error:
Initializing the backend… Error loading state: failed to upload state: KMS.KMSInvalidStateException: arn:aws:kms:eu-west-2:XXXXXXXX:key/unique_number is pending deletion. status code: 400, request id: F52E6A6E33081A8E, host id: caUBtZC/yasdaddfgsafgasgsg=45674e67ehdgdsgh=
Initialize terraform using config.tfvars
tterraform init -backend-config=C:\DWP\homecare-terraform-aws\config.tfvars
You might have following error if terraform cannot create state/state.tfstate file in S3 bucket.
Terraform acquires a state lock to protect the state from being written by multiple users at the same time. Please resolve the issue above and try again. For most commands, you can disable locking with the "-lock=false" flag, but this is not recommended.
Using -reconfigure option helped me to get rid of the error
terraform init -input=false -reconfigure -backend-config=C:\DWP\homecare-terraform-aws\config.tfvars
terraform plan
The terraform plan
command is used to create an execution plan. Terraform performs a refresh, unless explicitly disabled, and then determines what actions are necessary to achieve the desired state specified in the configuration files. The result of the commond is as follows

terraform apply
The terraform apply
command is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a terraform plan
execution plan.