bext.dev
DocsProtocols
Protocols4 min read
On this page

MQTT Gateway

bext acts as an MQTT 5 gateway broker — IoT devices connect via standard MQTT, and messages route into bext's plugin system and pub/sub infrastructure. bext is not a full-persistence broker; it bridges MQTT traffic into your application logic.

Enabling MQTT#

Add a [mqtt] section to bext.config.toml:

toml
[mqtt]
enabled = true
bind = "0.0.0.0:1883"
tls_bind = "0.0.0.0:8883"
max_connections = 10000
max_packet_size_bytes = 65536

Compile with the mqtt feature flag:

bash
bext build --features mqtt

Listener Ports#

MQTT runs on its own TCP listeners, separate from the HTTP port:

Port Protocol Description
1883 MQTT Plain TCP (LAN / dev use).
8883 MQTTS TLS-encrypted (production).

TLS uses the same certificate configured in the site's [tls] section.

Gateway Model#

bext is a gateway, not a standalone broker. This means:

  • Incoming MQTT publishes are forwarded to bext plugins and the internal pub/sub bus.
  • Plugins can subscribe to MQTT topics and react to messages.
  • There is no built-in disk-backed message persistence. Messages that cannot be delivered are dropped after QoS retries.
code
  IoT Device ──mqtt──▶ bext ──▶ Plugin handler
                         │
                         └──▶ PubSub bus (SSE, WebSocket subscribers)

MQTT 5 Features#

bext implements the MQTT 5.0 protocol (RFC 9431):

Quality of Service#

QoS Level Guarantee Use Case
0 At most once (fire and forget) Sensor telemetry.
1 At least once (ack required) Commands, alerts.
2 Exactly once (4-step handshake) Billing, state changes.

Sessions#

  • Clean Start — client starts fresh, no stored state.
  • Persistent Session — bext stores subscriptions and pending QoS 1/2 messages for the session expiry interval.
toml
[mqtt]
session_expiry_secs = 3600   # 1 hour default

Topic Wildcards#

Standard MQTT wildcard subscriptions are supported:

Wildcard Example Matches
+ sensors/+/temp sensors/room1/temp, etc.
# sensors/# Everything under sensors/.

Authentication#

MQTT clients authenticate via the token-in-username pattern. The client sends a bearer token as the MQTT username, and bext validates it through the same Auth capability used for HTTP:

code
Username: Bearer eyJhbGciOi...
Password: (empty or ignored)

Alternatively, use client certificate authentication over MQTTS for device fleets where token management is impractical.

toml
[mqtt.auth]
mode = "token"        # "token" | "cert" | "none"

HTTP Publish Bridge#

Publish MQTT messages from any HTTP client via the built-in bridge endpoint:

code
POST /__bext/mqtt/publish
Content-Type: application/json

{
  "topic": "sensors/room1/temp",
  "payload": "22.5",
  "qos": 1,
  "retain": false
}

This is useful for backend services that do not have an MQTT client library, or for triggering device commands from a web dashboard.

Plugin Integration#

Plugins can subscribe to MQTT topics and publish messages:

rust
use bext::mqtt::{MqttBus, MqttMessage};

async fn on_mqtt_message(msg: MqttMessage, bus: &MqttBus) {
    println!("topic={} payload={}", msg.topic, msg.payload_str());

    // Publish a response
    bus.publish("devices/ack", b"ok", QoS::AtLeastOnce).await?;
}

Register the subscription in the plugin manifest:

toml
[plugin]
name = "sensor-handler"

[[plugin.mqtt_subscriptions]]
topic = "sensors/+/temp"
qos = 1

Retained Messages#

When retain = true, bext stores the last message per topic in memory. New subscribers immediately receive the retained message for matching topics. This is standard MQTT behavior for "last known value" patterns.

Will Messages#

Clients can set a Last Will and Testament (LWT) on connect. If the client disconnects ungracefully, bext publishes the will message to the specified topic:

code
Will Topic: devices/sensor-42/status
Will Payload: offline
Will QoS: 1
Will Retain: true

Metrics#

Metric Description
mqtt_connections_active Current MQTT client connections.
mqtt_messages_received_total Messages received from clients.
mqtt_messages_sent_total Messages sent to clients.
mqtt_subscriptions_active Active topic subscriptions.

Feature Flag#

MQTT requires the mqtt feature flag:

bash
bext build --features mqtt

Without this flag, the [mqtt] config section is ignored.

Warning

bext is a gateway, not a persistence broker. Messages that cannot be delivered within QoS retry limits are dropped — there is no durable queue behind them. For workloads that require guaranteed delivery across broker restarts, bridge to an external broker (Mosquitto, EMQX, etc.) from a plugin rather than relying on bext's in-memory session store.

Tip

Port 1883 (plain TCP) is suitable for LAN or dev use only. In production, use port 8883 (MQTTS) and the cert auth mode so device credentials are not transmitted in plaintext.

Edit this page ↗Need a hand? ↗
FIND YOUR NEXT STEP

Start with a topic, a command, or a question.