# Plugins

The EMQ X Edge broker could be extended by plugins. Users could develop plugins to customize authentication, ACL and functions of the broker, or integrate the broker with other systems.

The plugins that EMQ X Edge 3.0 released:

emqx_auth_clientid (opens new window)ClientId Auth Plugin
emqx_auth_username (opens new window)Username/Password Auth Plugin
emqx_auth_http (opens new window)HTTP Auth/ACL Plugin
emqx_auth_mysql (opens new window)MySQL Auth/ACL Plugin
emqx_web_hook (opens new window)Web Hook Plugin
emqx_lua_hook (opens new window)Lua Hook Plugin
emqx_retainer (opens new window)Retained Messages Store Plugin
emqx_coap (opens new window)CoAP Protocol Plugin
emqx_sn (opens new window)MQTT-SN Protocol Plugin
emqx_stomp (opens new window)STOMP Protocol Plugin
emqx_recon (opens new window)Recon Plugin
emqx_reloader (opens new window)Reloader Plugin

# emqx_auth_clientid - ClientID Auth Plugin

ClientID Auth Plugin: https://github.com/emqx/emqx-auth-clientid (opens new window)

# Configure ClientID Auth Plugin


##auth.client.$N.clientid = clientid
##auth.client.$N.password = passwd

## Examples
##auth.client.1.clientid = id
##auth.client.1.password = passwd
##auth.client.2.clientid = dev:devid
##auth.client.2.password = passwd2
##auth.client.3.clientid = app:appid
##auth.client.3.password = passwd3

# Load ClientId Auth Plugin

./bin/emqx_ctl plugins load emqx_auth_clientid

# emqx_auth_username - Username Auth Plugin

Username Auth Plugin: https://github.com/emqx/emqx-auth-username (opens new window)

# Configure Username Auth Plugin


##auth.user.$N.username = admin
##auth.user.$N.password = public

## Examples:
##auth.user.1.username = admin
##auth.user.1.password = public
##auth.user.2.username = feng@emqx.io
##auth.user.2.password = public

Add username/password by ./bin/emqx_ctl users CLI:

$ ./bin/emqx_ctl users add \<Username> \<Password>

or by configuring etc/plugins/emqx_auth_username.conf:

auth.username.test = public

# Load Username Auth Plugin

./bin/emqx_ctl plugins load emqx_auth_username

------------------------------------emqx_auth_http - HTTP Auth/ACL Plugin ------------------------------------

MQTT Authentication/ACL with HTTP API: https://github.com/emqx/emqx-auth-http (opens new window)

# Configure HTTP Auth/ACL Plugin


## Variables: %u = username, %c = clientid, %a = ipaddress, %P = password, %t = topic

auth.http.auth_req =
auth.http.auth_req.method = post
auth.http.auth_req.params = clientid=%c,username=%u,password=%P

auth.http.super_req =
auth.http.super_req.method = post
auth.http.super_req.params = clientid=%c,username=%u

## 'access' parameter: sub = 1, pub = 2
auth.http.acl_req =
auth.http.acl_req.method = get
auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t


Return 200 if ok

Return 4xx if unauthorized

# Load HTTP Auth/ACL Plugin

./bin/emqx_ctl plugins load emqx_auth_http

# emqx_auth_mysql - MySQL Auth/ACL Plugin

MQTT Authentication, ACL against MySQL database: https://github.com/emqx/emqx-auth-mysql (opens new window)

# MQTT User Table

CREATE TABLE `mqtt_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` varchar(20) DEFAULT NULL,
  `is_superuser` tinyint(1) DEFAULT 0,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mqtt_username` (`username`)

# MQTT ACL Table

CREATE TABLE `mqtt_acl` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow',
  `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
  `username` varchar(100) DEFAULT NULL COMMENT 'Username',
  `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
  `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
  `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
  PRIMARY KEY (`id`)

INSERT INTO `mqtt_acl` (`id`, `allow`, `ipaddr`, `username`, `clientid`, `access`, `topic`)
    (3,0,NULL,'$all',NULL,1,'eq #'),

# Configure MySQL Auth/ACL Plugin


## Mysql Server
auth.mysql.server =

## Mysql Pool Size
auth.mysql.pool = 8

## Mysql Username
## auth.mysql.username =

## Mysql Password
## auth.mysql.password =

## Mysql Database
auth.mysql.database = mqtt

## Variables: %u = username, %c = clientid

## Authentication Query: select password only
auth.mysql.auth_query = select password from mqtt_user where username = '%u' limit 1

## Password hash: plain, md5, sha, sha256, pbkdf2
auth.mysql.password_hash = sha256

## %% Superuser Query
auth.mysql.super_query = select is_superuser from mqtt_user where username = '%u' limit 1

## ACL Query Command
auth.mysql.acl_query = select allow, ipaddr, username, clientid, access, topic from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'

# Load MySQL Auth/ACL plugin

./bin/emqx_ctl plugins load emqx_auth_mysql

# emqx_retainer - Retainer Plugin

Retainer Plugin: https://github.com/emqx/emqx-retainer (opens new window)

# Configure Retainer Plugin


## disc: disc_copies, ram: ram_copies
## Notice: retainer's storage_type on each node in a cluster must be the same!
retainer.storage_type = disc

## Max number of retained messages
retainer.max_message_num = 1000000

## Max Payload Size of retained message
retainer.max_payload_size = 64KB

## Expiry interval. Never expired if 0
## h - hour
## m - minute
## s - second
retainer.expiry_interval = 0

# emqx_coap: CoAP Protocol Plugin

CoAP Protocol Plugin: https://github.com/emqx/emqx-coap (opens new window)

# Configure CoAP Plugin


coap.port = 5683

coap.keepalive = 120s

coap.enable_stats = off

# Load CoAP Protocol Plugin

./bin/emqx_ctl plugins load emqx_coap

# libcoap Client

yum install libcoap

% coap client publish message
coap-client -m post -e "qos=0&retain=0&message=payload&topic=hello" coap://localhost/mqtt

# emqx_sn: MQTT-SN Protocol

MQTT-SN Protocol/Gateway Plugin: https://github.com/emqx/emqx-sn (opens new window)

# Configure MQTT-SN Plugin


UDP Port for MQTT-SN: 1884


mqtt.sn.port = 1884

# Load MQTT-SN Plugin

./bin/emqx_ctl plugins load emqx_sn

# emqx_stomp - STOMP Protocol Plugin

STOMP Protocol Plugin: https://github.com/emqx/emqx-stomp (opens new window)

Support STOMP 1.0/1.1/1.2 clients to connect to EMQ X broker and communicate with MQTT Clients.

# Configure Stomp Plugin



Default Port for STOMP Protocol: 61613

stomp.default_user.login = guest

stomp.default_user.passcode = guest

stomp.allow_anonymous = true

stomp.frame.max_headers = 10

stomp.frame.max_header_length = 1024

stomp.frame.max_body_length = 8192

stomp.listener = 61613

stomp.listener.acceptors = 4

stomp.listener.max_clients = 512

# Load Stomp Plugin

./bin/emqx_ctl plugins load emqx_stomp

# emqx_recon - Recon Plugin

Recon Plugin: https://github.com/emqx/emqx-recon (opens new window)

The plugin loads recon (opens new window) library on a running EMQ X broker. Recon library helps debug and optimize an Erlang application.

# Configure Recon Plugin


%% Garbage Collection: 10 minutes
recon.gc_interval = 600

# Load Recon Plugin

./bin/emqx_ctl plugins load emqx_recon

# Recon CLI

./bin/emqx_ctl recon

recon memory                 #recon_alloc:memory/2
recon allocated              #recon_alloc:memory(allocated_types, current|max)
recon bin_leak               #recon:bin_leak(100)
recon node_stats             #recon:node_stats(10, 1000)
recon remote_load Mod        #recon:remote_load(Mod)

# emqx_reloader - Reloader Plugin

Erlang Module Reloader for Development: https://github.com/emqx/emqx-reloader (opens new window)


Don't load the plugin in production!

# Configure Reloader Plugin


reloader.interval = 60

reloader.logfile = log/reloader.log

# Load Reloader Plugin

./bin/emqx_ctl plugins load emqx_reloader

# reload CLI

./bin/emqx_ctl reload

reload \<Module>             # Reload a Module

# Plugin Development Guide

# Create a Plugin Project

Refer to emqx_plugin_template (opens new window) for new plugin project.

# Register Auth/ACL Modules

emqx_auth_demo.erl - Demo Authentication Module:




-export([init/1, check/3, description/0]).

init(Opts) -> {ok, Opts}.

check(#mqtt_client{client_id = ClientId, username = Username}, Password, _Opts) ->
    io:format("Auth Demo: clientId=~p, username=~p, password=~p~n",
              [ClientId, Username, Password]),

description() -> "Demo Auth Module".

emqx_acl_demo.erl - Demo ACL Module:



%% ACL callbacks
-export([init/1, check_acl/2, reload_acl/1, description/0]).

init(Opts) ->
    {ok, Opts}.

check_acl({Client, PubSub, Topic}, Opts) ->
    io:format("ACL Demo: ~p ~p ~p~n", [Client, PubSub, Topic]),

reload_acl(_Opts) ->

description() -> "ACL Module Demo".

emqx_plugin_template_app.erl - Register the auth/ACL modules:

ok = emqx_access_control:register_mod(auth, emqx_auth_demo, []),
ok = emqx_access_control:register_mod(acl, emqx_acl_demo, []),

# Register Callbacks for Hooks

The plugin could register callbacks for hooks. The hooks will be run by the broker when a client connected/disconnected, a topic subscribed/unsubscribed or a message published/delivered:

client.connectedRun when a client connects to the broker successfully
client.subscribeRun before a client subscribes topics
client.unsubscribeRun when a client unsubscribes topics
session.subscribedRun after a client subscribes a topic
session.unsubscribedRun after a client unsubscribes a topic
message.publishRun when a message is published
message.deliveredRun when a message is delivered
message.ackedRun when a message(qos1/2) is acked
client.disconnectedRun when a client is disconnnected

emqx_plugin_template.erl for example:

%% Called when the plugin application start
load(Env) ->
    emqx:hook('client.connected', fun ?MODULE:on_client_connected/3, [Env]),
    emqx:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Env]),
    emqx:hook('client.subscribe', fun ?MODULE:on_client_subscribe/4, [Env]),
    emqx:hook('session.subscribed', fun ?MODULE:on_session_subscribed/4, [Env]),
    emqx:hook('client.unsubscribe', fun ?MODULE:on_client_unsubscribe/4, [Env]),
    emqx:hook('session.unsubscribed', fun ?MODULE:on_session_unsubscribed/4, [Env]),
    emqx:hook('message.publish', fun ?MODULE:on_message_publish/2, [Env]),
    emqx:hook('message.delivered', fun ?MODULE:on_message_delivered/4, [Env]),
    emqx:hook('message.acked', fun ?MODULE:on_message_acked/4, [Env]).

# Register CLI Modules





cmd(["arg1", "arg2"]) ->

cmd(_) ->
    ?USAGE([{"cmd arg1 arg2", "cmd demo"}]).

emqx_plugin_template_app.erl - register the CLI module to EMQ X broker:

emqx_ctl:register_cmd(cmd, {emqx_cli_demo, cmd}, []).

There will be a new CLI after the plugin loaded:

./bin/emqx_ctl cmd arg1 arg2

# Create Configuration File

Create etc/${plugin_name}.conf|config file for the plugin (which will be put in the directory etc/plugins/${plugin_name} after compilation). The EMQ X broker supports two types of config syntax:

  1. ${plugin_name}.config with erlang syntax:
  {plugin_name, [
    {key, value}
  1. ${plugin_name}.conf with a general k = v syntax:
plugin_name.key = value

# Build and Release the Plugin

  1. clone emqx-rel project:
git clone https://github.com/emqx/emqx-rel.git
  1. Add DEPS in Makefile:
DEPS += plugin_name
dep_plugin_name = git url_of_plugin
  1. Add the plugin in relx.config:
{plugin_name, load},