Generate Azure DNS zones, records, alias records, and Traffic Manager configurations. Use when the user wants to manage DNS, domain routing, or traffic distribution on Azure.
You are an Azure DNS expert. Generate production-ready DNS configurations including public and private zones, record sets, alias records, and Traffic Manager profiles.
Determine from user input or $ARGUMENTS:
Bicep template:
param domainName string
param location string = 'global'
resource dnsZone 'Microsoft.Network/dnsZones@2023-07-01-preview' = {
name: domainName
location: location
properties: {
zoneType: 'Public'
}
}
output nameServers array = dnsZone.properties.nameServers
output zoneId string = dnsZone.id
Terraform:
resource "azurerm_dns_zone" "main" {
name = var.domain_name
resource_group_name = var.resource_group_name
tags = var.tags
}
output "name_servers" {
value = azurerm_dns_zone.main.name_servers
}
Azure CLI:
# Create public DNS zone
az network dns zone create \
--resource-group myResourceGroup \
--name contoso.com
# Show name servers (update at your registrar)
az network dns zone show \
--resource-group myResourceGroup \
--name contoso.com \
--query nameServers
Bicep template:
param privateDnsZoneName string = 'contoso.internal'
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2024-06-01' = {
name: privateDnsZoneName
location: 'global'
}
resource vnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
parent: privateDnsZone
name: '${vnet.name}-link'
location: 'global'
properties: {
virtualNetwork: {
id: vnet.id
}
registrationEnabled: true // Auto-register VM DNS records
}
}
Terraform:
resource "azurerm_private_dns_zone" "main" {
name = "contoso.internal"
resource_group_name = var.resource_group_name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "main" {
name = "${var.vnet_name}-link"
resource_group_name = var.resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.main.name
virtual_network_id = azurerm_virtual_network.main.id
registration_enabled = true
tags = var.tags
}
Bicep template with all record types:
// A record - IPv4 address
resource aRecord 'Microsoft.Network/dnsZones/A@2023-07-01-preview' = {
parent: dnsZone
name: 'www'
properties: {
TTL: 300
ARecords: [
{ ipv4Address: '20.50.100.1' }
]
}
}
// AAAA record - IPv6 address
resource aaaaRecord 'Microsoft.Network/dnsZones/AAAA@2023-07-01-preview' = {
parent: dnsZone
name: 'www'
properties: {
TTL: 300
AAAARecords: [
{ ipv6Address: '2001:db8::1' }
]
}
}
// CNAME record - canonical name
resource cnameRecord 'Microsoft.Network/dnsZones/CNAME@2023-07-01-preview' = {
parent: dnsZone
name: 'blog'
properties: {
TTL: 3600
CNAMERecord: {
cname: 'contoso.azurewebsites.net'
}
}
}
// MX record - mail exchange
resource mxRecord 'Microsoft.Network/dnsZones/MX@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 3600
MXRecords: [
{ preference: 10, exchange: 'mail1.contoso.com.' }
{ preference: 20, exchange: 'mail2.contoso.com.' }
]
}
}
// TXT record - SPF, DKIM, DMARC, verification
resource txtRecord 'Microsoft.Network/dnsZones/TXT@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 3600
TXTRecords: [
{ value: ['v=spf1 include:spf.protection.outlook.com -all'] }
]
}
}
resource dmarcRecord 'Microsoft.Network/dnsZones/TXT@2023-07-01-preview' = {
parent: dnsZone
name: '_dmarc'
properties: {
TTL: 3600
TXTRecords: [
{ value: ['v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1'] }
]
}
}
// SRV record - service locator
resource srvRecord 'Microsoft.Network/dnsZones/SRV@2023-07-01-preview' = {
parent: dnsZone
name: '_sip._tcp'
properties: {
TTL: 3600
SRVRecords: [
{ priority: 10, weight: 60, port: 5060, target: 'sip.contoso.com.' }
{ priority: 10, weight: 40, port: 5060, target: 'sip2.contoso.com.' }
]
}
}
// CAA record - certificate authority authorization
resource caaRecord 'Microsoft.Network/dnsZones/CAA@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 3600
caaRecords: [
{ flags: 0, tag: 'issue', value: 'letsencrypt.org' }
{ flags: 0, tag: 'issue', value: 'digicert.com' }
{ flags: 0, tag: 'issuewild', value: 'digicert.com' }
{ flags: 0, tag: 'iodef', value: 'mailto:[email protected]' }
]
}
}
Terraform record examples:
resource "azurerm_dns_a_record" "www" {
name = "www"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 300
records = ["20.50.100.1"]
}
resource "azurerm_dns_cname_record" "blog" {
name = "blog"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 3600
record = "contoso.azurewebsites.net"
}
resource "azurerm_dns_mx_record" "main" {
name = "@"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 3600
record {
preference = 10
exchange = "mail1.contoso.com."
}
record {
preference = 20
exchange = "mail2.contoso.com."
}
}
resource "azurerm_dns_txt_record" "spf" {
name = "@"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 3600
record {
value = "v=spf1 include:spf.protection.outlook.com -all"
}
}
resource "azurerm_dns_caa_record" "main" {
name = "@"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 3600
record {
flags = 0
tag = "issue"
value = "letsencrypt.org"
}
record {
flags = 0
tag = "issue"
value = "digicert.com"
}
}
Alias records point directly to Azure resources (no charge for alias queries at zone apex):
Bicep alias records:
// Alias to Azure Front Door
resource frontDoorAlias 'Microsoft.Network/dnsZones/A@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 60
targetResource: {
id: frontDoor.id
}
}
}
// Alias to Traffic Manager
resource trafficManagerAlias 'Microsoft.Network/dnsZones/A@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 60
targetResource: {
id: trafficManagerProfile.id
}
}
}
// Alias to public IP (supports zone apex)
resource publicIpAlias 'Microsoft.Network/dnsZones/A@2023-07-01-preview' = {
parent: dnsZone
name: '@'
properties: {
TTL: 60
targetResource: {
id: publicIp.id
}
}
}
// Alias to CDN endpoint
resource cdnAlias 'Microsoft.Network/dnsZones/CNAME@2023-07-01-preview' = {
parent: dnsZone
name: 'cdn'
properties: {
TTL: 60
targetResource: {
id: cdnEndpoint.id
}
}
}
Terraform alias records:
resource "azurerm_dns_a_record" "apex_alias" {
name = "@"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 60
target_resource_id = azurerm_public_ip.main.id
}
resource "azurerm_dns_a_record" "traffic_manager_alias" {
name = "@"
zone_name = azurerm_dns_zone.main.name
resource_group_name = var.resource_group_name
ttl = 60
target_resource_id = azurerm_traffic_manager_profile.main.id
}
Priority routing (primary/failover):
resource trafficManager 'Microsoft.Network/trafficManagerProfiles@2022-04-01' = {
name: 'contoso-tm'
location: 'global'
properties: {
profileStatus: 'Enabled'
trafficRoutingMethod: 'Priority'
dnsConfig: {
relativeName: 'contoso-tm'
ttl: 60
}
monitorConfig: {
protocol: 'HTTPS'
port: 443
path: '/health'
intervalInSeconds: 10
timeoutInSeconds: 5
toleratedNumberOfFailures: 3
expectedStatusCodeRanges: [
{ min: 200, max: 200 }
]
}
endpoints: [
{
name: 'primary'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: primaryAppService.id
endpointStatus: 'Enabled'
priority: 1
}
}
{
name: 'secondary'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: secondaryAppService.id
endpointStatus: 'Enabled'
priority: 2
}
}
]
}
}
Weighted routing (A/B testing, gradual migration):
resource trafficManagerWeighted 'Microsoft.Network/trafficManagerProfiles@2022-04-01' = {
name: 'contoso-weighted-tm'
location: 'global'
properties: {
trafficRoutingMethod: 'Weighted'
dnsConfig: {
relativeName: 'contoso-weighted'
ttl: 30
}
monitorConfig: {
protocol: 'HTTPS'
port: 443
path: '/health'
}
endpoints: [
{
name: 'version-1'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appV1.id
weight: 90
}
}
{
name: 'version-2'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appV2.id
weight: 10
}
}
]
}
}
Performance routing (lowest latency):
resource trafficManagerPerformance 'Microsoft.Network/trafficManagerProfiles@2022-04-01' = {
name: 'contoso-perf-tm'
location: 'global'
properties: {
trafficRoutingMethod: 'Performance'
dnsConfig: {
relativeName: 'contoso-perf'
ttl: 60
}
monitorConfig: {
protocol: 'HTTPS'
port: 443
path: '/health'
}
endpoints: [
{
name: 'eastus'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appEastUS.id
endpointLocation: 'East US'
}
}
{
name: 'westeurope'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appWestEurope.id
endpointLocation: 'West Europe'
}
}
{
name: 'southeastasia'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appSoutheastAsia.id
endpointLocation: 'Southeast Asia'
}
}
]
}
}
Geographic routing:
resource trafficManagerGeo 'Microsoft.Network/trafficManagerProfiles@2022-04-01' = {
name: 'contoso-geo-tm'
location: 'global'
properties: {
trafficRoutingMethod: 'Geographic'
dnsConfig: {
relativeName: 'contoso-geo'
ttl: 60
}
monitorConfig: {
protocol: 'HTTPS'
port: 443
path: '/health'
}
endpoints: [
{
name: 'us-endpoint'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appUS.id
geoMapping: ['US', 'CA', 'MX']
}
}
{
name: 'eu-endpoint'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appEU.id
geoMapping: ['GEO-EU']
}
}
{
name: 'default'
type: 'Microsoft.Network/trafficManagerProfiles/azureEndpoints'
properties: {
targetResourceId: appDefault.id
geoMapping: ['WORLD']
}
}
]
}
}
Terraform Traffic Manager:
resource "azurerm_traffic_manager_profile" "main" {
name = "contoso-tm"
resource_group_name = var.resource_group_name
traffic_routing_method = "Priority"
dns_config {
relative_name = "contoso-tm"
ttl = 60
}
monitor_config {
protocol = "HTTPS"
port = 443
path = "/health"
interval_in_seconds = 10
timeout_in_seconds = 5
tolerated_number_of_failures = 3
expected_status_code_ranges = ["200-200"]
}
tags = var.tags
}
resource "azurerm_traffic_manager_azure_endpoint" "primary" {
name = "primary"
profile_id = azurerm_traffic_manager_profile.main.id
target_resource_id = azurerm_linux_web_app.primary.id
priority = 1
}
resource "azurerm_traffic_manager_azure_endpoint" "secondary" {
name = "secondary"
profile_id = azurerm_traffic_manager_profile.main.id
target_resource_id = azurerm_linux_web_app.secondary.id
priority = 2
}
# After creating the zone, get name servers
az network dns zone show \
--resource-group myResourceGroup \
--name contoso.com \
--query "nameServers" \
--output tsv
# Delegate a subdomain to another DNS zone
az network dns record-set ns create \
--resource-group myResourceGroup \
--zone-name contoso.com \
--name staging
az network dns record-set ns add-record \
--resource-group myResourceGroup \
--zone-name contoso.com \
--record-set-name staging \
--nsdname ns1-01.azure-dns.com.
// Private DNS zones for Azure PaaS private endpoints
var privateDnsZones = [
'privatelink.blob.${environment().suffixes.storage}'
'privatelink.database.windows.net'
'privatelink.vaultcore.azure.net'
'privatelink.azurewebsites.net'
'privatelink.azurecr.io'
'privatelink.cognitiveservices.azure.com'
]
resource privateDnsZonesResource 'Microsoft.Network/privateDnsZones@2024-06-01' = [
for zone in privateDnsZones: {
name: zone
location: 'global'
}
]
resource privateDnsZoneLinks 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = [
for (zone, i) in privateDnsZones: {
parent: privateDnsZonesResource[i]
name: '${vnet.name}-link'
location: 'global'
properties: {
virtualNetwork: {
id: vnet.id
}
registrationEnabled: false
}
}
]