Terraform - setting up domain DNS with cloudflare
Owen Davies
Posted on February 17, 2020
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.
If you need to install Terraform check out my article on Getting Started with Terraform.
Our plan today
- Setup our new Terraform file
- Get our Cloudflare API key
- (Optional) Import our already existing DNS configuration from Cloudflare
- Create our DNS resources in our Terraform file
- 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
We can see that terraform has pulled down version 2.3 of the cloudflare provider.
2. Get our Cloudflare Global API key
- Login to Cloudflare with your credentials
- Click on My Profile at the top right
- Click on the 3rd tab “API Tokens”
- Click on View next to Global API Key
- Type in your password again to confirm it’s you
- 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.
- 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).
Posted on February 17, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.