First time at Zeet?

24 Apr
min read

A Comprehensive Terraform Tutorial for Beginners

New to Terraform? This Terraform tutorial will help you understand the basics and advance your skills in managing infrastructure efficiently.

Jack Dwyer

How To

Share this article

What is Terraform?

basics and advanced levels of terraform tutorial

What Is Terraform? Terraform is an infrastructure as code tool that lets you build, change, and version cloud and on-prem resources safely and efficiently.

How does Terraform work?

Terraform creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable Terraform to work with virtually any platform or service with an accessible API.

Use Cases

Multi-Cloud Deployment

Provisioning infrastructure across multiple clouds increases fault tolerance, allowing for more graceful recovery from cloud provider outages. However, multi-cloud deployments add complexity because each provider has its own interfaces, tools, and workflows. Terraform lets you use the same workflow to manage multiple providers and handle cross-cloud dependencies. This simplifies management and orchestration for large-scale, multi-cloud infrastructures.

Application Infrastructure Deployment, Scaling, and Monitoring Tools

You can use Terraform to efficiently deploy, release, scale, and monitor infrastructure for multi-tier applications. N-tier application architecture lets you scale application components independently and provides a separation of concerns. 

An application could consist of a pool of web servers that use a database tier, with additional tiers for API servers, caching servers, and routing meshes. Terraform allows you to manage the resources in each tier together, and automatically handles dependencies between tiers. For example, Terraform will deploy a database tier before provisioning the web servers that depend on it.

Self-Service Clusters

At a large organization, your centralized operations team may get many repetitive infrastructure requests. You can use Terraform to build a "self-serve" infrastructure model that lets product teams manage their own infrastructure independently. 

You can create and use Terraform modules that codify the standards for deploying and managing services in your organization, allowing teams to efficiently deploy services in compliance with your organization’s practices. HCP Terraform can also integrate with ticketing systems like ServiceNow to automatically generate new infrastructure requests.

Policy Compliance and Management

Terraform can help you enforce policies on the types of resources teams can provision and use. Ticket-based review processes are a bottleneck that can slow down development. Instead, you can use Sentinel, a policy-as-code framework, to automatically enforce compliance and governance policies before Terraform makes infrastructure changes. Sentinel policies are available in Terraform Enterprise and HCP Terraform.

PaaS Application Setup

Platform as a Service (PaaS) vendors like Heroku allow you to create web applications and attach add-ons, such as databases or email providers. Heroku can elastically scale the number of dynos or workers, but most non-trivial applications need many add-ons and external services. 

You can use Terraform to codify the setup required for a Heroku application, configure a DNSimple to set a CNAME, and set up Cloudflare as a Content Delivery Network (CDN) for the app. Terraform can quickly and consistently do all of this without a web interface.

Software Defined Networking

Terraform can interact with Software Defined Networks (SDNs) to automatically configure the network according to the needs of the applications running in it. This lets you move from a ticket-based workflow to an automated one, reducing deployment times. 

For example, when a service registers with HashiCorp Consul, Consul-Terraform-Sync can automatically generate Terraform configuration to expose appropriate ports and adjust network settings for any SDN that has an associated Terraform provider. Network Infrastructure Automation (NIA) allows you to safely approve the changes that your applications require without having to manually translate tickets from developers into the changes you think their applications need.


Kubernetes is an open-source workload scheduler for containerized applications. Terraform lets you both deploy a Kubernetes cluster and manage its resources (e.g., pods, deployments, services, etc.). You can also use the Kubernetes Operator for Terraform to manage cloud and on-prem infrastructure through a Kubernetes Custom Resource Definition (CRD) and HCP Terraform.

Parallel Environments

You may have staging or QA environments that you use to test new applications before releasing them in production. As the production environment grows larger and more complex, it can be increasingly difficult to maintain an up-to-date environment for each stage of the development process. 

Terraform lets you rapidly spin up and decommission infrastructure for development, test, QA, and production. Using Terraform to create disposable environments as needed is more cost-efficient than maintaining each one indefinitely.

Software Demos

You can use Terraform to create, provision, and bootstrap a demo on various cloud providers. This lets end users easily try the software on their own infrastructure and even enables them to adjust parameters like cluster size to more rigorously test tools at any scale."

Complete Terraform Tutorial Starting With Terraform Basics

understanding basics - terraform tutorial


The cloud providers interface with Terraform via providers. Providers manage cloud resources such as compute instances, storage, networking, and more.


The primary building block of the infrastructure created by Terraform is a resource. These are components that represent some infrastructure objects, such as instances, networks, or even DNS records.


Terraform promotes reusability and maintainability through modules. These are self-contained packages of Terraform configurations that can be reused in different configurations to create multiple instances of the same resource.


The state is a vital component that stores the configuration details of the created resources. Terraform uses the state to understand the current state of the infrastructure and determine the changes to make.


In Terraform, outputs provide a way to expose some of the attributes of the resources that are created by Terraform. These outputs can be used by other configurations or scripts.

Unlocking Cloud Potential with Zeet

Zeet helps you to get more from your cloud, Kubernetes, and Terraform investments and helps your engineering team become strong individual contributors through our CI/CD & deployment platform. 

Contact Zeet to learn more about how Zeet help you get seamless cloud deployments every time, and helps your team to become a top-performing engineering team.

Zeet Terraform and Helm Product Overview

Related Reading

Setting up Terraform

Installation and Setup for Terraform and AWS CLI

Installing Terraform involves downloading the appropriate binary based on your operating system and setting up the path variable. Once installed, ensure the version is correct. Similarly, for AWS CLI installation, follow the steps for your OS. After installation, verify the version and configure credentials in the AWS CLI.

Setting up Working Environment and Terraform Providers

Create a directory for your Terraform project. All Terraform code should be in .tf files in this directory. Make sure to create files like and to manage your Terraform code effectively. To work with AWS, initiate the AWS provider in the Terraform project.

Creating the First Terraform Configuration

To create an EC2 instance in AWS using Terraform, write a configuration specifying the provider and the resource to create. In the file, define the AWS provider version to use. In the file, declare the resource block for the AWS EC2 instance, including attributes like ami, instance_type, and tags.

Remember to follow these steps diligently to ensure a smooth setup for Terraform and AWS CLI. The process might seem intricate initially, but once you master it, provisioning resources through Terraform will become more manageable and efficient.

Terraform CLI (Command Line Interface)

woman using cli commands - terraform tutorial

Format (fmt)

The `terraform fmt` command helps format Terraform code in a specific directory. It removes unnecessary spaces and aligns the code properly for better readability and consistency.  

Initialize (init)

The `terraform init` command is crucial for initializing a Terraform project, especially when adding new providers or updating existing ones. It ensures that the correct provider modules are used and kept consistent with the configuration. 

Plan (plan)

The `terraform plan` command validates Terraform configurations, syntax, and versions. It provides a snapshot of the changes to be made before applying them, helping users understand the resources to be created, updated, or deleted. 

Apply (apply)

The `terraform apply` command provisions all declared resources in the Terraform code. It creates the infrastructure specified in the code and requests final confirmation before initiating the provisioning process. 

Destroy (destroy)

The `terraform destroy` command terminates or deletes all resources managed by Terraform. It is essential for cleaning up resources once they are no longer required, ensuring that the infrastructure lifecycle is fully managed by Terraform.

Related Reading

Variables and Outputs

understanding variables and outputs - terraform tutorial

Local Variables in Terraform

In Terraform, local variables are used to define attribute values within the Terraform code. They are especially useful when a value needs to be referenced in multiple places in the code. Local variables can also be used to calculate values based on other values. 

For example, a local variable can be declared as follows:

terraform locals {  ami      = "ami-065deacbcaac64cf2"  type     = "t2.micro"  name_tag = "My EC2 Instance" }

After declaring local variables, they can be referred to anywhere within the module using the syntax `local.<variable_name>`. This helps in keeping the code clean and more maintainable.

Input Variables in Terraform

Input variables in Terraform allow the dynamic assignment of values during runtime. Local variables are limited to their scope, whereas input variables can accept values during runtime. Input variables are especially useful when values need to be provided at runtime or when defining input values for modules.

An example of input variables declaration in Terraform can be as follows:

terraform variable "ami" {   type        = string   description = "Ubuntu AMI ID" } variable "instance_type" {   type        = string   description = "Instance type" } variable "name_tag" {   type        = string   description = "Name of the EC2 instance" }

To use input variables in the Terraform code, the syntax `var.<variable_name>` is used. Terraform prompts for input values during the apply process unless default values are provided for these variables.

Default Values and Terraform Variables

Default values can be assigned to variables in Terraform to avoid supplying values one by one during apply. Default values can be declared in the variables declaration itself. 

Here is an example of assigning default values to input variables in Terraform:

terraform variable "ami" {   type        = string   description = "Ubuntu AMI ID in N. Virginia Region"   default     = "ami-065deacbcaac64cf2" } variable "instance_type" {   type        = string   description = "Instance type"   default     = "t2.micro" } variable "name_tag" {   type        = string   description = "Name of the EC2 instance"   default     = "My EC2 Instance" }

When Terraform applies the configuration with default values, it automatically assumes the default values provided in the variables.

Terraform Output Variables

Output variables in Terraform allow for retrieving specific details about resources created during the apply process. These details can be useful for further processing or to display critical information in the same CLI terminal.

Output variables are defined in the same file where input variables are declared. They can be used to retrieve important information like public IP, instance ID, etc., about the resources created using Terraform.

terraform output "public_ip" { value       = aws_instance.my_vm.public_ip description = "Public IP Address of EC2 instance" } output "instance_id" { value       = description = "Instance ID" }

When Terraform applies the configuration, it displays the values of output variables known after apply. These output variables provide critical information about the resources provisioned using Terraform.

By using various types of variables – local, input, and output – in Terraform, the management of infrastructure becomes more dynamic and flexible. They also help in adhering to the principle of DRY (don't repeat yourself) when creating modules.

Terraform State Management

state management in terraform - terraform tutorial

State files in Terraform are crucial to understanding the status of resources provisioned by Terraform. The terraform.tfstate file maintains a mapping between the resources defined in the configuration and their real-world entities. This mapping is used by Terraform to identify the existing state of resources and determine which resources need to be provisioned or destroyed.

Understanding State Locking in Terraform

State locking is another important concept in Terraform. Terraform creates a file temporarily when executing commands like apply or destroy. This file helps avoid race conditions by ensuring that only one operation is executed at a time.

Safe State Management in Terraform

However, manually editing state files is highly discouraged as it can lead to corruption in resource configuration. Terraform provides commands like terraform state list and terraform state show to query and manipulate state information safely.

Utilizing Remote Backends for State Storage: Enhancing Collaboration and Security

Working with local backend storage for state files presents challenges in a team setting. Version control issues and the risk of data corruption arise when multiple developers are involved in managing Terraform infrastructure.

Enhancing Collaboration with Remote Backends in Terraform

Remote backends offer a solution by securely storing state files independently, avoiding the pitfalls of using local storage. By configuring a remote backend like Amazon S3, developers can work collaboratively on Terraform projects while ensuring consistency and security.

Transitioning to Remote Backends for Improved Security

To transition to a remote backend, developers need to reinitialize Terraform and update the backend configuration in the file. This move not only improves collaboration but also enhances security by isolating sensitive information like credentials and keys from version-controlled repositories.

Streamlining Resource Management with Terraform State Commands

By following best practices and utilizing state file management commands like terraform state rm, teams can streamline resource management and ensure the integrity of their Terraform environments.

Modules and Reusability

A Terraform module is a set of Terraform configuration files in a single directory. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module. So in this sense, every Terraform configuration is part of a module. You may have a simple set of Terraform configuration files such as:

Calling modules

Terraform commands will only directly use the configuration files in one directory, which is usually the current working directory. However, your configuration can use module blocks to call modules in other directories. When Terraform encounters a module block, it loads and processes that module's configuration files. A module that is called by another configuration is sometimes referred to as a "child module" of that configuration.

Local and remote modules

Modules can either be loaded from the local filesystem, or a remote source. Terraform supports a variety of remote sources, including the Terraform Registry, most version control systems, HTTP URLs, and HCP Terraform or Terraform Enterprise private module registries.

Module best practices

In many ways, Terraform modules are similar to the concepts of libraries, packages, or modules found in most programming languages, and provide many of the same benefits. Just like almost any non-trivial computer program, real-world Terraform configurations should almost always use modules to provide the benefits mentioned above.

Advanced Terraform Features

Terraform Cloud is a fantastic tool that allows you to manage your Terraform configurations, state files, and variables all in the cloud. This means you can easily collaborate with team members, manage infrastructure across numerous environments, and automate workflows within your team. 

One of the best features of Terraform Cloud is its remote execution capabilities, which lets you run your configurations on remote servers instead of your local machine. This makes it easier to scale your Terraform pipeline and even run it from automated scripts.

Caution with Terraform Provisioners

Terraform provisioners, which allow you to run scripts or commands on the created resources during deployment, can be an essential part of your Terraform workflow. However, proceed with caution - as they can have side effects, like slowing down your Terraform runs and making your infrastructure harder to manage. 

Plus, keep in mind that using provisioners can make your configurations harder to understand. You could use a provisioner to install software on a machine after it's created, but if you do this, anyone looking at your configuration might not understand where a particular piece of software is coming from.

Related Reading

Best Practices and Common Patterns

students watching terraform tutorial

1. Use Remote State: Best Practice for Collaborative Terraform Deployments

Using a remote shared state location is one of the first best practices you should adopt when working in a team. Having a single remote backend for your state is crucial to avoid conflicts and ensure smooth collaboration. Remote state location should support state locking to prevent multiple people from changing the state simultaneously. 

Treat your state as immutable and avoid manual state changes. Make sure to have backups of your state in case of a disaster. For certain backends like AWS S3, enabling versioning allows for easy state recovery.

2. Leveraging Existing Shared and Community Modules for Efficient Terraform Deployments

Instead of reinventing the wheel, check if there are existing modules for your use case. This saves time and taps into the power of the Terraform community. You can also contribute by improving existing modules or reporting issues. The Terraform Registry is a great resource to discover available modules.

3. Import Existing Infrastructure to Terraform for Better Management

If you have inherited a project with manually created infrastructure, importing existing infrastructure into Terraform can consolidate management and avoid handling infrastructure from multiple endpoints.

4. Avoid Hard-Coding Variables for Flexible Terraform Configurations

Resist the temptation to hardcode values and consider defining them as variables for future changes. Utilize data sources to get attribute values instead of setting them explicitly for enhanced flexibility.

5. Formatting and Validating Terraform Code for Consistency and Error Prevention

Ensure consistent formatting and catch any missed issues by running `terraform fmt` and `terraform validate`. Ideally, automate this using CI/CD pipelines or pre-commit hooks for code quality.

6. Consistent Naming Conventions for Readable Terraform Code

Follow a consistent naming convention with lowercase letters and underscores as separators. Avoid repeating the resource type in the resource name and use singular nouns for single-value variables and outputs. Use plural nouns for lists or maps and include descriptive names with descriptions for variables and outputs.

7. Tagging Resources for Easy Identification and Management

Implement a robust and consistent tagging strategy to assist in issue resolution and cost management. Tag resources with Terraform arguments as the last argument to ensure clear labeling.

8. Introducing Policy as Code for Secure and Automated Rules Implementation

Establish policies to maintain operational and security standards as your teams and infrastructure scale. Policy as Code allows for defining rules at scale and automatic rule verification. Tools like Spacelift with Open Policy Agent (OPA) can help enforce these rules.

9. Implementing a Secrets Management Strategy for Secure Terraform Deployments

Define a strategy for handling secrets securely, avoiding storing secrets in plaintext in version control systems. Use techniques like setting environment variables with TF_VAR and marking sensitive variables with sensitive = true for better secret management. Consider using secret stores like Hashicorp Vault or AWS Secrets Manager for enhanced security features like rotation and audit logs.

10. Testing Terraform Code for Error-Free Deployments

Test IaC code properly using tools like `terraform plan` for quick verification, static analysis for identifying potential issues without applying changes, and unit testing for normal operation. 

Integrate Terraform linters into CI/CD pipelines to enforce best practices and catch errors early in the development process. Consider setting up integration tests for thorough verification before applying changes to production.

11. Enabling Debugging and Troubleshooting for Quick Issue Resolution

Set Terraform log level to debug for efficient gathering of necessary information to resolve issues quickly. Persist logs in a file using TF_LOG_PATH environment variable for reference. Debug issues effectively for smoother troubleshooting.

12. Building Modules for Reusability and Scalability in Terraform Deployments

Create custom modules when there are no existing community modules for your use case. Building modules from the start allows for adding features as your infrastructure matures and aids in replicating code across different environments effortlessly.

13. Using Loops, Conditionals, and Functions for Flexibility in Terraform Configurations

Utilize count or for_each for resources that may change between environments. Incorporating conditionals and functions in your code enhances genericity and flexibility in your parameters, facilitating varied use cases.

14. Harnessing Dynamic Blocks for Simplified Resource Management

Dynamic Blocks streamline resource management by allowing flexibility in resource configuration. Ensure simplicity in adding new rules without altering the configuration.

15. Employing Terraform Workspaces for Environment Management

Utilize Terraform's built-in workspaces to reuse configurations across different environments, even without sophisticated workflow tools. Workspaces aid in managing environments efficiently.

16. Implementing the Lifecycle Block for Resource Management Optimization

Utilize the lifecycle block for sophisticated conditions in your code to prevent unwanted changes and ensure resource recreation without downtime.

17. Utilizing Variables Validations for Precise Input Handling

Leverage variable validations within Terraform variables for precise input handling. Set conditions and error messages to enforce restrictions and maintain data integrity.

18. Optimize Terraform Configurations with Variables Validations

Utilize variable validations within Terraform variables to ensure correct inputs and enforce restrictions. Incorporate conditions and error messages to maintain data integrity and protect against errors.

19. Adopting Helper Tools for Enhanced Terraform Workflow

Explore tools like tflint, tfenv, checkov, terratest, pre-commit-terraform, terraform-docs, spacelift, and others to streamline your Terraform workflow. Choose tools based on your needs to enhance your Terraform experience.

20. Enhancing Development with IDE Extensions for Efficient Coding

Leverage IDE extensions like those available in Visual Studio Code to speed up development and ensure correct code formatting while writing Terraform configurations. Incorporate extensions to enhance efficiency and code quality.

Zeet Contact Us

Have Successful Releases Every Time With Zeet's CI/CD & Deployment Platform for Kubernetes and Terraform

Zeet helps you to get more from your cloud, Kubernetes, and Terraform investments and helps your engineering team become strong individual contributors through our CI/CD & deployment platform. 

Contact Zeet to learn more about how Zeet help you get seamless cloud deployments every time, and helps your team to become a top-performing engineering team.

Subscribe to Changelog newsletter

Jack from the Zeet team shares DevOps & SRE learnings, top articles, and new Zeet features in a twice-a-month newsletter.

Thank you!

Your submission has been processed
Oops! Something went wrong while submitting the form.