# Listener Configuration

In EMQX, listener is configured to receive requests from MQTT clients. EMQX supports the following message transfer protocols, including:

- TCP: port  `1883`
- SSL: port `8883`
- Websocket listener: `8083`
- Secure websocket listener: `8084`

::: tip

You can also configure listeners via Dashboard by clicking **Management** -> **Listeners** on the left navigation menu of the Dashboard.
If you want to configure listeners from config files, it is recommended to use `base.hocon` instead of `emqx.conf`.
This is because if the configuration is set in emqx.conf, any changes made through the Dashboard will only be temporary and will be lost upon EMQX restart.

:::

::: tip

EMQX offers more configuration items to better serve customized needs. For details, see the [EMQX Enterprise Configuration Manual](https://docs.emqx.com/en/enterprise/v6.3.1/hocon/).

:::

## How EMQX Determines the Listener Address

A listener address determines the local network interfaces and port on which EMQX receives client connections.

A listener's `bind` setting accepts an explicit IP address and port, such as `"0.0.0.0:1883"`, or a port alone, such as `1883`. Starting from EMQX 6.3.0, the node-level `node.default_listener_address` setting controls the address used by listeners whose binds specify only a port.

EMQX selects the address in the following order:

1. If `bind` includes an IP address, EMQX uses that address. Neither `node.default_listener_address` nor the security profile overrides it.
2. If `bind` specifies only a port and `node.default_listener_address` is set, EMQX uses the address selected by that setting on the local node.
3. Otherwise, MQTT listeners use the security profile's default: all network interfaces under `legacy`, or the loopback address under `hardened`. The loopback address is accessible only from the local host.

The configured `bind` value stays unchanged. For example, `bind = 1883` remains a port-only value even when the listener uses a specific IP address at runtime.

The TCP, SSL, and WebSocket configuration examples below use explicit IP addresses, so they are not affected by the default listener address setting.

For supported values and startup behavior, see [Default Listener Address](../access-control/security-profile.md#default-listener-address). The official Docker image sets its own default; see [Listener Addresses in Docker](../../get-started/deploy/install-docker.md#listener-addresses-in-docker).

## Configure TCP Listener

TCP listener is a network service that listens for incoming TCP connections on a specific network port. It plays an essential role in establishing and managing connections between clients and EMQX over TCP/IP networks. 

To configure the TCP listener in EMQX, you can add the `listeners.tcp` configuration items in the `base.hocon` file within the `etc` folder of the EMQX installation directory.

For example, to enable the TCP listener on port `1883`, with a maximum 1,024,000 of concurrent connections allowed by the listener, you can work the code below:

```bash
listeners.tcp.default {
  bind = "0.0.0.0:1883"
  max_connections = 1024000
}
```

where, 

- `listeners.tcp.default` is to enable the listener, and here `default` is the name of the listener, you can change it to your own listener name. 

- `bind` is to set the IP address and port of the listener, here it will listen to all incoming traffic from any IP address on port `1883`. 
- `max_connection` is to set the maximum number of concurrent connections allowed by the listener; default value: `infinity`.

## Configure SSL Listener

SSL listener is a network service that listens for incoming SSL (Secure Sockets Layer) connections. In EMQX, it is used to secure network traffic between a client and EMQX by encrypting the data that is transmitted between them.

To configure the SSL listener in EMQX, you can add the `listeners.ssl` configuration items in the `base.hocon` file within the `etc` folder of the EMQX installation directory.

For example, to enable the SSL listener on port `8883`, with a maximum 1,024,000 of concurrent connections allowed by the listener:

```bash
listeners.ssl.default {
  bind = "0.0.0.0:8883"
  max_connections = 1024000
  ssl_options {
    cacertfile = "etc/certs/cacert.pem"
    certfile = "etc/certs/cert.pem"
    keyfile = "etc/certs/key.pem"
    verify = verify_none
    fail_if_no_peer_cert = false
  }
}
```

where:

- `listeners.ssl.default` is to enable the listener. 

- `bind` is the IP address and port of the listener, here it will listen to all incoming traffic from any IP address on port `8883`. 
- `max_connection` is the maximum number of concurrent connections allowed by the listener, default value: `infinity`.
- `ssl_options` is the SSL/TLS configuration option for the listener, it has three properties:
  - `cacertfile`: PEM file containing the trusted CA (certificate authority) certificates that the listener uses to verify the authenticity of the client certificates.
  - `certfile`: PEM file containing the SSL/TLS certificate chain for the listener. If the certificate is not directly issued by a root CA, the intermediate CA certificates should be appended after the listener certificate to form a chain.
  - `keyfile`: PEM file containing the private key corresponding to the SSL/TLS certificate.
  - `verify`:  Set 'verify_peer' to verify the authenticity of the clients' certificates, otherwise 'verify_none'.
  - `fail_if_no_peer_cert`: If set to `true`, the server fails if the client does not have a certificate to send, that is, sends an empty certificate. If set to false, it fails only if the client sends an invalid certificate (an empty certificate is considered valid).

## Configure WebSocket Listener

A WebSocket listener is a network service that receives and processes messages over WebSocket. WebSocket support in EMQX allows clients to use the WebSocket protocol to connect to EMQX and exchange data in real-time.

For an overview of how MQTT over WebSocket works and typical usage scenarios, see [MQTT over WebSocket](../../develop/connect-emqx/mqtt-over-websocket.md).

To configure the WebSocket listener in EMQX, you can add the `listeners.ws` configuration items in the `base.hocon` file within the `etc` folder of the EMQX installation directory.

For example, to enable the WebSocket listener on port `8083`, with a maximum 1,024,000 of concurrent connections allowed by the listener:

```bash
listeners.ws.default {
  bind = "0.0.0.0:8083"
  max_connections = 1024000
  websocket.mqtt_path = "/mqtt"
}
```

where:

- `listeners.ws.default` is to enable the listener. 

- `bind` is the IP address and port of the listener, here it will listen to all incoming traffic from any IP address on port `8083`. 
- `max_connection` is the maximum number of concurrent connections allowed by the listener, default value: `infinity`.
- `websocket.mqtt_path` is to set the path to the WebSocket’s MQTT protocol, which is `/mqtt` by default. 

## Configure Secure WebSocket Listener

A secure WebSocket listener is a WebSocket listener that uses the Secure Sockets Layer (SSL) or Transport Layer Security (TLS) protocol to encrypt the data exchanged between a WebSocket client and the broker. In EMQX, the secure WebSocket listener is an important security measure to protect sensitive data exchanged between WebSocket clients and EMQX> 

To configure the secure WebSocket listener in EMQX, you can add the `listeners.wss` configuration items in the `base.hocon` file within the `etc` folder of the EMQX installation directory.

For example, to enable the Secure WebSocket listener on port `8084`, with a maximum 1,024,000 of concurrent connections allowed by the listener:

```bash
listeners.wss.default {
  bind = "0.0.0.0:8084"
  max_connections = 1024000
  websocket.mqtt_path = "/mqtt"
  ssl_options {
    cacertfile = "etc/certs/cacert.pem"
    certfile = "etc/certs/cert.pem"
    keyfile = "etc/certs/key.pem"
  }
}
```

where:

- `listeners.wss.default` is to enable the listener. 

- `bind` is the IP address and port of the listener, here it will listen to all incoming traffic from any IP address on port `8084`. 
- `max_connection` is the maximum number of concurrent connections allowed by the listener, default value: `infinity`.
- `websocket.mqtt_path` is to set the path to the WebSocket’s MQTT protocol, which is `/mqtt` by default. 
- `ssl_options` is the SSL/TLS configuration option for the listener, it has three properties:
  - `cacertfile`: PEM file containing the trusted CA (certificate authority) certificates that the listener uses to verify the authenticity of the client certificates.
  - `certfile`: PEM file containing the SSL/TLS certificate chain for the listener. If the certificate is not directly issued by a root CA, the intermediate CA certificates should be appended after the listener certificate to form a chain.
  - `keyfile`: PEM file containing the private key corresponding to the SSL/TLS certificate.

## Use a Different Address on Each Node

Listener configuration changes made through the Dashboard, REST API, or CLI are replicated across the cluster. If you put one node's IP address in `bind`, the listener cannot bind to that address on other nodes unless the IP address is configured on a local network interface of those nodes. To use a different address on each node, keep the listener's bind as a port and configure the default address separately on each node.

Use `base.hocon` for listener settings, and `emqx.conf` or environment variables for the node-level default listener address. For example, to use the host part of each node's Erlang node name:

1. Set the TCP listener's bind to `1883` through the Dashboard, or configure the following in each node's `etc/base.hocon`:

   ```hocon
   listeners.tcp.default.bind = 1883
   ```

   If a higher-priority configuration source already sets an explicit bind address, update that source instead. See [Config Override Rules](./configuration.md#config-override-rules).

2. Add the following to each node's `emqx.conf`:

   ```hocon
   node.default_listener_address = "nodename"
   ```

   For Docker deployments, pass `-e EMQX_NODE__DEFAULT_LISTENER_ADDRESS=nodename` to `docker run`, or set `EMQX_NODE__DEFAULT_LISTENER_ADDRESS: nodename` in the Docker Compose service's `environment` section. This overrides the official image's `all` default, which takes precedence over the value in `emqx.conf`.

   EMQX uses the host part after `@` in the node name, resolving it at node startup if it is a hostname. Ensure that it resolves to an address available on that node. A hostname that cannot be resolved prevents the node from starting.

3. Restart each node to apply `node.default_listener_address`. This setting affects all port-only binds for MQTT listeners, gateway listeners, and the Dashboard HTTP listener on that node. Explicit IP addresses in listener binds remain unchanged.

You can also set `EMQX_NODE__DEFAULT_LISTENER_ADDRESS` in the node's environment. Environment variables take precedence over `emqx.conf`.

## View Listener Address Information

Starting from EMQX 6.3.0, you can view the resolved address and its source without changing the listener's configured `bind`. Use either the CLI or the REST API to query a node.

### Query a Node with the CLI

Run the following command on the node you want to check:

```bash
emqx ctl listeners
```

Check `listen_on` for the configured bind, `resolved_address` for the resolved IP, and `resolved_address_from` for the address source. Also check `running` to confirm whether the listener is running: a stopped listener can still report a resolved address. See [Listener Address Information](../cli.md#listener-address-information) for field meanings, including what an empty `resolved_address` value means.

### Query a Listener with the REST API

To check a listener through the REST API, use `GET /api/v5/listeners/:id`, for example `GET /api/v5/listeners/tcp:default`. The response reports the address on the node handling the request. Use [API authentication](../api.md#authentication) as required.

The `bind` field keeps the configured value, including the port. `resolved_address` and `resolved_address_from` are read-only information; change `bind` or `node.default_listener_address` to change the address, rather than editing these response fields.

These queries cover MQTT listeners. For gateway listeners, use the [gateway listener query](../../develop/gateway/gateway.md#listener).

## Forwarded Client Address (WebSocket Listeners)

WebSocket and secure WebSocket listeners have two options that control how EMQX determines a client's source address when the listener sits behind a proxy or load balancer:

- `websocket.proxy_address_header`: Specifies the HTTP header that carries the client IP address.
- `websocket.proxy_port_header`: Specifies the HTTP header that carries the client port.

Starting from EMQX 6.3.0, both options default to `""`. EMQX uses the corresponding TCP peer address or port for any option left empty. To obtain either value from a trusted proxy, explicitly configure the corresponding header name, such as `x-forwarded-for` or `x-forwarded-port`.

When the configured header is present on the WebSocket upgrade request, EMQX uses the first (leftmost) entry of the header value as the client's source IP address (or port) instead of the address of the real TCP peer. The derived address is what IP-based authorization rules, banned clients, flapping detection, and audit and trace logs see as the client's source IP. Configured header names are matched case-insensitively.

::: warning Trust Forwarded Address Headers Only Behind a Trusted Proxy

The header value determines the client source IP that EMQX uses, so it must be honored only when a trusted proxy sets it:

- If the listener is directly reachable by clients (no proxy in front), keep `proxy_address_header` and `proxy_port_header` empty so that EMQX always uses the real TCP peer address.
- If there is a proxy but it **appends** its observation to an inbound `X-Forwarded-For` header instead of overwriting or stripping it (appending is the default behavior of most proxies, for example NGINX's `$proxy_add_x_forwarded_for`), the leftmost entry that EMQX reads is still the one supplied by the client, so the source IP can still be spoofed. Configure the proxy to overwrite the header with the address it observed, use the [PROXY protocol](../cluster/lb.md) instead, or set the options to `""`.
- Do not try to disable the mechanism by pointing the option at an unused header name: a client can send a header by any name. The empty string is the only value a client can never supply.

When `proxy_protocol = true` is set on the listener, the client address comes from the PROXY protocol handshake, and these headers are not consulted.
:::

<!--To add QUIC-->

<!--To add code sample for adding multiple listeners.-->

## Link Listener to a Configuration Zone

Each listener in EMQX is associated with a zone, which by default is set to a logical zone named `default`.

When a listener is linked to a specific zone, MQTT clients connected to that listener inherit the settings from that zone.

For more information, see the [Zone Override](./configuration.md#zone-override) section in the configuration documentation.

## Mountpoint

Each listener can be configured with a `mountpoint`: a topic prefix that EMQX adds to topics used by clients connected through the listener. The prefix is added to topics in `PUBLISH` packets, `SUBSCRIBE` and `UNSUBSCRIBE` requests, and Will messages, and removed from the topics of messages delivered to the client. The mountpoint is transparent to the client and is commonly used to isolate topic spaces between groups of clients, for example in multi-tenant deployments.

```bash
listeners.tcp.demo {
    bind = "0.0.0.0:1883"
    mountpoint = "department-a/"
}
```

The mountpoint supports the placeholders `${clientid}`, `${username}`, `${zone}`, and `${client_attrs.NAME}`. For example, with `mountpoint = "${username}/"`, when a client with username `u1` subscribes to `sensors/#`, the subscription is internally created as `u1/sensors/#`.

### Incompatibility with Topic-Prefix Extension Features

Several EMQX features are triggered by publishing or subscribing to topics that start with a special `$` prefix. EMQX adds the mountpoint prefix before it matches these prefixes. For example, if a client connects through a listener with mountpoint `mp/` and publishes to `$delayed/10/t`, the broker receives the topic as `mp/$delayed/10/t`, which no longer starts with `$delayed/`. The feature is silently bypassed: EMQX routes the message as an ordinary message to the mounted literal topic, and no error is reported to the client.

::: warning Compatibility Limitation
Do not configure a mountpoint on listeners whose clients use any of the following features:

| Feature | Topic Prefix |
| --- | --- |
| [Delayed Publish](../../get-started/messaging/mqtt-delayed-publish.md) | `$delayed/` |
| [File Transfer](../../develop/file-transfer/introduction.md) | `$file/`, `$file-async/`, `$file-response/` |
| [Message Queue](../../develop/message-queue/message-queue-concept.md) | `$queue/` |
| [MQTT Streams](../../develop/mqtt-stream/mqtt-stream-concept.md) | `$stream/` |
| [Cluster Linking](../../develop/cluster-linking/introduction.md) | `$LINK/` |
| [Dynamic Keep Alive Adjustment](./mqtt.md#dynamic-keep-alive-adjustment) | `$SETOPTS/` |
| [A2A over MQTT](../../develop/emqx-ai/a2a-over-mqtt/overview.md) | `$a2a/` |

For Cluster Linking, the mountpoint must not be set on the listener that accepts connections from the linked cluster. For A2A over MQTT, a mountpoint of exactly one topic level (for example `acme/`) still works: EMQX parses it as a namespace prefix on `$a2a` topics.
:::

[Shared subscriptions](../../get-started/messaging/mqtt-shared-subscription.md) (`$share/{group}/`) and [exclusive subscriptions](../../get-started/messaging/mqtt-exclusive-subscription.md) (`$exclusive/`) are exceptions: they work with a mountpoint. EMQX parses these subscription prefixes before applying the mountpoint, so the mountpoint is added only to the inner topic filter. For example, subscribing to `$share/g/t` through a listener with mountpoint `mp/` joins the shared subscription group `g` on the topic `mp/t`.
