Skip to content
Open

2.2.0 #104

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@
* [Not a tuning guide](guides/not-a-tuning-guide.md)
* [Change Open File Limits](guides/change-open-file-limits.md)
* [Migrating to 2.0](guides/migration-to-2-0.md)
* [VerneMQ 2.2.0](guides/vernemq-2.2.0.md)
17 changes: 16 additions & 1 deletion administration/listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ You can isolate client connections accepted by a certain listener from other cli

To start an MQTT listener using defaults, just set the port and IP address as a minimum.

### Authentication and authorization plugin chains

Listeners started with `vmq-admin listener start` can define their own authentication and authorization plugin chains. Use `--auth_plugins` for authentication hooks and `--authz_plugins` for authorization hooks. The configured order is preserved.

```text
vmq-admin listener start address=192.168.1.50 port=1884 --auth_plugins=[vmq_passwd] --authz_plugins=[vmq_acl]
```

The same flags can be used when starting WebSocket listeners:

```text
vmq-admin listener start address=192.168.1.50 port=8888 --websocket --auth_plugins=[vmq_webhooks,vmq_passwd] --authz_plugins=[vmq_webhooks]
```

If no listener-specific chain is configured, VerneMQ uses the globally enabled plugin chain.

## Stopping a listener

```text
Expand All @@ -69,4 +85,3 @@ vmq-admin listener restart address=192.168.1.50 port=1884
```text
vmq-admin listener delete address=192.168.1.50 port=1884
```

31 changes: 30 additions & 1 deletion clustering/communication.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,36 @@ listener.vmq.clustering = 0.0.0.0:44053
It isn't necessary to configure the same port on every machine, as the nodes will probe each other for this information.
{% endhint %}

## Internode MQTT Delivery

VerneMQ uses MQTT connections between cluster nodes to deliver MQTT messages to subscribers on remote nodes. In most deployments, the defaults should be left unchanged. The following settings are advanced options for deployments that need to tune behavior around slow peers, short disconnects, reconnect handshakes, or unusually large bursts of internode traffic.

`outgoing_cluster_handshake_ack_timeout` configures how long a node waits for the receiving side to acknowledge an outgoing cluster delivery connection before assuming legacy behavior. The value is in milliseconds and defaults to `250`.

```text
outgoing_cluster_handshake_ack_timeout = 250
```

`incoming_clustering_buffer_size` limits how many bytes are buffered while parsing incoming internode MQTT traffic. Malformed or oversized cluster frames are rejected instead of being buffered indefinitely. The value is in bytes and defaults to `67108864`.

```text
incoming_clustering_buffer_size = 67108864
```

`outgoing_clustering_buffer_size` configures how many bytes are buffered when a remote node is temporarily unavailable. The value is in bytes and defaults to `67108864`.

```text
outgoing_clustering_buffer_size = 67108864
```

`outgoing_clustering_flush_threshold` configures how many pending outgoing bytes are batched before VerneMQ eagerly flushes internode traffic. The value is in bytes and defaults to `65536`.

```text
outgoing_clustering_flush_threshold = 65536
```

Change these values only after testing with realistic cluster traffic. Setting buffers too low can increase dropped internode traffic during transient disconnects, while setting them too high can increase memory usage under sustained peer or network problems.

**Attributions:**

This section, "VerneMQ Inter-node Communication", is a derivative of Security and Firewalls by Riak, used under Creative Commons Attribution 3.0 Unported License.

19 changes: 18 additions & 1 deletion configuration/advanced_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ Specify how queues should process messages, either the `fifo` or `lifo` way, wit
queue_type = fifo
```

## Fanout Sharding

Fanout sharding can increase throughput and lower backpressure in high-frequency publish scenarios where a topic fanout has to deliver to many subscribers. It splits local fanout work over multiple fanout shards.

`fanout.shard_count` configures the number of local fanout shards. The default is `1`, which preserves the previous behavior.

```text
fanout.shard_count = 8
```

`fanout.async_handoff` decouples the publisher from local shard delivery work. This can further reduce publisher backpressure, but local match counts are not exact when async handoff is enabled. The default is `off`.

```text
fanout.async_handoff = on
```

These settings are experimental and should be changed only after load testing with traffic patterns close to production.

## Max Message Rate

Specifies the maximum incoming publish rate per session per second. Depending on the underlying network buffers this rate isn't enforced. Defaults to `0`, which means no rate limits apply. Setting to a value of `2` limits any publisher to 2 messages per second, for instance.
Expand Down Expand Up @@ -81,4 +99,3 @@ listener.max_connection_lifetime = 25000
```

It is possible to override the value in auth_on_register(_m5) to a lower limit.

4 changes: 2 additions & 2 deletions configuration/http-listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ listener.http.default = 127.0.0.1:8888
You can have multiple HTTP(s) listener listening to different port and running different modules:
```text
listener.https.default = 127.0.0.1:443
listeners.https.default.http_modules = vmq_status_http, vmq_health_http, vmq_metrics_http
listener.https.default.http_modules = vmq_status_http, vmq_health_http, vmq_metrics_http

listener.https.mgmt = 127.0.0.1:444
listeners.https.mgmt.http_modules = vmq_mgmt_http
listener.https.mgmt.http_modules = vmq_mgmt_http
```

This configuration snippet defines two HTTPS listeners with different modules. One for default traffic and one for management traffic. It specifies which HTTP modules will be enabled on each listener, allowing for status, health, and metrics information to be retrieved from the default listener and providing a web-based interface for managing and monitoring VerneMQ through the management listener.
86 changes: 85 additions & 1 deletion configuration/listeners.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,91 @@ listener.ssl.my_listener.tls_handshake_timeout = 8000
mqtt.connect.timeout = 30000
```

## Active Socket Packets

For TCP and SSL listeners, `active_n` controls how many incoming TCP packets may be delivered before the socket switches back to passive mode. The default value is `1`, which preserves the previous `{active, once}` behavior. Valid values are integers from `1` to `32767`.

The value can be configured on the protocol level or overridden for a named listener:

```text
listener.tcp.active_n = 10
listener.ssl.active_n = 10

listener.tcp.my_listener.active_n = 100
listener.ssl.my_listener.active_n = 100
```

## Per-Listener Authentication and Authorization

Listeners can define their own authentication and authorization plugin chains. If no per-listener chain is configured, the globally enabled plugin chain is used. The configured order is preserved.

Configure authentication plugins with `auth_plugins` and authorization plugins with `authz_plugins`:

```text
listener.tcp.internal = 127.0.0.1:1883
listener.tcp.internal.auth_plugins = [vmq_passwd]
listener.tcp.internal.authz_plugins = [vmq_acl]

listener.wss.external = 0.0.0.0:8884
listener.wss.external.auth_plugins = [vmq_webhooks, vmq_passwd]
listener.wss.external.authz_plugins = [vmq_webhooks]
```

This setting is available for TCP, SSL, WebSocket, and secure WebSocket listeners:

```text
listener.tcp.my_listener.auth_plugins = [vmq_passwd]
listener.ssl.my_listener.auth_plugins = [vmq_passwd]
listener.ws.my_listener.auth_plugins = [vmq_webhooks]
listener.wss.my_listener.auth_plugins = [vmq_webhooks]

listener.tcp.my_listener.authz_plugins = [vmq_acl]
listener.ssl.my_listener.authz_plugins = [vmq_acl]
listener.ws.my_listener.authz_plugins = [vmq_webhooks]
listener.wss.my_listener.authz_plugins = [vmq_webhooks]
```

## Anonymous Access Override

`allow_anonymous_override` allows a named listener to override a global `allow_anonymous = off` setting. Its main use case is a listener that authenticates clients outside the normal MQTT authentication plugin chain, for example with client certificates.

The global and listener-specific values are OR'ed together. This means a listener can allow anonymous access when the global setting is `off`, but a listener cannot disable anonymous access when the global setting is `on`.

```text
allow_anonymous = off

listener.ssl.mtls = 0.0.0.0:8883
listener.ssl.mtls.require_certificate = on
listener.ssl.mtls.allow_anonymous_override = on
```

The setting is available for TCP, SSL, WebSocket, and secure WebSocket listeners:

```text
listener.tcp.my_listener.allow_anonymous_override = on
listener.ssl.my_listener.allow_anonymous_override = on
listener.ws.my_listener.allow_anonymous_override = on
listener.wss.my_listener.allow_anonymous_override = on
```

## Forward Connection Options

`forward_connection_opts` passes listener metadata to the extended `auth_on_register` and `auth_on_register_m5` hooks. Enable it if an authentication plugin needs to make decisions based on listener information such as the transport or listener name.

The setting can be configured on the protocol level or for a named listener:

```text
listener.tcp.forward_connection_opts = on
listener.ssl.forward_connection_opts = on
listener.ws.forward_connection_opts = on
listener.wss.forward_connection_opts = on

listener.tcp.my_listener.forward_connection_opts = on
listener.ssl.my_listener.forward_connection_opts = on
listener.ws.my_listener.forward_connection_opts = on
listener.wss.my_listener.forward_connection_opts = on
```

## SSL/TLS Support
VerneMQ supports different Transport Layer Security (TLS) options, which allow for secure communication between MQTT clients and VerneMQ.

Expand Down Expand Up @@ -152,4 +237,3 @@ With SSL, you still need to configure authentication and authorization! That is,

The default listener `listener.vmq.clustering` is used for distributing MQTT messages among the cluster nodes.
{% endhint %}

10 changes: 10 additions & 0 deletions configuration/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ max_inflight_messages = 20

Defaults to `20` messages, use `0` for no limit. The inflight window serves as a protection for sessions, on the incoming side.

## Subscriptions per Client

This option defines the maximum number of subscriptions a client can have. Existing subscriptions can be replaced even after the limit is reached.

```text
max_subscriptions_per_client = 0
```

Defaults to `0`, which means no limit applies. This setting can be used as a guardrail against clients creating too many subscriptions.

## Load Shedding

The maximum number of messages to hold in the queue above those messages that are currently in flight. Defaults to `1000`. Set to `-1` for no limit. This option protects a client session from overload by dropping messages \(of any QoS\).
Expand Down
55 changes: 55 additions & 0 deletions guides/vernemq-2.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# VerneMQ 2.2.0

VerneMQ 2.2.0 adds runtime compatibility updates, listener-level configuration improvements, performance options, and operational examples. This page summarizes the most relevant user-facing changes and links to the detailed documentation.

## Runtime Support

VerneMQ 2.2.0 supports running on Erlang/OTP 28 and Erlang/OTP 29.

## Fanout Sharding

Fanout sharding can increase throughput and lower backpressure for high-frequency publishers where local topic fanout has to deliver to many subscribers. The related advanced settings are `fanout.shard_count` and `fanout.async_handoff`.

See [Advanced Options](../configuration/advanced_options.md#fanout-sharding).

## Subscription Limit Guardrail

The new `max_subscriptions_per_client` setting limits how many subscriptions a client can have. A value of `0` keeps the default unlimited behavior.

See [MQTT Options](../configuration/options.md#subscriptions-per-client).

## Per-Listener Auth Chains

MQTT listeners can define their own authentication and authorization plugin chains with `auth_plugins` and `authz_plugins`. This allows different listeners to use different authentication and authorization behavior without changing the global plugin chain.

See [MQTT Listeners](../configuration/listeners.md#per-listener-authentication-and-authorization) and [Managing Listeners](../administration/listeners.md#authentication-and-authorization-plugin-chains).

## Forward Connection Options

`forward_connection_opts` can pass listener metadata to `auth_on_register` and `auth_on_register_m5` hooks. Plugins can use that metadata to implement different behavior based on the listener that accepted the client connection.

See [MQTT Listeners](../configuration/listeners.md#forward-connection-options) and [Session lifecycle](../plugindevelopment/sessionlifecycle.md#listener-metadata).

## Listener active_n

TCP and SSL listeners support `active_n`, which controls how many incoming TCP packets may be delivered before the socket switches back to passive mode. The default is `1`, preserving the previous behavior.

See [MQTT Listeners](../configuration/listeners.md#active-socket-packets).

## WebSocket Anonymous Override

`allow_anonymous_override` is now available for WebSocket and secure WebSocket listeners as well as TCP and SSL listeners. This allows a named listener to override a global `allow_anonymous = off` setting.

See [MQTT Listeners](../configuration/listeners.md#anonymous-access-override).

## Cluster and Internode Robustness

VerneMQ 2.2.0 improves internode MQTT delivery with a connect-ack handshake, bounded inbound buffering, outgoing batching, and larger default outgoing clustering buffers. These settings are advanced and should usually be left at their defaults.

See [Inter-node Communication](../clustering/communication.md#internode-mqtt-delivery).

## Prometheus Alert Rules Template

VerneMQ ships with a minimal Prometheus alert rules template in `metrics_scripts/prometheus/vernemq-alert-rules.yml`. The template is intended as a starting point and should be extended or adapted to the thresholds, labels, severities, and runbooks of each deployment.

See [Prometheus](../monitoring/prometheus.md#example-alert-rules).
10 changes: 10 additions & 0 deletions monitoring/health-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,13 @@ In addition to the simple `/health` path, the following options are available as
With the `ping` or `listeners` option, you can configure a health check for a single node, even if it is part of a cluster.

If you want to configure any automated actions based on the health check results, you need to chose an appropriate health check path. For example, you should not use the `/health` check (checking for full cluster consistency) to automatically restart a single node. This is of special importance for Kubernetes deployments.

## Cluster readiness timeout

Cluster readiness checks use parallel RPC calls to check cluster nodes. The total timeout for this check is controlled by `cluster_ready_rpc_timeout` and defaults to `5000` milliseconds.

```text
cluster_ready_rpc_timeout = 5000
```

The timeout applies to the whole readiness check, not once per cluster node. In most deployments, the default should be left unchanged.
26 changes: 26 additions & 0 deletions monitoring/prometheus.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,29 @@ This tells Prometheus to scrape the VerneMQ metrics endpoint every 5 seconds.

Please follow the documentation on the [Prometheus](http://prometheus.io) website to properly configure the metrics scraping as well as how to access those metrics and configure alarms and graphs.

## Example Alert Rules

VerneMQ ships with a minimal Prometheus alert rules template in `metrics_scripts/prometheus/vernemq-alert-rules.yml`. The template contains baseline alerts for broker availability, scheduler utilization, memory usage, queue drops, socket errors, keepalive expirations, and cluster-related signals.

The template is intended as a starting point. Extend and adapt thresholds, severities, labels, job matchers, and runbook hints for your own deployment and use cases.

To install the template, copy it to your Prometheus rules directory and reference it from `prometheus.yml`:

```yaml
rule_files:
- /etc/prometheus/vernemq-alert-rules.yml
```

Validate the rules before reloading Prometheus:

```text
promtool check rules /etc/prometheus/vernemq-alert-rules.yml
```

The example rules assume the default VerneMQ Prometheus namespace:

```text
prometheus_namespace = vernemq_
```

If you changed `prometheus_namespace`, update the metric name prefixes in the alert rules accordingly.
38 changes: 37 additions & 1 deletion plugindevelopment/sessionlifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,43 @@ The `auth_on_register` and `auth_on_register_m5` hooks allow your plugin to gran

Every plugin that implements the `auth_on_register` or `auth_on_register_m5` hooks are part of a conditional plugin chain. For this reason we allow the hook to return different values depending on how the plugin grants or rejects this client. In case the plugin doesn't know the client it is best to return `next` as this would allow subsequent plugins in the chain to validate this client. If no plugin is able to validate the client it gets automatically rejected.

### Listener metadata

If `forward_connection_opts` is enabled for a TCP, SSL, WebSocket, or secure WebSocket listener, VerneMQ calls the extended auth hook variant with listener metadata as the last argument.

```text
listener.tcp.my_listener.forward_connection_opts = on
listener.ssl.my_listener.forward_connection_opts = on
listener.ws.my_listener.forward_connection_opts = on
listener.wss.my_listener.forward_connection_opts = on
```

For MQTT 3.x clients, implement `auth_on_register/6` instead of `auth_on_register/5`:

```erlang
auth_on_register(Peer, SubscriberId, User, Password, CleanSession, Opts) ->
...
```

For MQTT 5 clients, implement `auth_on_register_m5/7` instead of `auth_on_register_m5/6`:

```erlang
auth_on_register_m5(Peer, SubscriberId, User, Password, CleanStart, Properties, Opts) ->
...
```

`Opts` is a map containing listener information:

```erlang
#{listener_addr := {127, 0, 0, 1},
listener_port := 1883,
listener_type := mqtt}
```

The `listener_type` value is one of `mqtt`, `mqtts`, `mqttws`, or `mqttwss`. This allows an authentication plugin to choose different authentication behavior depending on the listener that accepted the connection.

For TLS listeners with client certificates, `Opts` also includes `client_cert`, containing the peer certificate binary returned by `ssl:peercert/1`. The common name is not extracted for this option.

## on\_auth\_m5

The `on_auth_m5` hook allows your plugin to implement MQTT enhanced authentication, see [Enhanced Authentication Flow](enhancedauthflow.md).
Expand All @@ -29,4 +66,3 @@ This hook is called if an MQTT 3.1/3.1.1 client using `clean_session=false` or a
## on\_client\_gone

This hook is called if an MQTT 3.1/3.1.1 client using `clean_session=true` or an MQTT 5.0 client with the `session_expiry_interval` set to zero closes the connection or gets disconnected by a duplicate client. The hook is specified in the Erlang behaviour [on\_client\_gone\_hook](https://github.com/vernemq/vernemq_dev/blob/master/src/on_client_gone_hook.erl) available in the [vernemq\_dev](https://github.com/vernemq/vernemq_dev) repo.

7 changes: 6 additions & 1 deletion plugindevelopment/webhookplugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ For detailed information about the hooks and when they are called, see the secti
Note, when overriding a **mountpoint** or a **client-id** both have to be returned by the webhook implementation for it to have an effect.
{% endhint %}

### Cancellable authentication requests

For the `auth_on_register` and `auth_on_register_m5` hooks, VerneMQ cancels the in-flight HTTP request if the client connection closes while the webhook call is still waiting for a response. This prevents disconnected clients from leaving authentication webhook calls running until the normal response timeout is reached.

The endpoint may still receive the HTTP request before cancellation reaches it. Authentication endpoints should therefore treat requests as idempotent and avoid relying on every request producing a completed VerneMQ authentication decision.

### Responses

All hooks, unless stated otherwise, respond with a JSON-encoded payload and a success code of 200. All hooks support responding with "ok", indicated that the request was successful.
Expand Down Expand Up @@ -807,4 +813,3 @@ vmq_webhooks.webhook3.endpoint = http://127.0.0.1:8080
vmq_webhooks.webhook4.hook = auth_on_subscribe_m5
vmq_webhooks.webhook4.endpoint = http://127.0.0.1:8080
```