---
title: "Ensuring Success by Learning Terraform Best Practices"
description: "Discover Terraform best practices and ensure that your DevOps environment is being utilized safely and securely to it’s fullest potential!"
canonical: "https://adamtheautomator.com/terraform-best-practices/"
---

# Ensuring Success by Learning Terraform Best Practices

> Discover Terraform best practices and ensure that your DevOps environment is being utilized safely and securely to it’s fullest potential!

Source: https://adamtheautomator.com/terraform-best-practices/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Ensuring Success by Learning Terraform Best Practices](https://adamtheautomator.com/wp-content/uploads/2023/02/terraform-best-practices.jpg)

# Ensuring Success by Learning Terraform Best Practices

[![](https://secure.gravatar.com/avatar/2beb65fca997135120ed98dc6a2e57dcdf1a7d7d2f5ff687b5d91dc7ccd7a6b5?s=192&d=mm&r=g)Sagar](https://adamtheautomator.com/author/shanky-mendiratta/)22 February 20237 min. read

Categories: [DevOps](/category/devops/)

Tags:[Terraform](/tag/terraform/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [Launching an AWS EC2 Instance with Terraform Best Practices](#launching-an-aws-ec2-instance-with-terraform-best-practices)
*   [Using Comments to Save Time Later](#using-comments-to-save-time-later)
*   [Controlling Terraform Operations with Lifecycle Arguments](#controlling-terraform-operations-with-lifecycle-arguments)
*   [Tagging a Terraform Workspace](#tagging-a-terraform-workspace)
*   [Building a Variable and Provider Configuration](#building-a-variable-and-provider-configuration)
*   [Running Terraform to Create an AWS EC2 instance](#running-terraform-to-create-an-aws-ec2-instance)
*   [Conclusion](#conclusion)

Terraform configuration management, in any environment, has its share of difficulties. But worry not. This tutorial has got you covered with some Terraform best practices to ensure successful deployments.

In this tutorial, you will launch an AWS EC2 instance while learning some of the best practices that allow you to securely and successfully manage your large infrastructure.

Sounds promising? Stay tuned and up your deployment skills with Terraform!

## Prerequisites

If you’d like to follow along in this tutorial, ensure you have the following in place:

An [Amazon Web Service account (AWS)](https://repost.aws/knowledge-center/create-and-activate-aws-account).

*   An IAM user with an [access key ID and secret key **set up on your local machine**](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html).

Related:[Helpful Guide to IAM in AWS Through Examples](https://adamtheautomator.com/iam-aws/)

*   Terraform installed – This tutorial uses [Terraform v1.36](https://releases.hashicorp.com/terraform/1.3.6/).

Related:[How to Install Terraform on Windows](https://adamtheautomator.com/terraform-windows/)

*   An Ubuntu machine – This tutorial uses Ubuntu 22.04.5 LTS, but other operating systems with Terraform will work.

Related:[How to Install Ubuntu 20.04 \[Step-by-Step\]](https://adamtheautomator.com/install-ubuntu/)

*   A code editor – You can use any text editor to work with Terraform configuration files. But one that understands the HCL Terraform language, like [Visual Studio (VS) Code](https://code.visualstudio.com/), would be great.

Related:[What You Need to Know about Visual Studio Code: A Tutorial](https://adamtheautomator.com/visual-studio-code-tutorial/)

## Launching an AWS EC2 Instance with Terraform Best Practices

The AWS cloud has dozens of services, from computing, storage, networking, and more. Each of these services can communicate like an on-prem data center’s services. But, one of the most important services is the AWS EC2 instance.

In this tutorial, you will configure the Terraform files with best practices, such as using Lifecycle, workspace, variables, etc.

### Using Comments to Save Time Later

Regardless of your familiarity with your Terraform configurations, using comments undoubtedly comes in handy. Besides making your configuration more comprehensive, comments also let you save time.

For example, you can comment out a line of command, which you can uncomment after testing the rest of the configuration.

Related:[How to Create Descriptive PowerShell Comments](https://adamtheautomator.com/powershell-comment/)

To see how comments work, you will build a Terraform configuration file with the following:

Open your terminal and run the commands below, which do not provide output. Create a directory (`mkdir`) in your home directory and switch (`cd`) to that directory. This directory stores your Terraform configuration files. In this tutorial, the directory is called _`~/terraform-count-demo`_ but can be named differently.

```bash
mkdir ~/terraform-count-demo
cd ~/terraform-count-demo
```

Next, open your favorite code editor, populate the configuration below, and save it as _main.tf_ inside the _~/terraform-count-demo_ directory. The _main.tf_ file contains the main set of your Terraform configuration, along with descriptive comments.

There are three different comment styles in a Terraform configuration file, as follows:

| Comment Style | Function |
| --- | --- |
| # | Single-line comment style is the default and should be used in most cases. |
| // | An alternative to the # character, which also makes a single-line comment. |
| /\* and \*/ | Start and end delimiters, which allow you to make multiple-line comments. |

> 💡 _Note that double-forward slashes (`//`) comment styles may automatically be transformed by configuration formatting tools to default single comment style (`#`). This behavior transpires since the double-forward slashes style is not idiomatic._

Below, the three comment styles are used to make the configuration more comprehensive.

```json
resource "aws_instance" "my-machine" {
  # count and for_each cannot be used together
  count = 4 // Allows creation of four similar EC2 instances.
  
  # Set the virtual image to create a VM within an EC2 instance.
  ami = "ami-0742a572c2ce45ebf" 

  /* Set the instance type of the workspace, either t2.medium or t2.micro,
  a separate instance of state data inside the Terraform directory */
  instance_type = terraform.workspace == "prod" ? "t2.medium": "t2.micro"
  # Set the availability zone
  availability_zones = var.availability_zones 
}
```

### Controlling Terraform Operations with Lifecycle Arguments

Terraform works great in defining cloud and on-prem resources (human-readable), but you still need a way to control Terraform operations. How? Lifecycle arguments let you create custom rules for resource creation and destruction.

Declaring lifecycle arguments is a game-changer when you want to minimize potential downtime and protect resources from change or impacting infrastructure.

Add the following configuration inside the `resource` code block in your _main.tf_ file, which declares the lifecycle arguments. Terraform lifecycle defines the behavior of resources of how they should be treated, such as ignoring changes to tags and preventing destroying the infrastructure.

Below are three main arguments declared within the Terraform lifecycle.

| Lifecycle Argument | Function |
| --- | --- |
| [create\_before\_destroy](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#create_before_destroy) | Allows you to create the resource first before destroying a resource. This is the default option. |
| [prevent\_destroy](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#prevent_destroy) | Terraform skips the destruction of the existing resource. |
| [ignores-changes](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes) | Tells Terraform to ignore the changes. This is a list of attribute names, such as tags. |
| [replace\_triggered\_by](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#replace_triggered_by) | Replaces the resource when any of the options change. This is a list of attribute names such as aws\_instance, which when replaced trigger the resource to be replaced as well. |

But as you can see below, two of the three arguments are single-line comments.

```json
  # Declare lifecycle arguments
  lifecycle {
      create_before_destroy = true
    # prevent_destroy = true
    # ignore_changes = [ tags, ]
    # replace_triggered_by = [ aws_instance.id, ]
  }
```

### Tagging a Terraform Workspace

If you are building a huge infrastructure with Terraform, considering multiple **[Terraform Workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)** is crucial. A Terraform workspace provides a separate virtual space to store your persistent data. Before building rock-solid resources, Terraform developers need multiple workspaces to test the same scripts and code.

> 💡 _By default, Terraform has one workspace named default that you cannot delete. Also note that not all backends support workspaces._

Related:[Demonstrating Unique Instances with Terraform Workspace](https://adamtheautomator.com/terraform-workspace/)

Add the configuration of the following `tag` right below the `lifecycle` block in your _[main.tf](http://main.tf)_ file. This configuration tags the instance according to the workspace you wish to launch in.

```json
  tags = {
    # Tags the instance according to the workspace to launch in.
    Name = "my-machine - ${terraform.workspace}-${count.index}"
  }
```

Once added, your full _main.tf_ configuration should look like the one below.

```json
resource "aws_instance" "my-machine" {
  # count and for_each cannot be used together.
  count = 4 // Allows creation of four similar EC2 instances.
  
  ami = "ami-0742a572c2ce45ebf"

  /* Set the instance type of the workspace, either t2.medium or t2.micro,
  a separate instance of state data inside the Terraform directory */
  instance_type = terraform.workspace == "prod" ? "t2.medium": "t2.micro"
  availability_zones = var.availability_zones
  
  # Declare lifecycle arguments.
  lifecycle {
		create_before_destroy = true
		# prevent_destroy = true
    # ignore_changes = [ tags, ]
    # replace_triggered_by = [ aws_instance.id, ]
  }

  # Tags the instance according to the workspace to launch in.
  tags = {
    Name = "my-machine - ${terraform.workspace}-${count.index}"
  }
}
```

## Building a Variable and Provider Configuration

[Variables](https://adamtheautomator.com/ubuntu-environment-variables/) in Terraform are also known as input variables or function arguments. You can set the values of these variables using CLI or environment variables.

Related:[How To Wrangle Ubuntu Environment Variables](https://adamtheautomator.com/ubuntu-environment-variables/)

Create a new file inside the _~/terraform-count-demo_ directory, name it _vars.tf,_ and add the code below. The _vars.tf_ file is a [Terraform variables file](https://developer.hashicorp.com/terraform/language/values/variables) containing all the variables the configuration file references.

In the below code, the variable named `availability_zones` is of type `list(string)`, and the `us-east-1a` and `us-east-1a` are the default values.

```json
variable "availability_zones" {
    type = list(string)
    default = ["us-east-1a","us-east-1b"]
}
```

> 💡 _You can also run the following `export` command to declare the environment variables before running the `terraform plan` and `terraform apply` commands: `export TF_VAR_availability_zones=["us-east-1a","us-east-1b"]`_

> 💡 _Another way to consume variables is by using the below command: `terraform plan -var 'availability_zones=["us-east-1a","us-east-1b"]'`_

Now, create one more file called _provider.tf_, and populate the following code, which defines the AWS provider (`aws`) with the `region` set to `us-east-1`.

The _provider.tf_ file contains the [Terraform backend](https://developer.hashicorp.com/terraform/language/settings/backends/configuration) where the Terraform state file will reside. The Terraform state file contains all resource details and tracking, which were or will be provisioned with Terraform.

There are two types of Terraform backend, as follows:

*   **Local backend** – Resides where you run Terraform, a Linux machine, a Windows machine, or wherever you run Terraform from.
*   **Remote backend** – A SAAS-based URL or storage location, such as an AWS S3 bucket.

The `source` within the Terraform provider contains the following components:

*   **Hostname** – The hostname of the Terraform registry that distributes the provider. The default hostname is [`registry.terraform.io`](https://registry.terraform.io/).
*   **Namespace** – An organizational [namespace](https://docs.aws.amazon.com/cloud-map/latest/dg/working-with-namespaces.html) within the specified [registry](https://aws.amazon.com/ecr/), like Hashicorp or partner.
*   **Type** – A type is a short name you provide for the platform or system the provider manages, which must be unique.

```json
terraform {
   # Declare the source parameter in Terraform 0.13 and later versions.
   required_providers {
     aws = {
        # Sets the source address where Terraform can download plugins
        source = "hashicorp/aws"  # The syntax is <hostname>/<namespace>/<type>
                                  # hostname like registery.terraform.io 
                                  # registery.terraform.io/hashicorp/aws commonly known as hashicorp/aws

        # Declaring the version of AWS provider as 4.35.0
        # Installs the relevant dependencies and plugins
        version = "4.35.0"
     }
   }
}

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

# Local Backend
# Whenever a statefile is created or updated, it is stored in the local machine.
 
terraform {
  backend "local" {
    path = "relative/path/to/terraform.tfstate"
  }
}
 
# Configuring Terraform to use the remote terraform backend s3.
# Whenever a statefile is created or updated, it is stored in the AWS S3 bucket. 
 
terraform {
  backend "s3" {
    bucket = "mybucket"
    key    = "path/to/my/key"
    region = "us-east-2"
  }
}
```

## Running Terraform to Create an AWS EC2 instance

With your Terraform configuration and variables files ready, it is time to initiate Terraform and create the EC2 instances.

To provision, a Terraform configuration, Terraform typically uses a three-stage approach [`terraform init`](https://developer.hashicorp.com/terraform/cli/commands/init) → [`terraform plan`](https://developer.hashicorp.com/terraform/cli/commands/plan) → [`terraform apply`](https://developer.hashicorp.com/terraform/cli/commands/apply).

1\. Run the below command to change the working directory to the _~\\terraform-count-demo_ directory.

```bash
~\terraform-count-demo
```

2\. Run the `terraform init` command in the _~\\terraform-count-demo_ directory to initialize the plugins and providers required to work with resources.

```bash
terraform init
```

If all goes well, you should see the message `Terraform has been successfully initialized` in the output, as shown below.

![Initiating Terraform](https://adamtheautomator.com/wp-content/uploads/2023/02/image-171.png)

Initiating Terraform

3\. Once initiated, run the below `terraform plan` command, an optional yet recommended action to ensure your configuration’s syntax is correct. This command gives you an overview of which resources will be provisioned in your infrastructure.

```bash
terraform plan
```

If successful, you will see a message like the one below, which summarizes the plan of which resources will be provisioned.

![Viewing which resources will be provisioned](https://adamtheautomator.com/wp-content/uploads/2023/02/image-172.png)

Viewing which resources will be provisioned

4\. Run the following `terraform apply` command to tell Terraform to provision the AWS EC2 instances. Terraform reads the configuration (_main.tf_) and the other files to compile a configuration.

```javascript
terraform apply
```

![terraform best practices - Provisioning the AWS EC2 instances](https://adamtheautomator.com/wp-content/uploads/2023/02/image-173.png)

Provisioning the AWS EC2 instances

5\. Finally, open your favorite web browser, and log on to the [AWS Management Console](https://aws.amazon.com/console/) to verify the machines. On the EC2 page, you will see all four newly-created EC2 instances, as shown below.

![Verifying the machines in the AWS Management Console](https://adamtheautomator.com/wp-content/uploads/2023/02/image-174.png)

Verifying the machines in the AWS Management Console

## Conclusion

Terraform offers consistent workflow, letting you provision and manage infrastructures throughout its lifecycle. And in this tutorial, you have learned to ensure success with your workflow in Terraform with best practices.

You can confidently secure your Terraform state with Terraform backends, local, and remote backends (AWS S3).

With this newfound knowledge, why not try storing the states of other AWS services with Terraform backends? Or perhaps [migrate the state from S3 to Terraform Cloud](https://developer.hashicorp.com/terraform/tutorials/cloud/migrate-remote-s3-backend-tfc)?

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fterraform-best-practices%2F&text=Ensuring%20Success%20by%20Learning%20Terraform%20Best%20Practices)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fterraform-best-practices%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fterraform-best-practices%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2022/08/Which-Tool-Terraform-vs-Cloudformation-in-the-Fight-for-AWS.jpg)

### [Which Tool? Terraform vs. Cloudformation in the Fight for AWS](/terraform-vs-cloudformation/)

Learn which tool, Terraform vs Cloudformation is right for infrastructure as configuration with AWS in this ATA Learning tutorial!

![](https://adamtheautomator.com/wp-content/uploads/2022/07/A-Definitive-Guide-to-Leveraging-the-AWS-Terraform-IAM-Role.jpg)

### [A Definitive Guide to Leveraging the AWS Terraform IAM Role](/terraform-iam-role/)

Discover this definitive guide to the AWS Terraform IAM role and take your devops game to the next level in this ATA Learning tutorial.

![](https://adamtheautomator.com/wp-content/uploads/2022/06/Automate-Tasks-With-Terraform-Docker-Integration-.jpg)

### [Automate Tasks With Terraform Docker Integration](/terraform-docker/)

Empower your infrastructure with this Terraform Docker tutorial and integrate these two popular technologies into one!

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
