Terraform module to provision a CloudFlare zone with DNS record managment
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Source: <https://opensource.org/licenses/MIT>
See LICENSE for full details.
Submodules included to root module that can be called independent:
- single-record - Root module creates an object with a full zone and object with all records, this small sub-module is to facilitate the creation of a single record to an existing zone.
- The
name
and thedata.name
argument values default to@
(root). This is actually the default behavior, but only for the value of thedata.name
argument when you are not using the module. - The
data
argument is fully supported. Thevalue
argument takes precedence over thedata
argument to avoid errors if two arguments are accidentally given at the same time, since only one of them can be given at the same time. - The
ttl
argument value defaults to1
(automatic). This is actually the default behavior. - The
ttl
argument value is forced to1
(automatic), regardless of explicitly set value, if you set theproxied
argument value totrue
. - The
proxied
argument value defaults tofalse
. This is actually the default behavior. You must explicitly set this argument value totrue
for the records that you want to proxy through Cloudflare. - The
proxied
argument value is forced tofalse
for unsupported record types, regardless of explicitly set value. - The
proxied
argument value is forced tofalse
for wildcard records for non-enterprise plans, regardless of explicitly set value, because non-enterprise customers can create but not proxy wildcard records. - To create only each record without create whole zone, you can just use simple submodule single-record.
Name | Version |
---|---|
terraform | >= 0.14 |
cloudflare | >= 3.23 |
No modules.
Name | Type |
---|---|
cloudflare_record.this | resource |
cloudflare_zone.this | resource |
cloudflare_zone_dnssec.this | resource |
Name | Description | Type | Default | Required |
---|---|---|---|---|
account_id | Account ID to manage the zone resource in. You can get more information on how to find account_id at this page. |
string |
"" |
no |
enable_dnssec | Enable or disable DNSSEC. | bool |
false |
no |
jump_start | Automatically attempt to fetch existing DNS records on creation. Ignored after zone is created. | bool |
false |
no |
paused | Indicates if the zone is only using Cloudflare DNS services. A true value means the zone will not receive security or performance benefits. | bool |
false |
no |
plan | The desired plan for the zone. Can be updated once the one is created. Changing this value will create/cancel associated subscriptions. Possible values: free , partners_free , pro , partners_pro , business , partners_business , enterprise , partners_enterprise ."You can get more information about available plans at this page. |
string |
"free" |
no |
records | Zone's DNS records. Possible values: * for the type argument: "A", "AAAA", "CAA", "CERT", "CNAME", "DNSKEY", "DS", "HTTPS", "LOC", "MX", "NAPTR", "NS", "PTR", "SMIMEA", "SPF", "SRV", "SSHFP", "SVCB", "TLSA", "TXT", "URI".*for the priority argument: between 0 and 65535.\nPossible values for the ttl argument: between 60 and 86400, or 1 for automatic." |
list(object({ |
[] |
no |
type | A full zone implies that DNS is hosted with Cloudflare. A partial zone is typically a partner-hosted zone or a CNAME setup. Possible values: full , partial .To learn more and choose the right configuration for you, see the documentation about full or partial CNAME setups. |
string |
"full" |
no |
zone | The DNS zone name which will be added, e.g. example.com. | string |
n/a | yes |
Name | Description |
---|---|
algorithm | Zone DNSSEC algorithm. |
digest | Zone DNSSEC digest. |
digest_algorithm | Digest algorithm use for Zone DNSSEC. |
digest_type | Digest Type for Zone DNSSEC. |
dnssec_status | The status of the Zone DNSSEC. |
ds | DS for the Zone DNSSEC. |
flags | Zone DNSSEC flags. |
key_tag | Key Tag for the Zone DNSSEC. |
key_type | Key type used for Zone DNSSEC. |
meta | Map of booleans, indicating some zone statuses or flags. |
modified_on | Zone DNSSEC updated time. |
name_servers | Cloudflare-assigned name servers. This is only populated for zones that use Cloudflare DNS. |
public_key | Public Key for the Zone DNSSEC. |
record_created_on | The RFC3339 timestamp of when the records were created. |
record_hostnames | The FQDN of the records. |
record_ids | The record IDs. |
record_metadata | A key-value map of string metadata Cloudflare associates with the records. |
record_modified_on | The RFC3339 timestamp of when the records were last modified. |
record_proxiable | Shows whether these records can be proxied, must be true if setting proxied=true. |
status | Status of the zone. Valid values: active, pending, initializing, moved, deleted, deactivated. |
vanity_name_servers | List of Vanity Nameservers (if set). |
verification_key | Contains the TXT record value to validate domain ownership. This is only populated for zones of type partial. |
zone_id | The zone ID. |
module "zone" {
source = "../.."
zone = var.zone
records = [
{
name = "bastion-example"
value = "1.1.1.1"
type = "A"
ttl = 1
},
{
name = "api-example"
value = "1.1.1.1"
type = "A"
ttl = 1
}
]
}
if the domain exists and already has records, don't worry about importing it into terraform using this module.
In the first step you need to create a zone to tfstate:
terraform import cloudflare_zone.example <zone_id>
according to official documentation.
When we have our zone in tfstate, we have 2 steps to done.
- As first, we can run our helper bash script to generate json.
A bash script dump records from exists zone DNS to json, just copy the generated json to the
records
variable. Script requireCLOUDFLARE_API_TOKEN
as a environment variable and domain name as a parameter.
For Example:
CLOUDFLARE_API_TOKEN=1234567890abcdef1234567890abcdef; bin/import_zone.sh "acme.sh"
- The second step is more complex because you need to import existing records into your
tfstate
. To make it as simple as possible, you can use a our hook:
#!/bin/bash
DOMAIN="$1"
zoneid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq \
-r '{"result"}[] | .[0] | .id')
records=$(curl -s -L -X GET "https://api.cloudflare.com/client/v4/zones/${zoneid}/dns_records" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type:application/json" | jq -r '.result[] | "\(.name)_\(.type)_\(.id)|\(.id)"')
for i in $records
do
s=$(echo $i | awk -F'|' '{print $1}')
t=$(echo $i | awk -F'|' '{print $2}')
terraform import cloudflare_record.this[\"${s}\"] ${zoneid}/${t}
done
This script is fully compatible with our bin/import_zone.sh
script and creates the same style object's names in tfstate
.
As previously, hook require CLOUDFLARE_API_TOKEN
as a environment variable and domain name as a parameter.
To more information about importing cloudflare_record please visit to official documentation.