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.
mkdir cloudflare-terraform
cd cloudflare-terraform
touch main.tf
provider "cloudflare" {
version = "~> 2.0"
email = "you@example.com"
api_key = "your-api-key"
}
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
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 into 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"
}
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
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.
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 your 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
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.
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
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 to 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).