Getty Images

Dive into Terraform basics with this tutorial

Terraform can save you time and headaches when deploying servers with cloud providers. Get up to speed on Terraform basics in this tutorial.

Terraform is a powerful tool for managing infrastructure as code. It can work for organizations that are just starting out with cloud adoption as well as those that already use cloud providers.

Terraform can manage a variety of resources. In most cases, if there is a software service your organization uses, you can manage it with Terraform. For example, Terraform can manage GitHub configuration as well as your PostgreSQL database.

It's important to understand the downsides and benefits as well as how to deploy a server using Terraform so you can make an informed decision about whether Terraform is right for your organization.

Drawbacks

With Terraform, updates to resources under management are not as quick as they would be if you manually updated the resources. If your organization requires regular immediate updates, Terraform will certainly slow those down.

Terraform can be difficult to work with if you often manually update resources under management because you must also make those updates again in the Terraform configuration files. You must perform a Terraform "refresh" to update the state of the resources under management.

This increase in complexity is worth considering. In simpler infrastructures, you might find that the duplication of work is untenable because it might take longer to configure Terraform than it would to deploy the resources manually.

Benefits

When you have resources stored in Terraform code that lives in version control, it creates an automatic changelog of all infrastructure updates. If a Terraform update is bad, revert the recent changes using the version control system and reapply the prior functioning Terraform configuration. Mistakes that can happen from human error are much less likely when changes are written out in code and teams can review before they apply them.

Another benefit of Terraform is ease of deploying new services. Terraform makes it simple to modify or deploy new services because you can reuse the code of existing services.

How to use Terraform to deploy a server

Terraform uses files written in HashiCorp configuration language to manage cloud resources. Terraform uses TF files that usually follow a similar naming convention across projects. A main.tf file contains the configuration of resources Terraform manages. A providers.tf file contains definitions to allow Terraform to connect with the providers of the resources under management.

For example, when you use Terraform to manage resources on AWS, the provider.tf file contains an AWS provider block. This specifies options for using the provider, such as the region where resources will be deployed.

Use a variables.tf file to define variables to create more flexible configurations. These variables are then referenced by resources and can be provided via various methods while running Terraform. An output.tf file contains references to resource values that will be returned after Terraform runs successfully. The names of files in Terraform projects must not match the files that will be returned, although it is a well-accepted standard and most Terraform projects follow this pattern.

Here's what a Terraform file to deploy an Ubuntu server looks like.

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

data "aws_ami" "ubuntu" {
 most_recent = true

 filter {
   name   = "name"
   values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
 }

 filter {
   name   = "virtualization-type"
   values = ["hvm"]
 }

 owners = ["099720109477"] # Canonical
}

data "http" "myip" {
 url = "https://ipv4.icanhazip.com"
}

resource "aws_instance" "example" {
 ami           = data.aws_ami.ubuntu.id
 instance_type = "t2.micro"

 vpc_security_group_ids = [aws_security_group.web_server_sg_tf.id]
 user_data              = <<-EOF
           #!/bin/bash
           sudo apt-get update
           sudo apt-get install -y nginx
           sudo systemctl start nginx
           sudo systemctl enable nginx
           EOF

 tags = {
   Name = "ExampleInstance"
 }
}

resource "aws_security_group" "web_server_sg_tf" {
 name        = "web-server-sg-tf"
 description = "Allow HTTP to web server from my IP"

 ingress {
   from_port   = 80
   to_port     = 80
   protocol    = "tcp"
   cidr_blocks = ["${chomp(data.http.myip.response_body)}/32"]
 }

 ingress {
   from_port   = 22
   to_port     = 22
   protocol    = "tcp"
   cidr_blocks = ["${chomp(data.http.myip.response_body)}/32"]
 }

 egress {
   from_port   = 0
   to_port     = 0
   protocol    = "-1"
   cidr_blocks = ["0.0.0.0/0"]
 }
}

output "instance_public_ip" {
 value = aws_instance.example.public_ip

For the purposes of this example, the output block and provider block are in the same file. Normally, these would live in their own output.tf and provider.tf file, which follows Terraform best practices.

The AWS provider block specifies that AWS resources are in use and that the resources will deploy in the us-east-1 region. The aws_ami data block will reach out to AWS and find the latest Amazon Machine Images (AMI) for the parameters set. The set parameters will return an Ubuntu AMI. This is an image that AWS maintains and Ubuntu uses to run on an AWS server. The next block is a data block that returns the local IP address. The data block will be used in the security group that will be attached to our AWS instance.

Resource block

The first resource block is responsible for creating an actual cloud resource. In this example, the resource is aws_instance which refers to a server that gets created in AWS. Set the security group of the instance to the id of the aws_security_group that is created later in the file, using the vpc_security_group_ids attribute of the aws_instance.

The user_data attribute lets you provide a script that will run when the instance starts. The script installs and runs Nginx. Nginx a web server that will serve as the default page where you can see that the server is properly deployed. An aws_security_group resource block specifies ingress rules that allow only your local IP to access the server over HTTP and SSH. The egress rule allows the server unrestricted access to the outside network. Finally, the output block named instance_public_ip returns the public IP of the aws_instance resource specified earlier in the file.

To deploy the resources, ensure Terraform is installed and run the terraform apply command. HashiCorp provides instructions to install Terraform. Make sure to satisfy the prerequisites to deploy resources using AWS.

When you execute the apply command, Terraform will show the resources that it will create. From there, it will either confirm or cancel the execution of the apply command. When you run the terraform apply command, it will look like the following example.

Terraform will generate the code.

After entering yes, Terraform will create the resources and output the progress of each resource.

Terraform will perform the actions written in code.

Terraform also returns the outputs, where you can find the public IP address of the instance that Terraform creates. If you visit this instance, you can see the default Nginx page, which shows the server is properly deployed.

Nginx web server has been successfully installed.

To remove the resources, run terraform destroy and confirm that the resources should be destroyed.

Matthew Grasberger is a DevOps engineer at Imperfect Foods. He has experience in test automation, DevOps engineering, security automation and open source mobile testing frameworks.

Next Steps

HCL vs. JSON: Configuration language uses, pros and cons

Dig Deeper on IT systems management and monitoring