Quick Links
Terraform is a popular infrastructure as code tool, and when paired with CloudFlare, makes managing complex configurations within CloudFlare much easier. For those not familiar, Terraform uses the HCL configuration language to define an infrastructure configuration that can then be used to apply the requested settings to the provider. CloudFlare offers DNS services, security, and edge computing services that pair perfectly with the Terraform tool.
Installing Terraform
Terraform can be used either on Windows or on Linux. The Terraform binary itself is a single executable, and merely needs to be downloaded and placed into the path of the system.
Windows Installation
First, you will need to download the Terraform executable for Windows. Once downloaded, place the executable in a Windows path location. If you need to put the executable in a different location but would like it accessible at any time, you can use the following PowerShell code to modify the user's PATH
environmental variable.
[System.Environment]::SetEnvironmentVariable("PATH",(($Env:PATH, "C:\Tools") -Join ";"),"User")
This can be used to modify the system PATH
by changing User
to Machine
. You will need Administrative rights to do this.
Linux Installation
Much like Windows, you will download the latest release of Terraform. Because you might not always be using a GUI, you can do this via the following shell code. Replace {release}
with the version of the code, like 0.13.0
.
wget <https://releases.hashicorp.com/terraform/{release}/terraform_{release}_linux_amd64.zip>
unzip terraform_{release}_linux_amd64.zip
mv terraform /usr/bin/
Setting Up Terraform for CloudFlare
To contain our Terraform configuration, we are going to make a directory to hold the .tf
files, which are the extension of the Terraform configuration files. Create a new directory to hold the configuration.
PowerShell 7 on Windows
New-Item -Name 'CF_Terraform' -Type 'Directory'
Set-Location -Path 'CF_Terraform'
Bash Shell on Linux
mkdir cf_terraform
cd cf_terraform
Once you have created and navigated to the directory, we will need to initialize the Terraform configuration. We first need to create our configuration file. We are opting to not hardcode our credentials into the configuration file. Instead, a file will pass in those credentials that are excluded from version control. Speaking of which, Git is highly recommended to keep track of the changes.
variable "api_token" {}
provider "cloudflare" {
version = "~> 2.9"
api_token = var.api_token
}
The following .auto.tfvars
file will contain the secrets that we pass into Terraform but do not want to commit to version control history.
cloudflare.auto.tfvars
# Zone.DNS Permissions
# Example token below
api_token = "as3uo7WkxL6asdfasdfaME7IdLofKBG9C_Zi-gf"
The reason for the .auto
section of the .tfvars
filename is that this variable folder will be automatically read by Terraform on operations instead of explicitly passing it in via -var-file="cloudflare.tfvars"
.
Now that we have both of our files configured, it is time to initialize our configuration. This will install any providers that have been specified in the provider
section of our Terraform configuration file.
terraform init
Defining the Terraform CloudFlare Configuration
Now that we have successfully connected to our domain, we need to create our configuration. The first thing we need to do is modify our cloudflare.auto.tfvars
file to include the zone_id
that we are going to be targeting the DNS records modifications to. Add the following line into the cloudflare.auto.tfvars
file.
# Zone.DNS Permissions
api_token = "as3uo7WkxL6asdfasdfaME7IdLofKBG9C_Zi-gf"
# Specific Domain Zone ID
zone_id = "fddd89b6e1d52ebdfdasdc8bc02186333"
Next, we need to define the records that we are going to add to CloudFlare. To do this, we are going to use the cloudflare_record
resource to create the records. The format of this is the following: resource {type} {name}
. The type will be cloudflare_record
, and for the name we will use a_mydomain_com
and cname_www
. These names are arbitrary though, and they can be whatever you would like.
resource "cloudflare_record" "a_mydomain_com" {
zone_id = var.zone_id
name = "mydomain.com"
value = "133.145.220.110"
type = "A"
ttl = 1
proxied = true
}
resource "cloudflare_record" "cname_www" {
zone_id = var.zone_id
name = "www"
value = "mydomain.com"
type = "CNAME"
ttl = 1
proxied = true
}
One caveat about the names. If you want to use terraform import
to import state on a given record, you will have to match the name with the import record like so:
terraform import cloudflare_record.a_mydomain_com {zone_id}/{record_id}
Planning the Terraform Changes
Now that we have our configuration defined, we can run the terraform plan
command, which will generate the changes between what is known by Terraform via the .tfstate
file and the CloudFlare environment. If resources have not been imported, or this is the first time running the command, then Terraform will have no knowledge of the environment and all changes will be new.
terraform plan
Applying the Terraform Changes
Once you are confident in your configuration, simply use the apply
command. This will prompt for a confirmation, where you need to type yes
. The output will show the configuration to apply and the state.
terraform apply
Conclusion
Combining CloudFlare and Terraform is a potent combination. When you are able to architect your environment in code and track changes over time (using version control), you unlock new efficiencies and control. In the event that a configuration is incorrect, it is trivial to roll back to a prior configuration, which makes recovering from errors very quick and painless.