---
title: "How to Build a Terraform CI/CD Pipeline with GitHub Actions"
description: "Learn how to automate AWS S3 bucket creation using a Terraform CI/CD pipeline with GitHub Actions. Includes full code, OIDC setup, and IAM configuration — from beginner to advanced."
url: https://srinimf.com/2026/01/13/complete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced/
date: 2026-01-13
modified: 2026-10-13
author: "Srini"
image: https://i0.wp.com/srinimf.com/wp-content/uploads/2026/01/pexels-photo-27609971.jpeg?fit=1880%2C1253&ssl=1
categories: ["GitHub", "Terraform"]
tags: ["cicd terraform setup example", "deploy s3 bucket terraform", "terraform automation"]
type: post
lang: en
---

# How to Build a Terraform CI/CD Pipeline with GitHub Actions

Setting up a Terraform CI/CD pipeline with GitHub Actions is one of the most effective ways to automate your AWS infrastructure deployments. In this guide, you’ll learn [how to](https://srinimf.com/2022/04/04/5-key-terms-you-need-to-know-in-terraform/) build a complete Terraform CI/CD pipeline with GitHub Actions — from configuring OIDC authentication and IAM roles to running plan and apply jobs automatically on every pull request and merge.

Related[4 Essential AWS Services to Accelerate Deployment](https://srinimf.com/2022/06/27/4-aws-code-services-the-real-usage/)

## Key Takeaways

- Here’s a comprehensive guide on automating the creation of AWS S3 buckets using Terraform and GitHub Actions.

- Readers will learn how to establish a seamless Continuous Integration and Continuous Deployment (CI/CD) workflow. This workflow automatically creates an S3 bucket whenever code is pushed to GitHub..

- The article covers the entire process. It includes writing Terraform code and configuring GitHub Secrets for secure credential management. The article provides clear instructions for setting up the necessary components.

- By the end of the post, you will have a fully functioning automation pipeline. This pipeline ensures efficient resource management. It also secures resource management in AWS.

![Terraform CI/CD pipeline GitHub Actions workflow chart](https://i0.wp.com/srinimf.com/wp-content/uploads/2026/01/image-1.png?resize=1205%2C316&ssl=1)

## ✅ Overview

This setup consists of a **Terraform project** and a **GitHub Actions workflow**. It automates the creation of an S3 bucket in AWS.

**What this project achieves:**

- **Automated Creation**: An S3 bucket is automatically created when the code is pushed.

- **Secure Authentication**: Uses GitHub Secrets to manage AWS login details.

- **CI/CD Integration**: No manual intervention is required.

## 🟦 Terraform Code: AWS Resource Definition

The main files involved in this process are:

- `main.tf`
- `variables.tf`
- `outputs.tf`

### What does the Terraform code create?

- One AWS S3 bucket with specified tags (`Environment=dev`, `Project=terraform-ci-cd`) and a name provided from variables.

## 🟧 GitHub Actions Workflow

The workflow defined in `.github/workflows/terraform.yml` triggers automatically when you push code to the `main` branch or create a pull request.

### Pipeline Steps

1. **Checkout Code**: Pulls the latest code from the GitHub repository.
2. **Setup Terraform**: Installs Terraform on the GitHub server.
3. **terraform init**: Initializes Terraform modules and provider plugins.
4. **terraform fmt**: Checks the formatting of Terraform files.
5. **terraform validate**: Validates the Terraform configuration syntax.
6. **terraform plan**: Shows the changes Terraform intends to make.
7. **terraform apply**: Creates the AWS S3 bucket on `main` branch push.

## 🟩 Using GitHub Secrets for AWS Credentials

The pipeline retrieves AWS credentials from GitHub Secrets:

- `AWS_ACCESS_KEY_ID`
- `AWS_SECRET_ACCESS_KEY`
- `AWS_REGION`

This approach ensures that credentials are not exposed in the code.

## 🟫 When Does It Run?

The pipeline is triggered by:

- A push to the `main` branch

- A pull request to the `main` branch

## Output of the Terraform Execution

After running the pipeline, Terraform will output:

- **Bucket Name**: Name of the created S3 bucket.
- **Bucket ARN**: Amazon Resource Name of the S3 bucket.

**Example output:**

```
bucket_name = "my-demo-s3-bucket"bucket_arn  = "arn:aws:s3:::my-demo-s3-bucket"
```

## 🎯 Summary

### Components and Purposes:

| Component | Purpose |
| --- | --- |
| Terraform files | Define an AWS resource (S3 bucket) |
| GitHub Actions pipeline | Automates validation, planning, and creation |
| AWS Secrets | Secure authentication |
| CI/CD | Eliminates manual `terraform apply` |

### In Simple Terms

“This project automatically creates an S3 bucket in AWS whenever you push code to GitHub.”

## ✅ Terraform Files

### 1. **main.tf** (Example: Create an S3 Bucket)

```
terraform {  required_version = ">= 1.0"  required_providers {    aws = {      source  = "hashicorp/aws"      version = "~> 5.0"    }  }}provider "aws" {  region = var.aws_region}resource "aws_s3_bucket" "demo_bucket" {  bucket = var.bucket_name  tags = {    Environment = "dev"    Project     = "terraform-ci-cd"  }}
```

### 2. **variables.tf**

```json
variable "aws_region" {  type        = string  description = "AWS region to create resources"  default     = "ap-south-1"}variable "bucket_name" {  type        = string  description = "S3 bucket name"}
```

### 3. **outputs.tf**

```
output "bucket_name" {  value = aws_s3_bucket.demo_bucket.bucket}output "bucket_arn" {  value = aws_s3_bucket.demo_bucket.arn}
```

### 4. **GitHub Actions Pipeline**

Create a folder `.github/workflows/` and add the following YAML:

```
name: Terraform CI/CDon:  push:    branches: ["main"]  pull_request:    branches: ["main"]jobs:  terraform:    name: Terraform Apply Pipeline    runs-on: ubuntu-latest    permissions:      contents: read      id-token: write    steps:      - name: Checkout source code        uses: actions/checkout@v3      - name: Setup Terraform        uses: hashicorp/setup-terraform@v2      - name: Terraform Init        run: terraform init      - name: Terraform Format        run: terraform fmt -check      - name: Terraform Validate        run: terraform validate      - name: Terraform Plan        run: terraform plan -input=false      - name: Terraform Apply        if: github.ref == &apos;refs/heads/main&apos;        run: terraform apply -auto-approve        env:          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}          AWS_REGION: ${{ secrets.AWS_REGION }}
```

## 📌 Required GitHub Secrets

Navigate to:

**GitHub → Repo → Settings → Secrets → Actions**

Add the following secrets:

- `AWS_ACCESS_KEY_ID`

- `AWS_SECRET_ACCESS_KEY`

- `AWS_REGION`

## 🌟 Folder Structure

Your project folder should look like this:

```
terraform-demo/│├── main.tf├── variables.tf├── outputs.tf│└── .github/    └── workflows/        └── terraform.yml
```

## 🎉 Deploy the Project to GitHub

To deploy the project, run the following commands:

```
git add .git commit -m "Initial Terraform CI/CD pipeline"git push
```

Related[10 Frequently Asked Jenkins(2.0) Interview Questions](https://srinimf.com/2021/12/25/10-frequently-asked-jenkins2-0-interview-questions/)

Upon pushing, GitHub Actions will automatically:

- Init
- Validate
- Plan
- Apply

Related[GitHub Features & Settings Explained: The Ultimate GitHub Options Guide](https://srinimf.com/2025/12/28/github-features-settings-explained-the-ultimate-github-options-guide/)

## Steps: Create IAM Role for GitHub Actions (OIDC)

---

### Step 1: Add GitHub OIDC Provider (One-Time)

> Skip this step if it already exists in your AWS account.

### AWS Console

1. Go to **IAM**
2. Click **Identity providers**
3. Click **Add provider**

### Provider settings

- **Provider type:** OpenID Connect
- **Provider URL:** `https://token.actions.githubusercontent.com`
- **Audience:** `sts.amazonaws.com`

1. Click **Add provider**

✅ GitHub is now trusted by AWS

## Step 2: Create IAM Role

1. Go to **IAM → Roles**
2. Click **Create role**

## Step 3: Select Trusted Entity

1. Choose **Web identity**
2. Identity provider:`token.actions.githubusercontent.com`
3. Audience:`sts.amazonaws.com`
4. Click **Next**

## Step 4: Attach Permissions Policy

For **demo/testing**, you can attach:

- `AmazonS3FullAccess`

For **Terraform production use**, common options:

- Custom least-privilege policy
- OR temporarily: `AdministratorAccess`

👉 Recommended later: **custom Terraform policy**

Click **Next**

## Step 5: Role Name & Create

- **Role name:** `github-actions-terraform`
- Description: `IAM role assumed by GitHub Actions via OIDC for Terraform deployments`

Click **Create role**

## Step 6: Edit Trust Policy (IMPORTANT)

After role creation:

1. Open the role
2. Go to **Trust relationships**
3. Click **Edit trust policy**
4. Replace with:

```
{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Principal": {        "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"      },      "Action": "sts:AssumeRoleWithWebIdentity",      "Condition": {        "StringEquals": {          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"        },        "StringLike": {          "token.actions.githubusercontent.com:sub": "repo:<GITHUB_ORG>/<REPO_NAME>:*"        }      }    }  ]}
```

### Replace:

- \`\` → AWS account ID
- \`\` → GitHub org or username
- \`\` → Repository name

✅ This locks access to **only your repo**

## Step 7: Verify Role ARN

Copy the **Role ARN**, example:

```
arn:aws:iam::123456789012:role/github-actions-terraform
```

You will use this in GitHub Actions.

## Step 8: Update GitHub Actions Workflow

In your GitHub Actions YAML:

```
permissions:  id-token: write  contents: readsteps:  - name: Configure AWS credentials    uses: aws-actions/configure-aws-credentials@v4    with:      role-to-assume: arn:aws:iam::123456789012:role/github-actions-terraform      aws-region: us-east-1
```

🚫 No AWS access keys needed
✅ Secure, short-lived credentials

## Step 9: Test the Setup

1. Push code to GitHub
2. GitHub Actions runs
3. AWS CloudTrail shows: `AssumeRoleWithWebIdentity`
4. Terraform executes successfully

## Recommended Next Hardening (Best Practices)

- Restrict `sub` to specific branches:

```
"repo:org/repo:ref:refs/heads/main"
```

- Use **separate roles per environment**
  - dev
  - staging
  - prod
- Replace `AdministratorAccess` with **least privilege**

## Quick Checklist ✅

✔ OIDC Provider added
✔ IAM Role created
✔ Trust policy locked to repo
✔ Permissions attached
✔ Role ARN used in GitHub Actions

### Share this:

-
- [Tweet](https://twitter.com/share)
- [![](https://i0.wp.com/assets.pinterest.com/images/pidgets/pinit_fg_en_rect_gray_20.png)](https://www.pinterest.com/pin/create/link/?url=https%3A%2F%2Fsrinimf.com%2F2026%2F01%2F13%2Fcomplete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced%2F&media=https%3A%2F%2Fi0.wp.com%2Fsrinimf.com%2Fwp-content%2Fuploads%2F2026%2F01%2Fpexels-photo-27609971.jpeg%3Ffit%3D1200%252C800%26ssl%3D1&description=How%20to%20Build%20a%20Terraform%20CI%2FCD%20Pipeline%20with%20GitHub%20Actions)
-
- [Share on Tumblr](https://www.tumblr.com/share)
- [Share on WhatsApp (Opens in new window) WhatsApp](https://srinimf.com/2026/01/13/complete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced/?share=jetpack-whatsapp)
- [More](#)
-

- [Print (Opens in new window) Print](https://srinimf.com/2026/01/13/complete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced/?share=print)
- [Share on Reddit (Opens in new window) Reddit](https://srinimf.com/2026/01/13/complete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced/?share=reddit)
- [Share on Telegram (Opens in new window) Telegram](https://srinimf.com/2026/01/13/complete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced/?share=telegram)
- [Email a link to a friend (Opens in new window) Email](mailto:?subject=%5BShared%20Post%5D%20How%20to%20Build%20a%20Terraform%20CI%2FCD%20Pipeline%20with%20GitHub%20Actions&body=https%3A%2F%2Fsrinimf.com%2F2026%2F01%2F13%2Fcomplete-terraform-ci-cd-pipeline-setup-with-github-actions-beginner-to-advanced%2F&share=email)
-

### Like this:

Like Loading…
