The azure-native:privatedns:PrivateRecordSet resource, part of the Pulumi Azure Native provider, defines DNS records within a Private DNS zone: their type, values, and TTL. This guide focuses on four capabilities: A records for IPv4 resolution, CNAME records for aliasing, MX records for mail routing, and SRV records for service discovery.
Record sets belong to Private DNS zones and reference resource groups that must exist separately. The examples are intentionally small. Combine them with your own Private DNS zones and network infrastructure.
Map hostnames to IPv4 addresses with A records
Most private DNS deployments create A records that map hostnames to IPv4 addresses, enabling internal services to resolve by name.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const privateRecordSet = new azure_native.privatedns.PrivateRecordSet("privateRecordSet", {
aRecords: [{
ipv4Address: "1.2.3.4",
}],
metadata: {
key1: "value1",
},
privateZoneName: "privatezone1.com",
recordType: "A",
relativeRecordSetName: "recordA",
resourceGroupName: "resourceGroup1",
ttl: 3600,
});
import pulumi
import pulumi_azure_native as azure_native
private_record_set = azure_native.privatedns.PrivateRecordSet("privateRecordSet",
a_records=[{
"ipv4_address": "1.2.3.4",
}],
metadata={
"key1": "value1",
},
private_zone_name="privatezone1.com",
record_type="A",
relative_record_set_name="recordA",
resource_group_name="resourceGroup1",
ttl=3600)
package main
import (
privatedns "github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := privatedns.NewPrivateRecordSet(ctx, "privateRecordSet", &privatedns.PrivateRecordSetArgs{
ARecords: privatedns.ARecordArray{
&privatedns.ARecordArgs{
Ipv4Address: pulumi.String("1.2.3.4"),
},
},
Metadata: pulumi.StringMap{
"key1": pulumi.String("value1"),
},
PrivateZoneName: pulumi.String("privatezone1.com"),
RecordType: pulumi.String("A"),
RelativeRecordSetName: pulumi.String("recordA"),
ResourceGroupName: pulumi.String("resourceGroup1"),
Ttl: pulumi.Float64(3600),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var privateRecordSet = new AzureNative.PrivateDns.PrivateRecordSet("privateRecordSet", new()
{
ARecords = new[]
{
new AzureNative.PrivateDns.Inputs.ARecordArgs
{
Ipv4Address = "1.2.3.4",
},
},
Metadata =
{
{ "key1", "value1" },
},
PrivateZoneName = "privatezone1.com",
RecordType = "A",
RelativeRecordSetName = "recordA",
ResourceGroupName = "resourceGroup1",
Ttl = 3600,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.privatedns.PrivateRecordSet;
import com.pulumi.azurenative.privatedns.PrivateRecordSetArgs;
import com.pulumi.azurenative.privatedns.inputs.ARecordArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var privateRecordSet = new PrivateRecordSet("privateRecordSet", PrivateRecordSetArgs.builder()
.aRecords(ARecordArgs.builder()
.ipv4Address("1.2.3.4")
.build())
.metadata(Map.of("key1", "value1"))
.privateZoneName("privatezone1.com")
.recordType("A")
.relativeRecordSetName("recordA")
.resourceGroupName("resourceGroup1")
.ttl(3600.0)
.build());
}
}
resources:
privateRecordSet:
type: azure-native:privatedns:PrivateRecordSet
properties:
aRecords:
- ipv4Address: 1.2.3.4
metadata:
key1: value1
privateZoneName: privatezone1.com
recordType: A
relativeRecordSetName: recordA
resourceGroupName: resourceGroup1
ttl: 3600
When a client queries the hostname, DNS returns the IPv4 address from aRecords. The recordType property specifies “A” for IPv4 address records. The relativeRecordSetName sets the hostname within the zone (e.g., “recordA” becomes “recordA.privatezone1.com”). The ttl property controls how long clients cache the response, measured in seconds.
Create aliases with CNAME records
Applications often need DNS aliases that point one hostname to another, allowing you to change targets without updating clients.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const privateRecordSet = new azure_native.privatedns.PrivateRecordSet("privateRecordSet", {
cnameRecord: {
cname: "contoso.com",
},
metadata: {
key1: "value1",
},
privateZoneName: "privatezone1.com",
recordType: "CNAME",
relativeRecordSetName: "recordCNAME",
resourceGroupName: "resourceGroup1",
ttl: 3600,
});
import pulumi
import pulumi_azure_native as azure_native
private_record_set = azure_native.privatedns.PrivateRecordSet("privateRecordSet",
cname_record={
"cname": "contoso.com",
},
metadata={
"key1": "value1",
},
private_zone_name="privatezone1.com",
record_type="CNAME",
relative_record_set_name="recordCNAME",
resource_group_name="resourceGroup1",
ttl=3600)
package main
import (
privatedns "github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := privatedns.NewPrivateRecordSet(ctx, "privateRecordSet", &privatedns.PrivateRecordSetArgs{
CnameRecord: &privatedns.CnameRecordArgs{
Cname: pulumi.String("contoso.com"),
},
Metadata: pulumi.StringMap{
"key1": pulumi.String("value1"),
},
PrivateZoneName: pulumi.String("privatezone1.com"),
RecordType: pulumi.String("CNAME"),
RelativeRecordSetName: pulumi.String("recordCNAME"),
ResourceGroupName: pulumi.String("resourceGroup1"),
Ttl: pulumi.Float64(3600),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var privateRecordSet = new AzureNative.PrivateDns.PrivateRecordSet("privateRecordSet", new()
{
CnameRecord = new AzureNative.PrivateDns.Inputs.CnameRecordArgs
{
Cname = "contoso.com",
},
Metadata =
{
{ "key1", "value1" },
},
PrivateZoneName = "privatezone1.com",
RecordType = "CNAME",
RelativeRecordSetName = "recordCNAME",
ResourceGroupName = "resourceGroup1",
Ttl = 3600,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.privatedns.PrivateRecordSet;
import com.pulumi.azurenative.privatedns.PrivateRecordSetArgs;
import com.pulumi.azurenative.privatedns.inputs.CnameRecordArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var privateRecordSet = new PrivateRecordSet("privateRecordSet", PrivateRecordSetArgs.builder()
.cnameRecord(CnameRecordArgs.builder()
.cname("contoso.com")
.build())
.metadata(Map.of("key1", "value1"))
.privateZoneName("privatezone1.com")
.recordType("CNAME")
.relativeRecordSetName("recordCNAME")
.resourceGroupName("resourceGroup1")
.ttl(3600.0)
.build());
}
}
resources:
privateRecordSet:
type: azure-native:privatedns:PrivateRecordSet
properties:
cnameRecord:
cname: contoso.com
metadata:
key1: value1
privateZoneName: privatezone1.com
recordType: CNAME
relativeRecordSetName: recordCNAME
resourceGroupName: resourceGroup1
ttl: 3600
The cnameRecord property contains a single cname value that points to the target hostname. CNAME records create aliases; when a client queries the alias, DNS returns the target name, which the client then resolves separately. This indirection lets you update the target without changing the alias.
Route email with MX records
Private zones can include MX records for internal mail routing, directing email to specific mail servers with priority-based failover.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const privateRecordSet = new azure_native.privatedns.PrivateRecordSet("privateRecordSet", {
metadata: {
key1: "value1",
},
mxRecords: [{
exchange: "mail.privatezone1.com",
preference: 0,
}],
privateZoneName: "privatezone1.com",
recordType: "MX",
relativeRecordSetName: "recordMX",
resourceGroupName: "resourceGroup1",
ttl: 3600,
});
import pulumi
import pulumi_azure_native as azure_native
private_record_set = azure_native.privatedns.PrivateRecordSet("privateRecordSet",
metadata={
"key1": "value1",
},
mx_records=[{
"exchange": "mail.privatezone1.com",
"preference": 0,
}],
private_zone_name="privatezone1.com",
record_type="MX",
relative_record_set_name="recordMX",
resource_group_name="resourceGroup1",
ttl=3600)
package main
import (
privatedns "github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := privatedns.NewPrivateRecordSet(ctx, "privateRecordSet", &privatedns.PrivateRecordSetArgs{
Metadata: pulumi.StringMap{
"key1": pulumi.String("value1"),
},
MxRecords: privatedns.MxRecordArray{
&privatedns.MxRecordArgs{
Exchange: pulumi.String("mail.privatezone1.com"),
Preference: pulumi.Int(0),
},
},
PrivateZoneName: pulumi.String("privatezone1.com"),
RecordType: pulumi.String("MX"),
RelativeRecordSetName: pulumi.String("recordMX"),
ResourceGroupName: pulumi.String("resourceGroup1"),
Ttl: pulumi.Float64(3600),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var privateRecordSet = new AzureNative.PrivateDns.PrivateRecordSet("privateRecordSet", new()
{
Metadata =
{
{ "key1", "value1" },
},
MxRecords = new[]
{
new AzureNative.PrivateDns.Inputs.MxRecordArgs
{
Exchange = "mail.privatezone1.com",
Preference = 0,
},
},
PrivateZoneName = "privatezone1.com",
RecordType = "MX",
RelativeRecordSetName = "recordMX",
ResourceGroupName = "resourceGroup1",
Ttl = 3600,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.privatedns.PrivateRecordSet;
import com.pulumi.azurenative.privatedns.PrivateRecordSetArgs;
import com.pulumi.azurenative.privatedns.inputs.MxRecordArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var privateRecordSet = new PrivateRecordSet("privateRecordSet", PrivateRecordSetArgs.builder()
.metadata(Map.of("key1", "value1"))
.mxRecords(MxRecordArgs.builder()
.exchange("mail.privatezone1.com")
.preference(0)
.build())
.privateZoneName("privatezone1.com")
.recordType("MX")
.relativeRecordSetName("recordMX")
.resourceGroupName("resourceGroup1")
.ttl(3600.0)
.build());
}
}
resources:
privateRecordSet:
type: azure-native:privatedns:PrivateRecordSet
properties:
metadata:
key1: value1
mxRecords:
- exchange: mail.privatezone1.com
preference: 0
privateZoneName: privatezone1.com
recordType: MX
relativeRecordSetName: recordMX
resourceGroupName: resourceGroup1
ttl: 3600
The mxRecords array lists mail servers with their exchange hostnames and preference values. Lower preference numbers indicate higher priority; mail clients try servers in priority order. This enables failover: if the primary server is unavailable, clients automatically try the next priority level.
Advertise service locations with SRV records
Service discovery protocols use SRV records to locate services by protocol and domain, encoding port numbers and load distribution.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const privateRecordSet = new azure_native.privatedns.PrivateRecordSet("privateRecordSet", {
metadata: {
key1: "value1",
},
privateZoneName: "privatezone1.com",
recordType: "SRV",
relativeRecordSetName: "recordSRV",
resourceGroupName: "resourceGroup1",
srvRecords: [{
port: 80,
priority: 0,
target: "contoso.com",
weight: 10,
}],
ttl: 3600,
});
import pulumi
import pulumi_azure_native as azure_native
private_record_set = azure_native.privatedns.PrivateRecordSet("privateRecordSet",
metadata={
"key1": "value1",
},
private_zone_name="privatezone1.com",
record_type="SRV",
relative_record_set_name="recordSRV",
resource_group_name="resourceGroup1",
srv_records=[{
"port": 80,
"priority": 0,
"target": "contoso.com",
"weight": 10,
}],
ttl=3600)
package main
import (
privatedns "github.com/pulumi/pulumi-azure-native-sdk/privatedns/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := privatedns.NewPrivateRecordSet(ctx, "privateRecordSet", &privatedns.PrivateRecordSetArgs{
Metadata: pulumi.StringMap{
"key1": pulumi.String("value1"),
},
PrivateZoneName: pulumi.String("privatezone1.com"),
RecordType: pulumi.String("SRV"),
RelativeRecordSetName: pulumi.String("recordSRV"),
ResourceGroupName: pulumi.String("resourceGroup1"),
SrvRecords: privatedns.SrvRecordArray{
&privatedns.SrvRecordArgs{
Port: pulumi.Int(80),
Priority: pulumi.Int(0),
Target: pulumi.String("contoso.com"),
Weight: pulumi.Int(10),
},
},
Ttl: pulumi.Float64(3600),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var privateRecordSet = new AzureNative.PrivateDns.PrivateRecordSet("privateRecordSet", new()
{
Metadata =
{
{ "key1", "value1" },
},
PrivateZoneName = "privatezone1.com",
RecordType = "SRV",
RelativeRecordSetName = "recordSRV",
ResourceGroupName = "resourceGroup1",
SrvRecords = new[]
{
new AzureNative.PrivateDns.Inputs.SrvRecordArgs
{
Port = 80,
Priority = 0,
Target = "contoso.com",
Weight = 10,
},
},
Ttl = 3600,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.privatedns.PrivateRecordSet;
import com.pulumi.azurenative.privatedns.PrivateRecordSetArgs;
import com.pulumi.azurenative.privatedns.inputs.SrvRecordArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var privateRecordSet = new PrivateRecordSet("privateRecordSet", PrivateRecordSetArgs.builder()
.metadata(Map.of("key1", "value1"))
.privateZoneName("privatezone1.com")
.recordType("SRV")
.relativeRecordSetName("recordSRV")
.resourceGroupName("resourceGroup1")
.srvRecords(SrvRecordArgs.builder()
.port(80)
.priority(0)
.target("contoso.com")
.weight(10)
.build())
.ttl(3600.0)
.build());
}
}
resources:
privateRecordSet:
type: azure-native:privatedns:PrivateRecordSet
properties:
metadata:
key1: value1
privateZoneName: privatezone1.com
recordType: SRV
relativeRecordSetName: recordSRV
resourceGroupName: resourceGroup1
srvRecords:
- port: 80
priority: 0
target: contoso.com
weight: 10
ttl: 3600
The srvRecords array defines service endpoints with port, priority, target, and weight properties. Priority controls failover order (lower values first). Weight enables load distribution among servers with the same priority; higher weights receive proportionally more traffic. The target specifies the hostname, and port indicates which TCP or UDP port the service listens on.
Beyond these examples
These snippets focus on specific record set features: DNS record types (A, CNAME, MX, SRV) and TTL and metadata configuration. They’re intentionally minimal rather than complete DNS zone configurations.
The examples reference pre-existing infrastructure such as Private DNS zones (privateZoneName) and Azure resource groups. They focus on configuring individual record sets rather than provisioning the surrounding DNS infrastructure.
To keep things focused, common record types are omitted, including:
- AAAA records for IPv6 addressing
- PTR records for reverse DNS lookups
- SOA records for zone authority configuration
- TXT records for verification and SPF
These omissions are intentional: the goal is to illustrate how each record type is wired, not provide drop-in DNS modules. See the Private DNS PrivateRecordSet resource reference for all available configuration options.
Let's configure Azure Private DNS Record Sets
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Naming & Immutability
privateZoneName, recordType, and relativeRecordSetName properties are immutable. Changing any of these requires replacing the resource.relativeRecordSetName is the record name relative to the zone. For example, if your zone is privatezone1.com and relativeRecordSetName is recordA, the full DNS name (FQDN) will be recordA.privatezone1.com.relativeRecordSetName to @ to create a record at the zone apex, as shown in the SOA record example.privatezone1.com instead of privatezone1.com.).Record Types & Configuration
aRecords for A records, cnameRecord for CNAME, mxRecords for MX, etc. Set recordType to match the record type you’re creating.relativeRecordSetName and recordType. You can’t have both an A record and a CNAME record with the same name, for example.0.0.127.in-addr.arpa for IPv4 or the appropriate format for IPv6, then create PTR records with the IP address octets as the relativeRecordSetName.Computed Properties & Behavior
fqdn (fully qualified domain name) is the complete DNS name of the record set, combining relativeRecordSetName and privateZoneName.isAutoRegistered indicates whether the record set was automatically created through a virtual network link’s auto-registration feature, rather than being manually created.