Skip to content

CLZ-300 - Optional Public DNS

Optional Public DNS architecture
Service or workflow illustration. The lesson defines the exact resource settings. Open at full size.

Goal

Model an Azure public DNS zone: the default creates no zone. Enable it only for a domain you actually own. The Terraform check warns about placeholders but does not block apply; stop and resolve every warning yourself.

CLZ-300 learning sequence
Arrows show the learning sequence, not service traffic. Optional Azure deployment. Open at full size.

Prerequisites

  • Complete CLZ-290.
  • To enable creation, own a real public domain and understand registrar delegation.
  • Do not change registrar name servers merely to finish the lesson.

Architecture

CLZ-300 — The default path creates a resource group without a public DNS zone. A dashed opt-in branch creates an owned zone, while registrar delegation remains external. Public authority depends on delegation and check warnings do not block apply.
Lesson-specific teaching diagram. Read the arrow legend and the accompanying architecture explanation. Optional Azure deployment. On narrow screens, scroll the diagram horizontally. Open at full size.

A boolean controls whether Terraform creates one Azure DNS zone. When disabled, only the lesson resource group is managed. When enabled, Azure returns authoritative name servers, but public resolution occurs only after the domain owner delegates the zone at the registrar.

Resources And Cost

Relative cost: Low. Azure DNS hosted zones and queries are low cost; registrar/domain charges are external.

Component Purpose and principal cost driver
Resource group Always created for lifecycle consistency.
Optional public DNS zone Created only when explicitly enabled with a non-placeholder owned domain.
Authoritative name servers Outputs used for deliberate external delegation; Terraform does not change the registrar.

Inputs

Input Required substitution or decision
subscription_id Required for Azure plan, apply, and destroy; use the exact subscription GUID.
environment Keep dev for the lab unless testing another environment boundary.
location Select a supported region with sufficient quota.
name_prefix Use a short lowercase prefix.
create_public_dns_zone Keep false for the safe path; set true only when you own and intend to manage the domain.
dns_zone_name Replace example.com with the owned apex domain before enabling creation; a check warning is not an execution barrier.

Keep real subscription IDs, CIDRs, domains, endpoint names, and secrets in untracked local files or environment variables.

Deploy

Review the plan and lesson-specific gates before deliberate execution. Local-only and read-only lessons create no Azure resources.
Review the plan and lesson-specific gates before deliberate execution. Local-only and read-only lessons create no Azure resources. Open at full size.

Run from the repository root in PowerShell 7:

Set-Location CLZ-300-public-dns-optional
Copy-Item terraform.tfvars.example terraform.tfvars -ErrorAction SilentlyContinue
$subscriptionId = az account show --query id --output tsv
terraform init -lockfile=readonly
terraform fmt -check
terraform validate
terraform plan -var "subscription_id=$subscriptionId" -out tfplan
terraform show tfplan
terraform apply tfplan

The default applies only the resource group. Enabling the zone is a separate, deliberate run after editing both public-DNS inputs.

Validate

terraform output -json public_dns_name_servers
terraform plan -var "subscription_id=$subscriptionId" -var 'create_public_dns_zone=true' -var 'dns_zone_name=example.com'
$resourceGroup = terraform output -raw resource_group_name
az network dns zone list --resource-group $resourceGroup --query '[].{name:name,nameServers:nameServers}' --output json

Expected result:

  • Default mode returns an empty name-server list and creates no DNS zone.
  • The deliberately unsafe example.com plan reports a failed check warning. Do not apply it: check blocks do not stop Terraform operations.
  • Enabled owned-domain mode returns Azure authoritative name servers; public lookup still requires registrar delegation.

Troubleshooting

Gather evidence, repair the cause, and rerun verification.
Gather evidence, repair the cause, and rerun verification. Open at full size.
Symptom Resolution
The domain check reports a warning Stop before apply. Use an owned domain, or keep zone creation disabled.
The zone exists but Internet DNS does not resolve Compare registrar delegation with the Azure name-server output and allow for DNS TTL/propagation.
A parent zone is already managed elsewhere Coordinate delegation; do not create conflicting authorities.

Cleanup

Use the lesson state and cleanup instructions. Preserve remote-state dependencies until consumers are removed.
Use the lesson state and cleanup instructions. Preserve remote-state dependencies until consumers are removed. Open at full size.
$resourceGroup = terraform output -raw resource_group_name
terraform destroy -var "subscription_id=$subscriptionId"
az group exists --name $resourceGroup

The optional zone and resource group are deleted. Restore registrar delegation separately if you changed it; Terraform does not own that external state.

Production Delta

  • Protect DNS changes with review, least privilege, activity logs, DNSSEC decisions, and documented registrar ownership.
  • Use separate zones/subdomains per environment and test delegation/rollback before production cutover.

Exercises

  1. Run the default plan and prove there is no azurerm_dns_zone change.
  2. With a domain you own, plan (but do not apply) enabled creation and identify the external delegation step.

← CLZ-290 - Private DNS | Curriculum | CLZ-310 - Remote State Storage →