{"id":51507960,"url":"https://github.com/explicit-logic/terraform-module-12.4","last_synced_at":"2026-07-08T02:30:43.705Z","repository":{"id":353655398,"uuid":"1220152169","full_name":"explicit-logic/terraform-module-12.4","owner":"explicit-logic","description":"Configure a Shared Remote State","archived":false,"fork":false,"pushed_at":"2026-04-24T22:00:49.000Z","size":3748,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T22:31:49.317Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/explicit-logic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T15:46:02.000Z","updated_at":"2026-04-24T22:00:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/explicit-logic/terraform-module-12.4","commit_stats":null,"previous_names":["explicit-logic/terraform-module-12.4"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/explicit-logic/terraform-module-12.4","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/explicit-logic%2Fterraform-module-12.4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/explicit-logic%2Fterraform-module-12.4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/explicit-logic%2Fterraform-module-12.4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/explicit-logic%2Fterraform-module-12.4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/explicit-logic","download_url":"https://codeload.github.com/explicit-logic/terraform-module-12.4/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/explicit-logic%2Fterraform-module-12.4/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35249883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"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":[],"created_at":"2026-07-08T02:30:43.041Z","updated_at":"2026-07-08T02:30:43.696Z","avatar_url":"https://github.com/explicit-logic.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Module 12 - Infrastructure as Code with Terraform\n\nThis repository contains a demo project created as part of my **DevOps studies** in the [TechWorld with Nana – DevOps Bootcamp](https://www.techworld-with-nana.com/devops-bootcamp).\n\n**Demo Project:** Configure a Shared Remote State\n\n**Technologies used:** Terraform, AWS S3\n\n**Project Description:**\n\n- Configure Amazon S3 as remote storage for Terraform state\n\n---\n\n## Prerequisites\n\nBefore starting, make sure the following setup module is complete:\n\n- **CI/CD with Terraform:** [terraform-module-12.5](https://github.com/explicit-logic/terraform-module-12.5)\n\nYou will also need:\n\n- An **AWS account** with permissions to create and manage S3 buckets\n- A running **Jenkins** instance from the prerequisite module\n- **Terraform** `\u003e= 0.12` installed locally (for verifying state)\n\n---\n\n## Overview\n\nBy default, Terraform stores state locally in a `terraform.tfstate` file. This works for a single user, but breaks down quickly in a team or CI/CD setting because state cannot be shared safely and concurrent runs can corrupt it.\n\nThis project moves Terraform state into an **AWS S3 backend** so that:\n\n- State is stored centrally and shared across the team and the CI/CD pipeline\n- Versioning protects against accidental state loss\n- Server-side encryption keeps sensitive values at rest secure\n- Native S3 locking (`use_lockfile`) prevents concurrent `apply` operations from clobbering each other\n\n![](./images/intro.png)\n\n---\n\n## 1. Create the AWS S3 Bucket\n\nThis bucket will hold the remote Terraform state file.\n\n1. Open the AWS console and navigate to **Amazon S3 → Buckets → Create bucket**.\n2. Configure the following options:\n\n   | Setting              | Value                                                            |\n   | -------------------- | ---------------------------------------------------------------- |\n   | **Name**             | `myapp-tf`                                                       |\n   | **Bucket namespace** | `Account Regional namespace`                                     |\n   | **Versioning**       | `Enable`                                                         |\n   | **Encryption type**  | `Server-side encryption with Amazon S3 managed keys (SSE-S3)`    |\n   | **Bucket Key**       | `Disable`                                                        |\n\n\u003e **Why versioning?** With versioning enabled, every change to the state file produces a new version, so a corrupted or accidentally deleted state can always be rolled back.\n\n![](./images/create-bucket-1.png)\n\n![](./images/create-bucket-2.png)\n\n![](./images/create-bucket-3.png)\n\n3. Click **Create bucket**.\n\n---\n\n## 2. Configure the Remote Backend\n\nOnce the bucket exists, copy its **full name** from the S3 console (for example: `myapp-tf-629604312222-eu-central-1-an`).\n\n![](./images/bucket-name.png)\n\nAdd the `backend \"s3\"` block to [terraform/main.tf](./terraform/main.tf):\n\n```hcl\nterraform {\n  required_version = \"\u003e= 0.12\"\n\n  backend \"s3\" {\n    bucket       = \"full-bucket-name\"\n    key          = \"myapp/state.tfstate\"\n    region       = \"eu-central-1\"\n    encrypt      = true\n    use_lockfile = true\n  }\n}\n```\n\n| Field          | Purpose                                                                           |\n| -------------- | --------------------------------------------------------------------------------- |\n| `bucket`       | The S3 bucket created in step 1 (replace `full-bucket-name` with your value).     |\n| `key`          | Object path inside the bucket where the state file is stored.                     |\n| `region`       | AWS region of the bucket — must match the bucket's region.                        |\n| `encrypt`      | Forces server-side encryption when uploading state.                               |\n| `use_lockfile` | Enables S3-native state locking, removing the need for a separate DynamoDB table. |\n\n---\n\n## 3. Launch the Pipeline\n\nThe Jenkins pipeline runs `terraform init/apply` against the new remote backend. It needs your public IP to whitelist SSH access to the provisioned EC2 instance.\n\n### 3.1 Get your public IP\n\n```sh\ncurl https://ipinfo.io/ip\n```\n\n### 3.2 Add the IP as a Jenkins credential\n\n1. Go to **`java-maven-app` → Credentials → Global → Add Credentials**.\n2. Choose **Secret text** and use the following values:\n\n   - **ID:** `MY_IP`\n   - **Secret:** `\u003cyour public IP\u003e`\n\nThe final list of pipeline credentials should look like this:\n\n![](./images/jenkins-creds.png)\n\n### 3.3 Run the pipeline\n\nTrigger the Jenkins job and watch the stages execute end-to-end:\n\n![](./images/pipeline.gif)\n\n---\n\n## 4. Verify the Remote State\n\nAfter the pipeline finishes, a `tfstate` file should appear inside the S3 bucket:\n\n![](./images/tfstate.png)\n\nTo confirm that your local Terraform CLI can read the same remote state, run from the [terraform/](./terraform) directory:\n\n```sh\nterraform init\nterraform state list\n```\n\n`terraform init` detects the new `backend \"s3\"` block and pulls the state from S3. `terraform state list` then prints every resource currently tracked — proving the local CLI and the Jenkins pipeline are now operating on the same shared state.\n\n![](./images/terraform-state.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexplicit-logic%2Fterraform-module-12.4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexplicit-logic%2Fterraform-module-12.4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexplicit-logic%2Fterraform-module-12.4/lists"}