This repository contains a demo project created as part of my DevOps studies in the TechWorld with Nana – DevOps Bootcamp.
Demo Project: Configure a Shared Remote State
Technologies used: Terraform, AWS S3
Project Description:
- Configure Amazon S3 as remote storage for Terraform state
Before starting, make sure the following setup module is complete:
- CI/CD with Terraform: terraform-module-12.5
You will also need:
- An AWS account with permissions to create and manage S3 buckets
- A running Jenkins instance from the prerequisite module
- Terraform
>= 0.12installed locally (for verifying state)
By 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.
This project moves Terraform state into an AWS S3 backend so that:
- State is stored centrally and shared across the team and the CI/CD pipeline
- Versioning protects against accidental state loss
- Server-side encryption keeps sensitive values at rest secure
- Native S3 locking (
use_lockfile) prevents concurrentapplyoperations from clobbering each other
This bucket will hold the remote Terraform state file.
-
Open the AWS console and navigate to Amazon S3 → Buckets → Create bucket.
-
Configure the following options:
Setting Value Name myapp-tfBucket namespace Account Regional namespaceVersioning EnableEncryption type Server-side encryption with Amazon S3 managed keys (SSE-S3)Bucket Key Disable
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.
- Click Create bucket.
Once the bucket exists, copy its full name from the S3 console (for example: myapp-tf-629604312222-eu-central-1-an).
Add the backend "s3" block to terraform/main.tf:
terraform {
required_version = ">= 0.12"
backend "s3" {
bucket = "full-bucket-name"
key = "myapp/state.tfstate"
region = "eu-central-1"
encrypt = true
use_lockfile = true
}
}| Field | Purpose |
|---|---|
bucket |
The S3 bucket created in step 1 (replace full-bucket-name with your value). |
key |
Object path inside the bucket where the state file is stored. |
region |
AWS region of the bucket — must match the bucket's region. |
encrypt |
Forces server-side encryption when uploading state. |
use_lockfile |
Enables S3-native state locking, removing the need for a separate DynamoDB table. |
The 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.
curl https://ipinfo.io/ip-
Go to
java-maven-app→ Credentials → Global → Add Credentials. -
Choose Secret text and use the following values:
- ID:
MY_IP - Secret:
<your public IP>
- ID:
The final list of pipeline credentials should look like this:
Trigger the Jenkins job and watch the stages execute end-to-end:
After the pipeline finishes, a tfstate file should appear inside the S3 bucket:
To confirm that your local Terraform CLI can read the same remote state, run from the terraform/ directory:
terraform init
terraform state listterraform 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.








