{"id":27103060,"url":"https://github.com/stuartellis/terraform-aws-backend","last_synced_at":"2026-05-09T04:32:21.315Z","repository":{"id":103210321,"uuid":"453332724","full_name":"stuartellis/terraform-aws-backend","owner":"stuartellis","description":"Tooling to deploy an AWS backend for Terraform, using Ansible and CloudFormation","archived":false,"fork":false,"pushed_at":"2022-02-19T09:30:10.000Z","size":42,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-06T16:43:45.943Z","etag":null,"topics":["ansible","ansible-playbook","aws","cloudformation-templates","terraform","terraform-state"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stuartellis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-29T07:52:56.000Z","updated_at":"2022-02-19T09:12:09.000Z","dependencies_parsed_at":"2023-06-28T23:45:13.768Z","dependency_job_id":null,"html_url":"https://github.com/stuartellis/terraform-aws-backend","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stuartellis/terraform-aws-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartellis%2Fterraform-aws-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartellis%2Fterraform-aws-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartellis%2Fterraform-aws-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartellis%2Fterraform-aws-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stuartellis","download_url":"https://codeload.github.com/stuartellis/terraform-aws-backend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartellis%2Fterraform-aws-backend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32807194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","ansible-playbook","aws","cloudformation-templates","terraform","terraform-state"],"created_at":"2025-04-06T16:38:43.893Z","updated_at":"2026-05-09T04:32:21.309Z","avatar_url":"https://github.com/stuartellis.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform AWS Backend\n\nTooling to deploy an [AWS backend for Terraform state](https://www.terraform.io/language/settings/backends/s3), using [Ansible](https://www.ansible.com/) and CloudFormation.\n\nThis sets up the AWS resources that Terraform needs, in a way that does not depend on Terraform.\n\nThe CloudFormation templates deploy a set of replicated S3 buckets and a DynamoDB table. Each bucket has [object versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html) enabled, so that previous versions of the state files can be restored. All storage is encrypted with KMS customer-managed keys.\n\nTo increase the safety of the Terraform state, the policy on the main S3 bucket prevents objects from being deleted.\n\nAnsible provides a convenient way to deploy sets of CloudFormation templates together. You may use the CloudFormation templates without Ansible.\n\n## Design\n\nThis project deliberately does not follow a standard directory structure for Ansible. By design it completely separates the files for Ansible and CloudFormation.\n\nIt assumes that you have at least two AWS accounts:\n\n- A *managing* AWS account that will contain the Terraform backend\n- One or more *managed* AWS accounts that will contain resources that will be managed by Terraform\n\nYou should always use more than one AWS account in your infrastructure. AWS accounts are free, because you are only charged for the resources that you use.\n\nIf you wish, you can use Terraform to control resources in the managing AWS account. The aim of this tooling is to set up just the AWS resources that Terraform itself needs.\n\nThe deployed resources include an IAM user account. This user account can assume the roles to access the Terraform storage, and execute Terraform on each AWS account. Your automation can then use this account to run Terraform on AWS.\n\nThe *org_prefix* should be a short string that uniquely identifies the current organization. S3 bucket names must be globally unique across all AWS customers, so we must prefix the name of each bucket with a string that is unique to our accounts. The playbooks also use the *org_prefix* to namespace the AWS tags that they apply.\n\n## Setting Up Ansible\n\nAnsible requires Python 3. You may run Ansible on Linux, macOS or WSL.\n\nRun these commands to install Ansible:\n\n    pip3 --user pipx\n    pipx install ansible-core\n    pipx inject ansible-core boto3\n    ansible-galaxy install -r requirements.yml\n\n## Usage\n\n### Requirements\n\nFirst decide an *org_prefix*, a short string that uniquely identifies your organization. This is used to ensure consistent and unique naming.\n\nChoose appropriate regions for your resources. The examples use eu-west-2 as the AWS region for the main bucket, with replica buckets in the eu-west-1 and eu-central-1 regions.\n\nThe examples below take variables from the command-line. You may create YAML or JSON files for the variables instead. This example reads variables from a YAML file called **tf-identities-vars.yml**:\n\n    ansible-playbook --connection=local ./ansible/deploy-tf-identities-playbook.yml --extra-vars \"@tf-identities-vars.yml\"\n\n### Deploy IAM Roles for Running Terraform\n\nRun the playbook **./ansible/deploy-tf-exec-role-playbook.yml** to create the IAM role that Terraform will use to run on each AWS account.\n\nTo run the Ansible playbook for Terraform execution role on an AWS account:\n\n    ansible-playbook --connection=local ./ansible/deploy-tf-exec-role-playbook.yml --extra-vars \"managing_account_id=MANAGING-AWS-ACCOUNT-ID org_prefix=YOUR-ORG-PREFIX stack_prefix=tf-exec\"\n\n### Deploy Terraform Storage to the Managing Account\n\nRun the playbook **deploy-tf-storage-playbook.yml** for Terraform storage.\n\n    ansible-playbook --connection=local ./ansible/deploy-tf-storage-playbook.yml --extra-vars \"org_prefix=YOUR-ORG-PREFIX stack_prefix=tf-state primary_region=eu-west-2 replica_region_001=eu-west-1 replica_region_002=eu-central-1\"\n\nGet the ARNs of the resources that were generated by this playbook.\n\nRun the playbook **deploy-tf-backend-access-playbook.yml** to deploy access to the Terraform backend storage\n\n    ansible-playbook --connection=local ./ansible/deploy-tf-backend-access-playbook.yml --extra-vars \"org_prefix=YOUR-ORG-PREFIX stack_prefix=tf-access-svc managing_account_id=MANAGING-AWS-ACCOUNT-ID kms_key_arn=PRIMARY_KMS_KEY_ARN s3_bucket_arn=arn:aws:s3:::YOUR-ORG-PREFIX-tf-state-primary-MANAGING-AWS-ACCOUNT-ID-eu-west-2 ddb_table_arn=arn:aws:dynamodb:eu-west-2:MANAGING-AWS-ACCOUNT-ID:table/YOUR-ORG-PREFIX-tf-state-lock-eu-west-2\"\n\n### Deploy IAM Identities for Accessing Terraform to the Managing Account\n\nRun the playbook **deploy-tf-identities-playbook.yml** to deploy IAM users and groups.\n\n    ansible-playbook --connection=local ./ansible/deploy-tf-identities-playbook.yml --extra-vars \"org_prefix=YOUR-ORG-PREFIX stack_prefix=tf-access managing_account_id=MANAGING-AWS-ACCOUNT-ID iam_role_arns=arn:aws:iam::MANAGING-AWS-ACCOUNT-ID:role/YOUR-ORG-PREFIX-tf-backend-access-role,arn:aws:iam::MANAGING-AWS-ACCOUNT-ID:role/YOUR-ORG-PREFIX-tf-exec-role,arn:aws:iam::FIRST-MANAGED-AWS-ACCOUNT-ID:role/YOUR-ORG-PREFIX-tf-exec-role,arn:aws:iam::SECOND-MANAGED-AWS-ACCOUNT-ID:role/YOUR-ORG-PREFIX-tf-exec-role\"\n\nOnce this playbook has completed, you will have a new IAM user account. This account can assume the roles to access the Terraform storage, and execute Terraform on each AWS account.\n\nCreate an AWS access key for the user, and configure your CI system to use it. Your CI system can then deploy to the AWS accounts with Terraform.\n\n## Resources\n\n- [Terraform documentation for state storage with AWS](https://www.terraform.io/language/settings/backends/s3)\n- [Terragrunt requirements for AWS](https://terragrunt.gruntwork.io/docs/features/aws-auth/)\n- [CloudFormation for a Terraform backend, by Tibor Hercz](https://github.com/tiborhercz/tf-state-backend-s3-cloudformation) - An existing implementation, using just CloudFormation\n- [Managing Terraform Remote State with CloudFormation, by Chris Kent](https://thirstydeveloper.io/tf-skeleton/2021/02/25/part-6-protecting-state.html) - Part of a series on setting up Terraform\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartellis%2Fterraform-aws-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstuartellis%2Fterraform-aws-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartellis%2Fterraform-aws-backend/lists"}