Introducing PostScale -- email API for transactional, inbound, and masked addresses. PostScale

    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:

    1. Terraform installed (version 1.0 or later) - Download Terraform
    2. A DNScale account with an API key - Get your API key
    3. 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 init

    Creating 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

    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.