Terraform - setting up domain DNS with cloudflare
Tags: cloudflare, terraform, devops
Published: 2020-02-17 08:16:19

---
title: Terraform - setting up domain DNS with cloudflare
published: true
date: 2020-02-17 00:00:00 UTC
tags: cloudflare,terraform,devops
canonical_url: https://owendavies.net/articles/terraform-setting-domain-dns-with-cloudflare/
---

I need to verify my domain name with google to confirm that I own it. To do that I need to create a TXT record in the DNS, which is currently hosted in Cloudflare. I’ve been wanting to get my Cloudflare DNS into Terraform for a while, so in this article we’re going to import my existing DNS settings into the Terraform state file, and then add a new TXT record to verify with google.

<!--more-->

If you need to install Terraform check out my article on [Getting Started with Terraform](https://owendavies.net/articles/getting-started-with-terraform).

# Our plan today

1. Setup our new Terraform file
2. Get our Cloudflare API key
3. (Optional) Import our already existing DNS configuration from Cloudflare
4. Create our DNS resources in our Terraform file
5. Run our Terraform DNS configuration

# 1. Setup our new Terraform file

## Create our new Terraform file in a new project directory

```
mkdir cloudflare-terraform
cd cloudflare-terraform
touch main.tf

```

## Add the cloudflare provider to our terraform file

```
provider "cloudflare" {
  version = "~> 2.0"
  email = "you@example.com"
  api_key = "your-api-key"
}

```

## Run terraform init

Run terraform init to setup the folder and download the providers declared in our main.tf terraform file.

```
terraform init

```

![terraform init output](https://owendavies.net/assets/images/terraform-cloudflare-dns/terraform-init.png)

We can see that terraform has pulled down version 2.3 of the cloudflare provider.

# 2. Get our Cloudflare Global API key

1. Login to Cloudflare with your credentials
2. Click on My Profile at the top right
3. Click on the 3rd tab “API Tokens”
4. Click on View next to Global API Key
5. Type in your password again to confirm it’s you
6. Copy your API Key and store it somewhere super safe. Don’t give this to anyone that you don’t want to be able to access and modify your DNS.
7. Add the generated token to your main.tf file.

# 3. (Optional) Import our already existing DNS configuration from Cloudflare

## 1. Add the Zone to our Terraform file

Let’s query the Cloudflare API to get the Zone ID of the domain that we want to import the DNS records for. By querying **https://api.cloudflare.com/client/v4/zones/** it will output all zones information.

```
curl -X GET "https://api.cloudflare.com/client/v4/zones/" -H "X-Auth-Key:YOUR_API_KEY" -H "X-Auth-Email:you@example.com" -H "Content-Type:application/json" | jq .

```

Find the domain (zone) that you want to import and copy the ID value, this is what we will use to import in to the state file.

## 2. Create a Zone entry in our Terraform file

Create a new resource with the type **cloudflare\_zone** and name it something appropriate.

Mine looks like this:

```
resource "cloudflare_zone" "owendavies-net" {
 zone= "owendavies.net"
}

```

## 3. Import the zone in to the Terraform state file so that it knows about it.

Run the following command, replacing ZONE\_ID with the ID that you copied in the first step.

```
terraform import cloudflare_zone.owendavies-net ZONE_ID

```

## 4. Check the Terraform file is correct

Now let’s run **terraform plan** and look at the output, if it complains and says that it’s going to make a change, that means that the **cloudflare\_zone** resource you created in your terraform file is different to what terraform imported into the state file, it will tell you what changes there are, modify the resource until it says there are no changes to make when you run **terraform plan**.

```
terraform plan

```

## 5. Get DNS records from Cloudflare API

Run the following curl command replacing the YOUR\_ZONE\_ID and YOUR\_API\_KEY and email address.

```
curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records" -H "X-Auth-Key:YOUR_API_KEY" -H "X-Auth-Email:you@example.com" -H "Content-Type:application/json" | jq . | tee importedcloudflare.json

```

This will query the Cloudflare api and return all the DNS records for the ZONE\_ID that you specify, it will format it into JSON and save it to **importedcloudflare.json**

## 6. Create Terraform resource to match the above output

Open up the _importedcloudflare.json_ file and create a new cloudflare\_record resource matching the values in the **importedcloudflare.json** file.

When you have created the resource, find the id value in the _importedcloudflare.json_ file.

## 7. Import the resource

Run the following command (replacing the ZONE\_ID & DNS\_RECORD\_ID with your IDs) to import the resource into the terraform state file.

```
terraform import cloudflare_record.www-owendavies-net ZONE_ID/DNS_RECORD_ID

```

## 8. Test to see if the file matches the state

Run _terraform plan_ which will show you what changes will be run (the differences between you state file and the main.tf file).

Make sure it says there are “No changes”, if there are any changes that it makes, go back and edit your resource in your main.tf file and try again.

```
terraform plan

```

## My final terraform file:

In my case I have 2 CNAME records as well as the cloudflare zone itself (the domain).

```
provider "cloudflare" {
  version = "~> 2.0"
  email = "you@example.com"
  api_key = "your-api-key"
}

resource "cloudflare_zone" "owendavies-net" {
 zone= "owendavies.net"
}

resource "cloudflare_record" "owendavies-net" {
  zone_id = "ZONE_ID"
  name = "owendavies.net"
  value = "owen-davies.github.io"
  type = "CNAME"
  proxied = true
  ttl = 1
}

resource "cloudflare_record" "www-owendavies-net" {
  zone_id = "ZONE_ID"
  name = "www"
  value = "owen-davies.github.io"
  type = "CNAME"
  proxied = true
  ttl = 1
}

```

Now when I run _terraform plan_ it says there are no changes to be applied

# 4. Create our DNS file in Terraform

## Add a Cloudflare Zone resource

If you didn’t already do this during the (optional) import, you will need a **cloudflare\_zone** resource.

```
resource "cloudflare_zone" "example" {
  zone = "example.com"
}

```

## Add a record to the domain

In my case I’m adding a new TXT record to the domain that google wants to see to verify my domain ownership:

```
resource "cloudflare_record" "txt-owendavies-net" {
  zone_id = "ZONE_ID"
  name = "owendavies.net"
  value = "google-site-verification=JZMrzi_LveMVIyP8g5ZICIcPVYg39UPvyOjbLmRLuWU"
  type = "TXT"
  proxied = false 
  ttl = 1

```

# 5. Run our Terraform DNS configuration

## Check the plan

Run _terraform plan_ to see the changes that are going to happen

```
terraform plan

```

Check the output from the above **terraform plan** and make sure that all that terraform is going to do is add the new dns record, it shouldn’t be changing anything else if you added the resources correctly.

## Make the changes

Now it’s time toe run **terraform apply** and make the change in Cloudflare.

```
terraform apply

```

Hopefully if everything has gone well, you now have your domain in Terraform, and a new record in the dns. You can now commit these changes to source control, and in the future can manage all your changes by Infrastructure as Code (IaC).