The azure-native:iotoperations:BrokerListener resource, part of the Pulumi Azure Native provider, defines network listeners for Azure IoT Operations MQTT brokers. This guide focuses on two capabilities: port and protocol configuration, and TLS certificate management through both automatic (cert-manager) and manual methods.
Broker listeners belong to an IoT Operations broker instance running on Azure Arc-enabled Kubernetes. They reference authentication resources, cert-manager Issuers for automatic certificate provisioning, and Kubernetes secrets for manual certificate management. The examples are intentionally small. Combine them with your own broker infrastructure, authentication policies, and certificate management setup.
Expose MQTT on the default port
Most IoT deployments start with a basic listener on port 1883, the standard unencrypted MQTT port.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const brokerListener = new azure_native.iotoperations.BrokerListener("brokerListener", {
brokerName: "resource-name123",
extendedLocation: {
name: "qmbrfwcpwwhggszhrdjv",
type: azure_native.iotoperations.ExtendedLocationType.CustomLocation,
},
instanceName: "resource-name123",
listenerName: "resource-name123",
properties: {
ports: [{
port: 1883,
}],
},
resourceGroupName: "rgiotoperations",
});
import pulumi
import pulumi_azure_native as azure_native
broker_listener = azure_native.iotoperations.BrokerListener("brokerListener",
broker_name="resource-name123",
extended_location={
"name": "qmbrfwcpwwhggszhrdjv",
"type": azure_native.iotoperations.ExtendedLocationType.CUSTOM_LOCATION,
},
instance_name="resource-name123",
listener_name="resource-name123",
properties={
"ports": [{
"port": 1883,
}],
},
resource_group_name="rgiotoperations")
package main
import (
iotoperations "github.com/pulumi/pulumi-azure-native-sdk/iotoperations/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iotoperations.NewBrokerListener(ctx, "brokerListener", &iotoperations.BrokerListenerArgs{
BrokerName: pulumi.String("resource-name123"),
ExtendedLocation: &iotoperations.ExtendedLocationArgs{
Name: pulumi.String("qmbrfwcpwwhggszhrdjv"),
Type: pulumi.String(iotoperations.ExtendedLocationTypeCustomLocation),
},
InstanceName: pulumi.String("resource-name123"),
ListenerName: pulumi.String("resource-name123"),
Properties: &iotoperations.BrokerListenerPropertiesArgs{
Ports: iotoperations.ListenerPortArray{
&iotoperations.ListenerPortArgs{
Port: pulumi.Int(1883),
},
},
},
ResourceGroupName: pulumi.String("rgiotoperations"),
})
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 brokerListener = new AzureNative.IoTOperations.BrokerListener("brokerListener", new()
{
BrokerName = "resource-name123",
ExtendedLocation = new AzureNative.IoTOperations.Inputs.ExtendedLocationArgs
{
Name = "qmbrfwcpwwhggszhrdjv",
Type = AzureNative.IoTOperations.ExtendedLocationType.CustomLocation,
},
InstanceName = "resource-name123",
ListenerName = "resource-name123",
Properties = new AzureNative.IoTOperations.Inputs.BrokerListenerPropertiesArgs
{
Ports = new[]
{
new AzureNative.IoTOperations.Inputs.ListenerPortArgs
{
Port = 1883,
},
},
},
ResourceGroupName = "rgiotoperations",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.iotoperations.BrokerListener;
import com.pulumi.azurenative.iotoperations.BrokerListenerArgs;
import com.pulumi.azurenative.iotoperations.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.iotoperations.inputs.BrokerListenerPropertiesArgs;
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 brokerListener = new BrokerListener("brokerListener", BrokerListenerArgs.builder()
.brokerName("resource-name123")
.extendedLocation(ExtendedLocationArgs.builder()
.name("qmbrfwcpwwhggszhrdjv")
.type("CustomLocation")
.build())
.instanceName("resource-name123")
.listenerName("resource-name123")
.properties(BrokerListenerPropertiesArgs.builder()
.ports(ListenerPortArgs.builder()
.port(1883)
.build())
.build())
.resourceGroupName("rgiotoperations")
.build());
}
}
resources:
brokerListener:
type: azure-native:iotoperations:BrokerListener
properties:
brokerName: resource-name123
extendedLocation:
name: qmbrfwcpwwhggszhrdjv
type: CustomLocation
instanceName: resource-name123
listenerName: resource-name123
properties:
ports:
- port: 1883
resourceGroupName: rgiotoperations
The ports array defines which ports the listener exposes. Each port entry specifies a port number; without additional configuration, the listener uses MQTT protocol without TLS. The brokerName and instanceName tie this listener to an existing IoT Operations broker, while extendedLocation points to the Azure Arc custom location where the broker runs.
Configure multiple ports with TLS variants
Production deployments typically expose multiple protocols to support different client capabilities, mixing encrypted and unencrypted connections.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const brokerListener = new azure_native.iotoperations.BrokerListener("brokerListener", {
brokerName: "resource-name123",
extendedLocation: {
name: "qmbrfwcpwwhggszhrdjv",
type: azure_native.iotoperations.ExtendedLocationType.CustomLocation,
},
instanceName: "resource-name123",
listenerName: "resource-name123",
properties: {
ports: [
{
authenticationRef: "example-authentication",
port: 8080,
protocol: azure_native.iotoperations.BrokerProtocolType.WebSockets,
},
{
authenticationRef: "example-authentication",
port: 8443,
protocol: azure_native.iotoperations.BrokerProtocolType.WebSockets,
tls: {
certManagerCertificateSpec: {
issuerRef: {
group: "jtmuladdkpasfpoyvewekmiy",
kind: azure_native.iotoperations.CertManagerIssuerKind.Issuer,
name: "example-issuer",
},
},
mode: azure_native.iotoperations.TlsCertMethodMode.Automatic,
},
},
{
authenticationRef: "example-authentication",
port: 1883,
},
{
authenticationRef: "example-authentication",
port: 8883,
tls: {
manual: {
secretRef: "example-secret",
},
mode: azure_native.iotoperations.TlsCertMethodMode.Manual,
},
},
],
serviceType: azure_native.iotoperations.ServiceType.LoadBalancer,
},
resourceGroupName: "rgiotoperations",
});
import pulumi
import pulumi_azure_native as azure_native
broker_listener = azure_native.iotoperations.BrokerListener("brokerListener",
broker_name="resource-name123",
extended_location={
"name": "qmbrfwcpwwhggszhrdjv",
"type": azure_native.iotoperations.ExtendedLocationType.CUSTOM_LOCATION,
},
instance_name="resource-name123",
listener_name="resource-name123",
properties={
"ports": [
{
"authentication_ref": "example-authentication",
"port": 8080,
"protocol": azure_native.iotoperations.BrokerProtocolType.WEB_SOCKETS,
},
{
"authentication_ref": "example-authentication",
"port": 8443,
"protocol": azure_native.iotoperations.BrokerProtocolType.WEB_SOCKETS,
"tls": {
"cert_manager_certificate_spec": {
"issuer_ref": {
"group": "jtmuladdkpasfpoyvewekmiy",
"kind": azure_native.iotoperations.CertManagerIssuerKind.ISSUER,
"name": "example-issuer",
},
},
"mode": azure_native.iotoperations.TlsCertMethodMode.AUTOMATIC,
},
},
{
"authentication_ref": "example-authentication",
"port": 1883,
},
{
"authentication_ref": "example-authentication",
"port": 8883,
"tls": {
"manual": {
"secret_ref": "example-secret",
},
"mode": azure_native.iotoperations.TlsCertMethodMode.MANUAL,
},
},
],
"service_type": azure_native.iotoperations.ServiceType.LOAD_BALANCER,
},
resource_group_name="rgiotoperations")
package main
import (
iotoperations "github.com/pulumi/pulumi-azure-native-sdk/iotoperations/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iotoperations.NewBrokerListener(ctx, "brokerListener", &iotoperations.BrokerListenerArgs{
BrokerName: pulumi.String("resource-name123"),
ExtendedLocation: &iotoperations.ExtendedLocationArgs{
Name: pulumi.String("qmbrfwcpwwhggszhrdjv"),
Type: pulumi.String(iotoperations.ExtendedLocationTypeCustomLocation),
},
InstanceName: pulumi.String("resource-name123"),
ListenerName: pulumi.String("resource-name123"),
Properties: &iotoperations.BrokerListenerPropertiesArgs{
Ports: iotoperations.ListenerPortArray{
&iotoperations.ListenerPortArgs{
AuthenticationRef: pulumi.String("example-authentication"),
Port: pulumi.Int(8080),
Protocol: pulumi.String(iotoperations.BrokerProtocolTypeWebSockets),
},
&iotoperations.ListenerPortArgs{
AuthenticationRef: pulumi.String("example-authentication"),
Port: pulumi.Int(8443),
Protocol: pulumi.String(iotoperations.BrokerProtocolTypeWebSockets),
Tls: &iotoperations.TlsCertMethodArgs{
CertManagerCertificateSpec: &iotoperations.CertManagerCertificateSpecArgs{
IssuerRef: &iotoperations.CertManagerIssuerRefArgs{
Group: pulumi.String("jtmuladdkpasfpoyvewekmiy"),
Kind: pulumi.String(iotoperations.CertManagerIssuerKindIssuer),
Name: pulumi.String("example-issuer"),
},
},
Mode: pulumi.String(iotoperations.TlsCertMethodModeAutomatic),
},
},
&iotoperations.ListenerPortArgs{
AuthenticationRef: pulumi.String("example-authentication"),
Port: pulumi.Int(1883),
},
&iotoperations.ListenerPortArgs{
AuthenticationRef: pulumi.String("example-authentication"),
Port: pulumi.Int(8883),
Tls: &iotoperations.TlsCertMethodArgs{
Manual: &iotoperations.X509ManualCertificateArgs{
SecretRef: pulumi.String("example-secret"),
},
Mode: pulumi.String(iotoperations.TlsCertMethodModeManual),
},
},
},
ServiceType: pulumi.String(iotoperations.ServiceTypeLoadBalancer),
},
ResourceGroupName: pulumi.String("rgiotoperations"),
})
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 brokerListener = new AzureNative.IoTOperations.BrokerListener("brokerListener", new()
{
BrokerName = "resource-name123",
ExtendedLocation = new AzureNative.IoTOperations.Inputs.ExtendedLocationArgs
{
Name = "qmbrfwcpwwhggszhrdjv",
Type = AzureNative.IoTOperations.ExtendedLocationType.CustomLocation,
},
InstanceName = "resource-name123",
ListenerName = "resource-name123",
Properties = new AzureNative.IoTOperations.Inputs.BrokerListenerPropertiesArgs
{
Ports = new[]
{
new AzureNative.IoTOperations.Inputs.ListenerPortArgs
{
AuthenticationRef = "example-authentication",
Port = 8080,
Protocol = AzureNative.IoTOperations.BrokerProtocolType.WebSockets,
},
new AzureNative.IoTOperations.Inputs.ListenerPortArgs
{
AuthenticationRef = "example-authentication",
Port = 8443,
Protocol = AzureNative.IoTOperations.BrokerProtocolType.WebSockets,
Tls = new AzureNative.IoTOperations.Inputs.TlsCertMethodArgs
{
CertManagerCertificateSpec = new AzureNative.IoTOperations.Inputs.CertManagerCertificateSpecArgs
{
IssuerRef = new AzureNative.IoTOperations.Inputs.CertManagerIssuerRefArgs
{
Group = "jtmuladdkpasfpoyvewekmiy",
Kind = AzureNative.IoTOperations.CertManagerIssuerKind.Issuer,
Name = "example-issuer",
},
},
Mode = AzureNative.IoTOperations.TlsCertMethodMode.Automatic,
},
},
new AzureNative.IoTOperations.Inputs.ListenerPortArgs
{
AuthenticationRef = "example-authentication",
Port = 1883,
},
new AzureNative.IoTOperations.Inputs.ListenerPortArgs
{
AuthenticationRef = "example-authentication",
Port = 8883,
Tls = new AzureNative.IoTOperations.Inputs.TlsCertMethodArgs
{
Manual = new AzureNative.IoTOperations.Inputs.X509ManualCertificateArgs
{
SecretRef = "example-secret",
},
Mode = AzureNative.IoTOperations.TlsCertMethodMode.Manual,
},
},
},
ServiceType = AzureNative.IoTOperations.ServiceType.LoadBalancer,
},
ResourceGroupName = "rgiotoperations",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.iotoperations.BrokerListener;
import com.pulumi.azurenative.iotoperations.BrokerListenerArgs;
import com.pulumi.azurenative.iotoperations.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.iotoperations.inputs.BrokerListenerPropertiesArgs;
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 brokerListener = new BrokerListener("brokerListener", BrokerListenerArgs.builder()
.brokerName("resource-name123")
.extendedLocation(ExtendedLocationArgs.builder()
.name("qmbrfwcpwwhggszhrdjv")
.type("CustomLocation")
.build())
.instanceName("resource-name123")
.listenerName("resource-name123")
.properties(BrokerListenerPropertiesArgs.builder()
.ports(
ListenerPortArgs.builder()
.authenticationRef("example-authentication")
.port(8080)
.protocol("WebSockets")
.build(),
ListenerPortArgs.builder()
.authenticationRef("example-authentication")
.port(8443)
.protocol("WebSockets")
.tls(TlsCertMethodArgs.builder()
.certManagerCertificateSpec(CertManagerCertificateSpecArgs.builder()
.issuerRef(CertManagerIssuerRefArgs.builder()
.group("jtmuladdkpasfpoyvewekmiy")
.kind("Issuer")
.name("example-issuer")
.build())
.build())
.mode("Automatic")
.build())
.build(),
ListenerPortArgs.builder()
.authenticationRef("example-authentication")
.port(1883)
.build(),
ListenerPortArgs.builder()
.authenticationRef("example-authentication")
.port(8883)
.tls(TlsCertMethodArgs.builder()
.manual(X509ManualCertificateArgs.builder()
.secretRef("example-secret")
.build())
.mode("Manual")
.build())
.build())
.serviceType("LoadBalancer")
.build())
.resourceGroupName("rgiotoperations")
.build());
}
}
resources:
brokerListener:
type: azure-native:iotoperations:BrokerListener
properties:
brokerName: resource-name123
extendedLocation:
name: qmbrfwcpwwhggszhrdjv
type: CustomLocation
instanceName: resource-name123
listenerName: resource-name123
properties:
ports:
- authenticationRef: example-authentication
port: 8080
protocol: WebSockets
- authenticationRef: example-authentication
port: 8443
protocol: WebSockets
tls:
certManagerCertificateSpec:
issuerRef:
group: jtmuladdkpasfpoyvewekmiy
kind: Issuer
name: example-issuer
mode: Automatic
- authenticationRef: example-authentication
port: 1883
- authenticationRef: example-authentication
port: 8883
tls:
manual:
secretRef: example-secret
mode: Manual
serviceType: LoadBalancer
resourceGroupName: rgiotoperations
Each port in the ports array can specify a different protocol (MQTT or WebSockets) and TLS configuration. The tls property controls certificate provisioning: mode set to Automatic uses cert-manager with certManagerCertificateSpec pointing to an Issuer, while Manual mode references a Kubernetes secret via manual.secretRef. The authenticationRef property links each port to an authentication resource that validates client credentials. Setting serviceType to LoadBalancer exposes the listener externally, while ClusterIP keeps it internal to the cluster.
Beyond these examples
These snippets focus on specific listener-level features: port configuration and protocol selection, TLS certificate management (automatic and manual), and service exposure (ClusterIP and LoadBalancer). They’re intentionally minimal rather than full IoT broker deployments.
The examples reference pre-existing infrastructure such as IoT Operations broker and instance resources, Azure Arc custom location, authentication and authorization resources, and cert-manager Issuer and Kubernetes secrets. They focus on configuring the listener rather than provisioning the entire IoT Operations stack.
To keep things focused, common listener patterns are omitted, including:
- Authorization policies (authorizationRef)
- NodePort configuration for external access
- Service naming (serviceName)
- Advanced TLS options (certificate rotation, SAN configuration)
These omissions are intentional: the goal is to illustrate how each listener feature is wired, not provide drop-in IoT modules. See the BrokerListener resource reference for all available configuration options.
Let's configure Azure IoT Operations Broker Listeners
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration Basics
extendedLocation, brokerName, instanceName, listenerName, and resourceGroupName. Changes to these require resource replacement.extendedLocation (with type CustomLocation), brokerName, instanceName, listenerName, resourceGroupName, and at least one port in the ports array.extendedLocation.type must be CustomLocation, as shown in all examples.TLS & Security
certManagerCertificateSpec with an issuerRef to automatically provision certificates via cert-manager. Manual mode uses manual.secretRef to reference an existing Kubernetes secret containing the certificate.tls object to the port configuration with mode set to either Automatic or Manual. For automatic, provide certManagerCertificateSpec with an issuerRef. For manual, provide manual.secretRef pointing to your certificate secret.authenticationRef and authorizationRef are optional. The simple example shows a port without these fields.Networking & Ports
ports array supports multiple port configurations. Each port can have its own protocol, authentication, authorization, and TLS settings.protocol field is optional. You can specify Mqtt or WebSockets explicitly, or leave it unspecified.ClusterIp exposes the listener only within the Kubernetes cluster, while LoadBalancer provisions an external load balancer for external access.Advanced Configuration
nodePort property is optional and specifies a static port on each cluster node. It’s shown in the full example but not required for basic configurations.