Hitesh Sahu
Hitesh SahuHitesh Sahu
  1. Home
  2. ›
  3. posts
  4. ›
  5. …

  6. ›
  7. 1.1 Basics

Loading ā³
Please wait...

šŸŖ This website uses cookies

No personal data is stored on our servers however third party tools Google Analytics cookies to measure traffic and improve your website experience. Learn more

Cover Image for Introduction To Terraform Basics

Introduction To Terraform Basics

Overview of Terraform basics, including installation, configuration, providers, and resource management.

Hitesh Sahu
Hitesh Sahu

Mon Sep 29 2025

Terraform basics - 11%

  • 3a Install and version Terraform providers
  • 3b Describe plugin-based architecture
  • 3c Write Terraform configuration using multiple providers
  • 3d Describe how Terraform finds and fetches providers

Initialize Terraform working directory

command use
terraform init initialize directory, pull down providers
terraform init -get-plugins=false initialize directory, do not download plugins
terraform init -verify-plugins=false initialize directory, do not verify plugins for Hashicorp signature
terraform version display Terraform binary version, also warns if version is old
terraform get -update=true download and update modules in the "root" module.

Misclaneous

command use
terraform -install-autocomplete Setup tab auto-completion, requires logging back in
terraform login obtain and save API token for Terraform cloud
terraform logout Log out of Terraform Cloud, defaults to hostname app.terraform.io
terraform graph | dot -Tpng > graph.png produce a PNG diagrams
echo 'join(",",["foo","bar"])' | terraform console echo expression into terraform console

Terrform help

  • āœ… -h, --h eg: terraform plan -h, terraform plan --h, -h plan, plan -h

  • āœ… -help , --help eg: terraform plan -help, terraform plan --help, --help plan, -help plan


HashiCorp Terraform

infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share.

  • Provides a consistent workflow to provision and manage all of infrastructure throughout its lifecycle.
  • Can manage low-level components like compute, storage, & networking resources, as well as high-level components like DNS entries and SaaS features.

To deploy infrastructure with Terraform:

  • Scope - Identify the infrastructure for your project.
  • Author - Write the configuration for your infrastructure.
  • Initialize - Install the plugins Terraform needs to manage the infrastructure.
  • Plan - Preview the changes Terraform will make to match your configuration.
  • Apply - Make the planned changes.

Terraform plugins

Terraform is comprised of Terraform Core and Terraform Plugins:

1. Terraform Core(core-plugins-api)

Terraform binary that communicates with plugins to manage infrastructure resources.

  • Provides a common interface that allows to leverage many different cloud providers, databases, services olutions.
  • Reads the configuration and builds the resource dependency graph.

2. Terraform Plugins (providers and provisioners)

Bridge Terraform Core and their respective target APIs.

  • Implement resources via basic CRUD (create, read, update, and delete) APIs to communicate with third party services.

.terraform.lock.hcl

Terraform remembers the compatible version of dependencies such as providers and modules through dependency lock file.

  • Terraform automatically creates or updates the dependency lock file each time you run the terraform init command.

Providers

Top level abstraction that define the available resources and data sources

  • Plugins to interact with cloud providers, SaaS providers, & other APIs.
  • installed from Terraform registry

Version Constraint Syntax

The following operators are valid:

  • =(or no operator): Allows only one exact version number. Cannot be combined with other conditions.

  • !=: Excludes an exact version number.

  • >, >=, <, <=: Comparisons against a specified version, allowing versions for which the comparison is true. " Greater-than" requests newer versions, and "less-than" requests older versions.

  • ~>: pessimistic constraint operator Allows only the rightmost version component to increment.

    • ~> 1.9.0 means >= 1.9.0 and < 1.10.0

        # allows: 1.9.1, 1.9.9 
        # not allow: 1.20.1, 1.8.9
        provider "google" {
        version = "~> 1.9.0"
        }
      

Provisioners

Use to model specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure objects for service.

Note: Provisioners should only be used as a last resort.

provisioner block is always added inside the resource block of compute instances

Provisioners that fail will also cause the Terraform apply itself to fail. The on_failure setting can be used to: continue and fail

  • āœ… continue
  • āœ… fail

local-exec provisioner

invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource.

    resource "aws_instance" "web" {
      provisioner "local-exec" {
         command = "echo The server's IP address is ${self.private_ip}"
      on_failure = continue  # Failure behaviour
    }}

Destroy provisioners

Destroy provisioners are run before the resource is destroyed. If they fail, Terraform will error and rerun the provisioners again on the next terraform apply.

    # Destroy-Time Provisioners
    resource "aws_instance" "web" {
        provisioner "local-exec" {
        when    = destroy <--When
        command = "echo 'Destroy-time provisioner'"
    }

remote-exec Provisioner

invokes a script on a remote resource after it is created.

    resource "aws_instance" "web" {
    # ...

    # Establishes connection to be used by all
    # generic remote provisioners (i.e. file/remote-exec)
    connection {
        type     = "ssh"
        user     = "root"
        password = var.root_password
        host     = self.public_ip
    }

    provisioner "remote-exec" {
        inline = [
        "puppet apply",
        "consul join ${aws_instance.web.private_ip}",
        ]
    }
    }

If resource is not available use terraform-data

    resource "aws_instance" "cluster" {
    count = 3

    # ...
    }

    resource "terraform_data" "cluster" {
    # Replacement of any instance of the cluster requires re-provisioning
    triggers_replace = aws_instance.cluster.[*].id

    # Bootstrap script can run on any instance of the cluster
    # So we just choose the first in this case
    connection {
        host = aws_instance.cluster.[0].public_ip
    }

    provisioner "remote-exec" {
        # Bootstrap script called with private_ip of each node in the cluster
        inline = [
        "bootstrap-cluster.sh ${join(" ", aws_instance.cluster.*.private_ip)}",
        ]
    }
    }

File Provisoner

copies files or directories from the machine running Terraform to the newly created resource.

# Copies the myapp.conf file to /etc/myapp.conf
provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "/etc/myapp.conf"
}       

Connection Block

Access to the remote resource via SSH or WinRM and expect a nested connection block with details about how to connect.

Mode SSH

    # Copies the file as the root user using SSH
    provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "/etc/myapp.conf"

    connection {
        type     = "ssh"
        user     = "root"
        password = "${var.root_password}"
        host     = "${var.host}"
    }
    }

Mode WinRM

    # Copies the file as the Administrator user using WinRM
    provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "C:/App/myapp.conf"

    connection {
        type     = "winrm"
        user     = "Administrator"
        password = "${var.admin_password}"
        host     = "${var.host}"
    }
    }

Resources

abstraction that allow Terraform to manage infrastructure objects, such as a compute instance, an access policy, or disk.

Providers act as a translation layer between Terraform and an API, offering one or more resources for practitioners to define in a configuration.

resource "aws_instance" "web" {
count = 4
}

Resource Addressing

is a string that identifies zero or more resource instances in your overall configuration.

Resource addressed as: <RESOURCE_TYPE>.<RESOURCE_NAME>[resource instance index]

aws_instance.web[3] # Third instance

aws_instance.web # Only the last instance

With for each:

resource "aws_instance" "demo" {
for_each = {
    "terraform": "infrastructure",
    "vault":     "security",
    "consul":    "connectivity",
    "nomad":     "scheduler",
}}

# address by key
access aws_instance.demo["vault"]

Module addressed as: module.<MODULE_NAME>[module index

module.foo[0].module.bar["a"]

Data Sources

Allow Terraform to use information defined outside of Terraform, defined by another separate Terraform configuration, or modified by functions.

The data source + name together serve as an identifier for a given resource and so must be unique within a module.

A data block requests that Terraform read from a given data source ("aws_ami") and export the result under the given local name ("ubuntu").

data "aws_ami" "ubuntu" {
most_recent = true

owners = ["self"]
tags = {
    Name   = "app-server"
    Tested = "true"
}
}

Data Source value is addressed as data.<DATA TYPE>.<NAME>.<ATTRIBUTE>

resource "aws_instance" "web" {
ami           = data.aws_ami.ubuntu.id # Data Source 
instance_type = "t3.micro"
}

Building Infrastructure

launch Docker using Teraform file: main.tf

    terraform { <---- TERRAFORM BLOCK
    required_providers {
        docker = {
        source  = "kreuzwerker/docker"
        version = "~> 3.0.1"
        }
    }
    }

    provider "docker" {} <---PROVIDER BLOCK

    resource "docker_image" "nginx" { <-----RESOURCE BLOCK
    name         = "nginx"
    keep_locally = false
    }

    resource "docker_container" "nginx" {
    image = docker_image.nginx.image_id
    name  = "tutorial"

    ports {
        internal = 80
        external = 8000
    }
    }

Initialize the project, which downloads a plugin called a provider

terraform init

Format & print out the names of the files it modified,

terraform fmt

Provision the infrastructure.

terraform apply