Managing DNS with Terraform
Learn how to manage your DNS zones and records as Infrastructure as Code using the DNScale Terraform Provider.
Managing DNS through code brings the same benefits you get from infrastructure as code everywhere else: version control, peer review, automated deployments, and reproducible environments. The DNScale Terraform Provider lets you manage zones, records, and DNSSEC configuration using HashiCorp Terraform.
Prerequisites
Before you begin, ensure you have:
- Terraform installed (version 1.0 or later) - Download Terraform
- A DNScale account with an API key - Get your API key
- Basic familiarity with Terraform concepts (providers, resources, state)
Provider Installation
The DNScale provider is published to the Terraform Registry. Add it to your Terraform configuration:
terraform {
required_providers {
dnscale = {
source = "dnscaleou/dnscale"
version = "~> 1.0"
}
}
}
provider "dnscale" {
api_key = var.dnscale_api_key
# Optional: api_url defaults to https://api.dnscale.eu
}Create a variables file to manage your API key securely:
# variables.tf
variable "dnscale_api_key" {
description = "DNScale API key"
type = string
sensitive = true
}Set the API key via environment variable:
export TF_VAR_dnscale_api_key="your-api-key-here"
terraform initCreating Your First Zone
A DNS zone represents a domain you want to manage. Create one with the dnscale_zone resource:
resource "dnscale_zone" "example" {
name = "example.com"
region = "eu"
}
output "zone_id" {
value = dnscale_zone.example.id
}
output "nameservers" {
value = dnscale_zone.example.nameservers
}Run terraform apply to create the zone. The output will show your assigned nameservers - update these at your domain registrar to activate DNS hosting.
Managing DNS Records
A Records
Point your domain to an IPv4 address:
resource "dnscale_record" "www" {
zone_id = dnscale_zone.example.id
name = "www"
type = "A"
content = "192.0.2.1"
ttl = 3600
}
# Apex domain (root)
resource "dnscale_record" "apex" {
zone_id = dnscale_zone.example.id
name = ""
type = "A"
content = "192.0.2.1"
ttl = 3600
}AAAA Records
Add IPv6 support:
resource "dnscale_record" "www_ipv6" {
zone_id = dnscale_zone.example.id
name = "www"
type = "AAAA"
content = "2001:db8::1"
ttl = 3600
}CNAME Records
Create aliases for subdomains:
resource "dnscale_record" "blog" {
zone_id = dnscale_zone.example.id
name = "blog"
type = "CNAME"
content = "example.github.io."
ttl = 3600
}MX Records
Configure email delivery:
resource "dnscale_record" "mx_primary" {
zone_id = dnscale_zone.example.id
name = ""
type = "MX"
content = "mail.example.com."
ttl = 3600
priority = 10
}
resource "dnscale_record" "mx_backup" {
zone_id = dnscale_zone.example.id
name = ""
type = "MX"
content = "mail2.example.com."
ttl = 3600
priority = 20
}TXT Records
Add SPF, DKIM, or verification records:
# SPF record
resource "dnscale_record" "spf" {
zone_id = dnscale_zone.example.id
name = ""
type = "TXT"
content = "v=spf1 include:_spf.google.com ~all"
ttl = 3600
}
# Domain verification
resource "dnscale_record" "verification" {
zone_id = dnscale_zone.example.id
name = ""
type = "TXT"
content = "google-site-verification=abc123..."
ttl = 3600
}Enabling DNSSEC
Secure your zone with DNSSEC by creating signing keys:
# Key Signing Key (KSK)
resource "dnscale_dnssec_key" "ksk" {
zone_id = dnscale_zone.example.id
key_type = "ksk"
algorithm = 13
bits = 256
active = true
published = true
}
# Zone Signing Key (ZSK)
resource "dnscale_dnssec_key" "zsk" {
zone_id = dnscale_zone.example.id
key_type = "zsk"
algorithm = 13
bits = 256
active = true
published = true
}After applying, retrieve the DS record to configure at your registrar:
output "ds_record" {
value = dnscale_dnssec_key.ksk.ds
}Using Data Sources
Query existing resources without managing them:
List All Zones
data "dnscale_zones" "all" {}
output "all_zones" {
value = data.dnscale_zones.all.zones
}List Records in a Zone
data "dnscale_records" "all" {
zone_id = dnscale_zone.example.id
}
# Filter to find specific records
output "a_records" {
value = [for r in data.dnscale_records.all.records : r if r.type == "A"]
}Check DNSSEC Status
data "dnscale_dnssec_status" "check" {
zone_id = dnscale_zone.example.id
}
output "dnssec_enabled" {
value = data.dnscale_dnssec_status.check.enabled
}Importing Existing Resources
Already have zones configured in DNScale? Import them into Terraform:
# Import a zone
terraform import dnscale_zone.existing <zone-id>
# Import a record
terraform import dnscale_record.existing <zone-id>/<record-id>
# Import a DNSSEC key
terraform import dnscale_dnssec_key.existing <zone-id>/<key-id>Find IDs in the DNScale dashboard or via the API.
Best Practices
Use Variables for Reusability
variable "domain" {
description = "Domain name to manage"
type = string
}
variable "web_servers" {
description = "List of web server IPs"
type = list(string)
}
resource "dnscale_zone" "main" {
name = var.domain
region = "eu"
}
resource "dnscale_record" "web" {
count = length(var.web_servers)
zone_id = dnscale_zone.main.id
name = "www"
type = "A"
content = var.web_servers[count.index]
ttl = 300
}Organize with Modules
Create reusable modules for common patterns:
# modules/website-dns/main.tf
resource "dnscale_zone" "zone" {
name = var.domain
region = var.region
}
resource "dnscale_record" "apex" {
zone_id = dnscale_zone.zone.id
name = ""
type = "A"
content = var.server_ip
ttl = var.ttl
}
resource "dnscale_record" "www" {
zone_id = dnscale_zone.zone.id
name = "www"
type = "CNAME"
content = "${var.domain}."
ttl = var.ttl
}Use Workspaces for Environments
terraform workspace new staging
terraform workspace new production
# Switch between environments
terraform workspace select staging
terraform apply -var-file="staging.tfvars"Store State Remotely
For team collaboration, use remote state:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "dns/terraform.tfstate"
region = "eu-west-1"
}
}Complete Example
Here's a full configuration for a typical website:
terraform {
required_providers {
dnscale = {
source = "dnscaleou/dnscale"
version = "~> 1.0"
}
}
}
provider "dnscale" {
api_key = var.dnscale_api_key
}
variable "dnscale_api_key" {
type = string
sensitive = true
}
# Create zone
resource "dnscale_zone" "main" {
name = "mywebsite.com"
region = "eu"
}
# Website records
resource "dnscale_record" "apex" {
zone_id = dnscale_zone.main.id
name = ""
type = "A"
content = "203.0.113.50"
ttl = 3600
}
resource "dnscale_record" "www" {
zone_id = dnscale_zone.main.id
name = "www"
type = "CNAME"
content = "mywebsite.com."
ttl = 3600
}
# Email configuration
resource "dnscale_record" "mx" {
zone_id = dnscale_zone.main.id
name = ""
type = "MX"
content = "aspmx.l.google.com."
ttl = 3600
priority = 1
}
resource "dnscale_record" "spf" {
zone_id = dnscale_zone.main.id
name = ""
type = "TXT"
content = "v=spf1 include:_spf.google.com ~all"
ttl = 3600
}
# Enable DNSSEC
resource "dnscale_dnssec_key" "ksk" {
zone_id = dnscale_zone.main.id
key_type = "ksk"
algorithm = 13
bits = 256
active = true
published = true
}
resource "dnscale_dnssec_key" "zsk" {
zone_id = dnscale_zone.main.id
key_type = "zsk"
algorithm = 13
bits = 256
active = true
published = true
}
# Outputs
output "nameservers" {
value = dnscale_zone.main.nameservers
}
output "ds_record" {
value = dnscale_dnssec_key.ksk.ds
}Next Steps
- Browse the Provider Documentation for complete API reference
- Learn about DNS Record Types supported by DNScale
- Understand DNS Zones and how they work
- Explore Zone Import Methods to migrate existing DNS
Conclusion
The DNScale Terraform Provider brings Infrastructure as Code principles to DNS management. Version control your DNS changes, automate deployments across environments, and maintain consistency across your infrastructure. Whether you manage a single domain or hundreds, Terraform provides the tooling to do it reliably and at scale.