What I've Learned Learning Terraform: Part 2
Tags: iac, terraform, devops, tutorial
Published: 2020-08-13 19:08:56

### Terraform Series

- [Part 1: Introduction](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-1-4en4)
- Part 2: Creating the Server
- [Part 3: Provisioning the Server](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-3-2e32)
- [Part 4: Managing Terraform State](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-4-np4)
- [Part 5: Cleaner Code with Terraform Modules](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-5-j4b)
- [Part 6: Loops with Terraform](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-6-id0)
- [Part 7: Conditionals with Terraform](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-7-4ae7)
- [Part 8: Testing Terraform Code](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-8-1328)

-----

# Choosing a Provider

Terraform is using HashiCorp Configuration Language (HCL). Although HCL is unifying how Terraform should be coded, different providers allow you to achieve different goals with different scopes. That's why it's not the same to create a server with AWS provider and GCP provider (although similar).

I have a few resources I use to learn and practice Terraform. One of them is the book Terraform: Up & Running: Writing Infrastructure as Code by Yevgeniy Brikman. It's a beautiful book in terms of how simple it goes through the basics. All examples are for AWS. My day-to-day job, on the other hand, requires me to work with GCP. That's why I chose to practice with something different which is also my favorite cloud provider: [DigitalOcean](https://m.do.co/c/4916561afc69). :-)

You can use my referral link to get $100 DigitalOcean credits: https://m.do.co/c/4916561afc69. It is more than enough to run through all practices in this series several times.

![DigitalOcean is a budget cloud platform for start-ups https://medium.com/brainstation23/reduce-cost-in-digital-ocean-cloud-for-startups-e6855e895c6e](https://dev-to-uploads.s3.amazonaws.com/i/jm9p5fzmfmpu9mfij5u7.jpg)

Why DigitalOcean? Because it's not as big and as complex as AWS or GCP. I love how DigitalOcean focuses on a limited set of assets like servers, managed DBs, and spaces. If you're not building for an enterprise, DigitalOcean provides more than enough with excellent UX.

# Creating a Server aka Droplet

We are going to create a droplet, and then configure it step by step. First, create a `main.tf` file and put the content below:

```tf
terraform {
  required_providers {
    digitalocean = {
      source  = "digitalocean/digitalocean"
      version = "1.22.1"
    }
  }
}
```

1.22.1 is the latest version of the DigitalOcean provider at the time of this writing. You can check the [registry](https://registry.terraform.io/providers/digitalocean/digitalocean) to find the newest version.

Next, we are going to create a resource to declare the droplet. In the same `main.tf` file, add this to the bottom:

```tf
resource "digitalocean_droplet" "web" {
  image  = "ubuntu-20-04-x64"
  name   = "terraform-sandbox"
  region = "ams3"
  size   = "s-1vcpu-1gb"
}
```

Here the name `digitalocean_droplet` identifies the resource as defined by the provider. `web`, on the other hand, is a name given by us to use this resource within Terraform later. Let me also list the configuration parameters below:

- `image`: The OS image.
- `name`: The server's name.
- `region`: The datacenter's region. You can check [Regional Availability Matrix](https://www.digitalocean.com/docs/platform/availability-matrix/) to find yourself a suitable region.
- `size`: The server type DigitalOcean provides. You can check [the list of size slugs](https://developers.digitalocean.com/documentation/changelog/api-v2/new-size-slugs-for-droplet-plan-changes/).

Image and size options are available via DO's API, but we'll talk about them later on. The example values given above are enough to continue our demo.

The code inside the `main.tf` file is sufficient to create a droplet. Now let's head to the terminal and run the commands below from the directory the `main.tf` file resides.

## Export your DigitalOcean access token as env

There are [multiple ways to provide your access token to Terraform](https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs#DIGITALOCEAN_ACCESS_TOKEN) so that it can communicate with the provider using its API. For the sake of simplicity, we are going to export it on the command line, and Terraform will pick it up as long as we keep that command-line session open.

```
export DIGITALOCEAN_ACCESS_TOKEN=cbb3b23bf9281232bd7cc60d0b281f1483d82b45cd067e4ca8a401cbbf44df3e
```

The access token above is fake, of course. You need to visit [the API page](https://cloud.digitalocean.com/account/api) on your DigitalOcean account to create one.

## Initialize Terraform

Terraform has hundreds of providers, and those providers don't come out of the package. By initializing, Terraform prepares your working directory and installs the required provider plugins. You need to rerun this command whenever you set or change modules or backend configuration for Terraform.

```bash
$ terraform init
```

The above command will do what I described above and return a long success message which eventually comes down to this:

> Terraform has been successfully initialized!

## Plan the changes

Terraform has a very nice feature where you can audit the changes it will make before applying anything.

```bash
$ terraform plan
```

The above command will generate an execution plan and show it to you. In our case, it's going to look something like this:

```
Terraform will perform the following actions:

  # digitalocean_droplet.web will be created
  + resource "digitalocean_droplet" "web" {
      + backups              = false
      + created_at           = (known after apply)
      + disk                 = (known after apply)
      + id                   = (known after apply)
      + image                = "ubuntu-20-04-x64"
      + ipv4_address         = (known after apply)
      + ipv4_address_private = (known after apply)
      + ipv6                 = false
      + ipv6_address         = (known after apply)
      + ipv6_address_private = (known after apply)
      + locked               = (known after apply)
      + memory               = (known after apply)
      + monitoring           = false
      + name                 = "terraform-sandbox"
      + price_hourly         = (known after apply)
      + price_monthly        = (known after apply)
      + private_networking   = (known after apply)
      + region               = "ams3"
      + resize_disk          = true
      + size                 = "s-1vcpu-1gb"
      + status               = (known after apply)
      + urn                  = (known after apply)
      + vcpus                = (known after apply)
      + volume_ids           = (known after apply)
      + vpc_uuid             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
```

You can already see the configuration values we've provided in the plan.

## Apply the execution plan

Our final step to create the server is to apply the plan. You can ignore the `terraform plan` command after some time because Terraform is going to require your approval one more time at this step.

```bash
$ terraform apply
```

This command will show you the execution plan we've been shown above and ask you to approve:

```
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
```

When you enter *yes*, it's going to go ahead and create your droplet:

```
  Enter a value: yes

digitalocean_droplet.web: Creating...
digitalocean_droplet.web: Still creating... [10s elapsed]
digitalocean_droplet.web: Still creating... [20s elapsed]
digitalocean_droplet.web: Still creating... [30s elapsed]
digitalocean_droplet.web: Creation complete after 34s [id=111111111]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

Now you can go ahead and check your newly created droplet on your account:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ltm33vnt2rf380dapbax.png)

PS: Cover photo by [Aron Visuals](https://unsplash.com/@aronvisuals?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)

-----

[Part 1](http://dev.to/gzg/what-i-ve-learned-learning-terraform-part-1-4en4)..........................................................................................................[Part 3](https://dev.to/gzg/what-i-ve-learned-learning-terraform-part-3-2e32)