Skip to content

Devops Fundamentals Terraform & Git

Table of Contents

Basic Intermediate Advanced
1. Terraform – Basic
a. What is Infrastructure as Code (IaC)
b. Terraform Overview
c. Terraform Workflow (init, plan, apply)
d. Terraform Core Components (Provider, Resource, State)
2. Terraform – Intermediate
a. Variables and Outputs
b. Terraform State Management
c. Remote State (S3, DynamoDB Locking)
d. Terraform Modules
e. Environment Separation
3. Terraform – Advanced
a. Terraform Design Best Practices
b. Large-Scale State Management
c. Module Design Patterns
d. Multi-Environment and Multi-Account Strategy
4. Git – Basic
a. Version Control Overview
b. Git Repository and Commit Lifecycle
c. Branching and Merging Basics
d. Working with Remote Repositories
5. Git – Intermediate
a. Branching Strategies
b. Pull Requests and Code Reviews
c. Merge vs Rebase
d. Handling Conflicts
6. Git – Advanced
a. Advanced Branching Models
b. Repository Governance and Access Control
7. GitHub Actions – Basic
a. Introduction to GitHub Actions
b. GitHub Actions Core Concepts (Workflow, Job, Step, Runner)
8. GitHub Actions – Intermediate
a. GitHub Actions Workflows
b. Events, Triggers, and Conditions
c. Caching, Artifacts, and Matrix Builds
d. Environments and Approvals
9. GitHub Actions – Advanced
a. GitHub Actions Custom Actions
b. Advanced Security Practices (OIDC, Secrets Management)
c. CI/CD for Multi-Environment Deployments
d. Self-Hosted Runners
e. Observability, Debugging, and Optimization
f. Governance and Enterprise Patterns

References & Further Reading

Terraform – Basics

What is Infrastructure as Code (IaC)

Infrastructure as Code (IaC) is a practice where infrastructure is defined and managed using code, instead of manually configuring resources through a user interface.

With IaC:

Infrastructure becomes version-controlled

Changes are repeatable and predictable

Environments can be recreated consistently

IaC is a foundational DevOps concept because it reduces human error and enables automation.

Example (IaC concept): Defining an S3 bucket or EC2 instance in a configuration file instead of creating it manually in the AWS Console.

Terraform Overview

Terraform is an Infrastructure as Code tool that allows you to define cloud infrastructure using declarative configuration files.

Terraform supports:

Multiple cloud providers (AWS, Azure, GCP)

Version-controlled infrastructure

Automated provisioning and updates

Terraform focuses on what the infrastructure should look like, and it handles how to create or update it.

Example (Basic Terraform file):

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-basic-terraform-bucket"
}

Explanation:

This configuration tells Terraform to connect to AWS and create an S3 bucket in the specified region.

provider "aws"
 Specifies AWS as the cloud provider that Terraform will use.
region = "us-east-1"
 Sets the AWS region where resources will be created.
resource "aws_s3_bucket" "example"
 Declares an AWS S3 bucket resource managed by Terraform.
bucket = "my-basic-terraform-bucket"
 Defines the name of the S3 bucket to be created.

Terraform Workflow (init, plan, apply)

Terraform follows a simple and consistent workflow:

terraform init

Initializes the working directory and downloads required providers.

Command: terraform init

terraform plan

Shows a preview of changes Terraform will make to reach the desired state.

Command: terraform plan

terraform apply

Creates or updates infrastructure based on the configuration.

Command: terraform apply

This workflow ensures infrastructure changes are reviewed before execution.

Terraform Core Components (Provider, Resource, State)

Provider

A plugin that allows Terraform to communicate with a specific cloud or service (for example, AWS).

provider "aws" {
  region = "us-east-1"
}

Resource

A definition of an infrastructure component such as an EC2 instance or S3 bucket.

resource "aws_instance" "example" {
  ami           = "ami-0abcdef"
  instance_type = "t2.micro"
}

State

A file that tracks the current state of infrastructure and maps it to the Terraform configuration.

Terraform automatically creates a state file after running:

terraform apply

Together, these components allow Terraform to manage infrastructure reliably and predictably.

Terraform – Intermediate

Variables and Outputs

Variables allow Terraform configurations to be parameterized, making them reusable across environments. Outputs expose important values after infrastructure is created, enabling integration with other modules or tools.

At this level, variables and outputs help avoid hardcoding and support environment-specific configurations.

Example (Using variables and outputs):

variable "instance_type" {
  default = "t3.micro"
}

resource "aws_instance" "app" {
  instance_type = var.instance_type
  ami           = "ami-0abcdef"
}

output "instance_id" {
  value = aws_instance.app.id
}

Explanation:

This configuration creates an EC2 instance using a configurable instance type and outputs its ID after deployment.

variable "instance_type"
 Declares a variable that allows the EC2 instance type to be configured dynamically.
default = "t3.micro"
 Sets the default instance type if no custom value is provided.
resource "aws_instance" "app"
 Defines an EC2 instance resource named app.
instance_type = var.instance_type
 Uses the variable value instead of hardcoding the instance type.
ami = "ami-0abcdef"
 Specifies the Amazon Machine Image (AMI) used to launch the instance.
output "instance_id"
 Exposes the created EC2 instance ID after Terraform applies the configuration.
value = aws_instance.app.id
 Retrieves the ID of the created EC2 instance

This allows the same configuration to be reused with different inputs.

Terraform State Management

Terraform state tracks the current real-world infrastructure and maps it to the configuration files. It enables Terraform to determine what needs to be created, updated, or destroyed.

Proper state management is critical to avoid configuration drift and unintended infrastructure changes.

Example (State usage):

terraform plan

Terraform compares the configuration with the state file to calculate changes.

Remote State (S3, DynamoDB Locking)

Remote state stores the Terraform state file in a shared backend instead of locally. Using a remote backend enables team collaboration and prevents state inconsistencies.

State locking ensures that only one operation can modify infrastructure at a time, reducing the risk of conflicts.

Example (Remote backend concept):

terraform {
  backend "s3" {
    bucket         = "terraform-state-bucket"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
  }
}

Explanation:

This configuration centralizes the Terraform state in S3 and uses DynamoDB locking to prevent concurrent updates, ensuring safe team collaboration.

backend "s3"
 Configures Terraform to store its state file remotely in an S3 bucket instead of locally.
bucket = "terraform-state-bucket"
 Specifies the S3 bucket where the state file will be stored.
key = "prod/terraform.tfstate"
 Defines the path inside the bucket, typically separating environments (here: production).
dynamodb_table = "terraform-locks"
 Enables state locking using DynamoDB to prevent multiple users from modifying infrastructure at the same time.

This setup allows multiple engineers to work safely on the same infrastructure.

Terraform Modules

Modules are reusable collections of Terraform configurations that represent a logical set of resources.

At the intermediate level, modules are used to:

Reduce code duplication

Standardize infrastructure patterns

Improve maintainability

Modules help teams scale Terraform usage across multiple projects.

Example (Calling a module):

module "network" {
  source = "../modules/vpc"
  cidr   = "10.0.0.0/16"
}

Explanation:

This configuration reuses a predefined VPC module and passes environment-specific values to create network infrastructure.

module "network"
 Calls a reusable Terraform module named network.
source = "../modules/vpc"
 Specifies the location of the module code (in this case, a local folder containing VPC configuration).
cidr = "10.0.0.0/16"
 Passes an input variable to the module, defining the CIDR block for the VPC.

This enables consistent infrastructure across environments.

Environment Separation

Environment separation ensures that development, staging, and production environments are isolated and independently managed.

This is commonly achieved using separate state files, variables, or workspaces to prevent accidental changes across environments.

Example (Using workspaces):

terraform workspace new dev

Explanation:

Creates a new workspace named dev, which maintains a separate state file for the development environment.
terraform workspace select prod
Switches to the prod workspace, allowing Terraform operations to target the production environment.

Each environment maintains its own state.

Terraform – Advanced

Terraform Design Best Practices

At the advanced level, Terraform is treated as a platform enabler, not just a provisioning tool.

Design best practices focus on:

Writing predictable and readable configurations

Minimizing blast radius during changes

Ensuring long-term maintainability

Key principles include clear naming conventions, small focused modules, avoiding hard dependencies, and making changes incremental to reduce risk in production environments.

Large-Scale State Management

In large environments, Terraform state becomes a critical system dependency.

Advanced state management focuses on:

Centralized state storage

Strict access controls

Controlled state modifications

Poor state handling at scale can lead to race conditions, accidental deletions, or environment corruption, making state governance as important as the infrastructure itself.

Module Design Patterns

Advanced module design emphasizes reusability without rigidity.

Effective module patterns:

Expose only necessary inputs and outputs

Avoid embedding environment-specific logic

Support extension without modification

Well-designed modules allow teams to scale infrastructure consistently while still supporting customization where needed.

Multi-Environment and Multi-Account Strategy

Advanced environments separate infrastructure across multiple environments and accounts to improve security and governance.

This strategy enables:

Strong isolation between environments

Reduced blast radius for failures

Clear ownership and billing separation

At scale, environment and account strategy becomes a core part of cloud architecture, not just an operational choice.

Git & GitHub Platform – Basics

Version Control Overview

Version control is a system that tracks changes made to files over time.

It allows teams to:

Collaborate on code

Track history and changes

Roll back to previous versions if needed

Git is the most widely used distributed version control system in modern DevOps workflows.

Basic Git initialization:

git init

Git Repository and Commit Lifecycle

A Git repository stores project files and their complete change history.

The typical commit lifecycle:

Modify files

Stage changes

Commit changes with a message

Push commits to a remote repository

git add .

Explanation:

Stages all modified and new files in the current directory to be included in the next commit.

git commit -m "Initial commit"

Creates a commit with a message, saving the staged changes as a snapshot in the repository history.

These commands stage changes and record them as a versioned snapshot in the Git repository.

Branching and Merging Basics

Branches allow developers to work on features or fixes independently from the main codebase.

Branching creates a separate line of development

Merging combines changes back into another branch

git checkout -b feature-login

Explanation:

Creates a new branch named feature-login and switches to it for development.
git merge feature-login
Merges the changes from the feature-login branch into the current branch.

These commands demonstrate creating a feature branch for development and merging it back into another branch.

Working with Remote Repositories

Remote repositories are hosted versions of Git repositories, commonly on platforms like GitHub.

They enable:

Team collaboration

Centralized code sharing

Integration with automation tools

Common operations:

git remote add origin 
git push origin main
git pull origin main

Explanation:

These commands connect a local repository to a remote repository and synchronize changes between them.

git remote add origin <repository-url>
 Connects the local repository to a remote repository named origin.
git push origin main
 Uploads local commits from the main branch to the remote repository.
git pull origin main
 Fetches and merges the latest changes from the remote main branch into the local branch.

Introduction to GitHub Actions

GitHub Actions is GitHub’s automation and CI/CD platform.

It allows teams to:

Build

Test

Scan

Deploy applications

Workflows are triggered by events such as code pushes or pull requests and are defined using YAML files.

Basic workflow trigger example:

on:
  push:
    branches: [ main ]

GitHub Actions Core Concepts (Workflow, Job, Step, Runner)

Workflow – A YAML-defined automation process stored in the repository

Job – A group of steps executed on the same runner

Step – An individual task within a job

Runner – A machine that executes the workflow jobs

Basic workflow structure:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello GitHub Actions"

These components work together to automate software workflows.

Git & GitHub Platform – Intermediate

Branching Strategies

Branching strategies define how teams organize and manage code changes. They help coordinate development, reduce conflicts, and maintain stability in the main branch.

Common strategies focus on isolating feature development while keeping production code stable.

Example (Feature branch workflow):

git checkout -b feature/payment
git push origin feature/payment

Pull Requests and Code Reviews

Pull requests provide a structured way to review changes before merging them into shared branches.

Code reviews improve code quality, enforce standards, and reduce defects before changes reach production.

Example:
 A feature branch is merged into main only after approvals and successful checks.

Merge vs Rebase

Merging and rebasing are two ways of integrating changes between branches.

Merge preserves full history and context

Rebase creates a cleaner, linear history

The choice depends on team preference and workflow requirements.

Example:

git merge feature/login
git rebase main

Handling Conflicts

Conflicts occur when multiple changes affect the same code. Handling conflicts requires understanding the intent of each change and resolving them carefully to preserve correctness.

Effective conflict resolution is a key collaboration skill at this level.

Example: Two developers modify the same configuration file and resolve conflicts before merging.

GitHub Actions Workflows

Workflows define automated processes such as build, test, and deployment pipelines.

At the intermediate level, workflows are used to:

Automate CI processes

Enforce consistency

Reduce manual intervention

Workflows are defined declaratively using YAML files.

Example (Basic CI workflow):

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm test

Events, Triggers, and Conditions

Events determine when workflows run, while conditions control whether jobs or steps execute.

Using triggers and conditions allows workflows to respond differently based on branches, environments, or repository events.

Example:

on:
  pull_request:
if: github.ref == 'refs/heads/main'

Caching, Artifacts, and Matrix Builds

Caching improves workflow performance by reusing dependencies

Artifacts persist build outputs across jobs

Matrix builds run workflows across multiple configurations in parallel

These features optimize pipeline speed and flexibility.

Example (Matrix build):

strategy:
  matrix:
    node-version: [16, 18, 20]

Environments and Approvals

Environments represent deployment targets such as dev, staging, or production.

Approvals add manual checks before workflows proceed, helping control changes to sensitive environments.

Example: Requiring approval before deploying to the production environment.

Git & GitHub Platform – Advanced

Advanced Branching Models

Advanced branching models are designed to support large teams and continuous delivery.

These models balance:

Developer productivity

Release stability

Traceability of changes

The choice of branching model directly impacts deployment frequency, incident recovery, and collaboration efficiency.

Repository Governance and Access Control

Repository governance ensures that code changes follow organizational standards and security policies.

Advanced governance focuses on:

Role-based access control

Mandatory reviews

Protected branches

Strong governance prevents unauthorized changes and enforces consistency across teams and repositories.

GitHub Actions Custom Actions

Custom actions encapsulate reusable automation logic into maintainable building blocks.

At the advanced level, custom actions are used to:

Standardize CI/CD behavior

Reduce workflow duplication

Encapsulate complex logic

They enable teams to treat CI/CD automation as a reusable product rather than ad-hoc scripts.

Advanced Security Practices (OIDC, Secrets Management)

Advanced CI/CD security eliminates long-lived credentials and enforces identity-based access.

Key focus areas include:

Short-lived authentication using OIDC

Centralized secrets management

Strict permission scoping

Security at this level is proactive, assuming that pipelines are a potential attack surface.

CI/CD for Multi-Environment Deployments

Advanced CI/CD pipelines manage artifact promotion across environments, not repeated builds.

This approach ensures:

Consistency between environments

Controlled production releases

Clear audit trails

Multi-environment pipelines reflect real-world release processes used in production systems.

Self-Hosted Runners

Self-hosted runners are introduced when organizations require:

Access to private networks

Custom tooling or hardware

Greater control over execution environments

At the advanced level, managing runner security, scalability, and maintenance becomes part of platform operations.

Observability, Debugging, and Optimization

Advanced CI/CD observability focuses on:

Pipeline performance analysis

Failure trend identification

Optimization of execution time

Well-instrumented pipelines reduce downtime and accelerate recovery when failures occur.

Governance and Enterprise Patterns

Enterprise-scale GitHub usage requires consistent governance across repositories and teams.

Advanced patterns include:

Centralized reusable workflows

Organization-wide policies

Auditability and compliance enforcement

Governance ensures that automation scales safely as the organization grows.

References & Further Reading

Category Resource Link
Terraform Terraform Documentation developer.hashicorp.com/terraform
Terraform State & Backends developer.hashicorp.com
Git Git Documentation git-scm.com/doc
Git Branching Concepts git-scm.com
Git Merge vs Rebase git-scm.com/docs/git-rebase
GitHub Actions GitHub Actions Documentation docs.github.com/actions
Workflow Syntax docs.github.com
Events & Triggers docs.github.com
Reusable Workflows docs.github.com
Security Hardening for GitHub Actions docs.github.com
DevOps Concepts CI/CD Concepts martinfowler.com
Infrastructure as Code Overview www.hashicorp.com