Преглед изворни кода

Merge pull request #11114 from zmstone/0621-merge-release-51-to-master

0621 merge release-51 to master
Zaiming (Stone) Shi пре 2 година
родитељ
комит
eec70b62e8
83 измењених фајлова са 2076 додато и 115 уклоњено
  1. 1 0
      .ci/docker-compose-file/python/pytest.sh
  2. 1 1
      .github/workflows/build_and_push_docker_images.yaml
  3. 1 1
      .gitignore
  4. 1 1
      Makefile
  5. 0 7
      apps/emqx/include/emqx.hrl
  6. 2 2
      apps/emqx/include/emqx_release.hrl
  7. 1 1
      apps/emqx/rebar.config
  8. 1 1
      apps/emqx/src/emqx.app.src
  9. 0 4
      apps/emqx/src/emqx_app.erl
  10. 6 3
      apps/emqx/src/emqx_release.erl
  11. 4 0
      apps/emqx/test/emqx_release_tests.erl
  12. 1 1
      apps/emqx_authn/src/emqx_authn.app.src
  13. 1 1
      apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src
  14. 0 1
      apps/emqx_conf/README.md
  15. 1 1
      apps/emqx_conf/etc/emqx_conf.conf
  16. 1 19
      apps/emqx_conf/src/emqx_conf.erl
  17. 24 13
      apps/emqx_conf/src/emqx_conf_app.erl
  18. 1 1
      apps/emqx_conf/src/emqx_conf_schema.erl
  19. 1 1
      apps/emqx_connector/src/emqx_connector.app.src
  20. 1 1
      apps/emqx_dashboard/src/emqx_dashboard.app.src
  21. 1 1
      apps/emqx_ft/src/emqx_ft.app.src
  22. 1 1
      apps/emqx_gateway/src/emqx_gateway.app.src
  23. 1 1
      apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src
  24. 0 2
      apps/emqx_management/include/emqx_mgmt.hrl
  25. 1 1
      apps/emqx_management/src/emqx_management.app.src
  26. 0 1
      apps/emqx_management/src/emqx_mgmt_app.erl
  27. 22 15
      apps/emqx_management/src/emqx_mgmt_cli.erl
  28. 1 1
      apps/emqx_modules/src/emqx_modules.app.src
  29. 1 1
      apps/emqx_node_rebalance/src/emqx_node_rebalance.app.src
  30. 1 1
      apps/emqx_oracle/src/emqx_oracle.app.src
  31. 1 1
      apps/emqx_resource/src/emqx_resource.app.src
  32. 1 1
      apps/emqx_rule_engine/src/emqx_rule_engine.app.src
  33. 1 1
      apps/emqx_slow_subs/src/emqx_slow_subs.app.src
  34. 1 1
      apps/emqx_utils/src/emqx_utils.app.src
  35. 3 1
      build
  36. 2 0
      changes/ce/fix-11092.en.md
  37. 138 0
      changes/e5.1.0.en.md
  38. 94 0
      changes/v5.1.0.en.md
  39. 16 0
      examples/README.md
  40. 22 0
      examples/alarm.conf.example
  41. 30 0
      examples/cluster-with-dns.conf.example
  42. 81 0
      examples/cluster-with-etcd-ssl.conf.example
  43. 33 0
      examples/cluster-with-etcd.conf.example
  44. 39 0
      examples/cluster-with-k8s.conf.example
  45. 21 0
      examples/cluster-with-manual.conf.example
  46. 24 0
      examples/cluster-with-static.conf.example
  47. 15 0
      examples/conn_congestion.conf.example
  48. 41 0
      examples/dashboard-with-http.conf.example
  49. 86 0
      examples/dashboard-with-https.conf.example
  50. 15 0
      examples/delayed.conf.example
  51. 52 0
      examples/exhook.conf.example
  52. 50 0
      examples/file_transfer-with-local-exporter.conf.example
  53. 72 0
      examples/file_transfer-with-s3-exporter.conf.example
  54. 21 0
      examples/flapping_detect.conf.example
  55. 18 0
      examples/force_gc.conf.example
  56. 19 0
      examples/force_shutdown.conf.example
  57. 24 0
      examples/gateway.coap.conf.example
  58. 31 0
      examples/gateway.exproto.conf.example
  59. 62 0
      examples/gateway.lwm2m.conf.example
  60. 38 0
      examples/gateway.mqttsn.conf.example
  61. 30 0
      examples/gateway.stomp.conf.example
  62. 19 0
      examples/license.conf.example
  63. 47 0
      examples/listeners.quic.conf.example
  64. 90 0
      examples/listeners.ssl.conf.example
  65. 77 0
      examples/listeners.tcp.conf.example
  66. 76 0
      examples/listeners.ws.conf.example
  67. 104 0
      examples/listeners.wss.conf.example
  68. 27 0
      examples/log.console.conf.example
  69. 38 0
      examples/log.file.conf.example
  70. 124 0
      examples/mqtt.conf.example
  71. 43 0
      examples/node.conf.example
  72. 27 0
      examples/plugin.conf.example
  73. 28 0
      examples/prometheus.conf.example
  74. 21 0
      examples/psk_authentication.conf.example
  75. 40 0
      examples/retainer.conf.example
  76. 25 0
      examples/sys_topics.conf.example
  77. 30 0
      examples/sysmon.os.conf.example
  78. 42 0
      examples/sysmon.vm.conf.example
  79. 4 4
      mix.exs
  80. 1 1
      rebar.config
  81. 1 14
      rebar.config.erl
  82. 1 1
      rel/i18n/emqx_prometheus_schema.hocon
  83. 52 5
      scripts/test/start-two-nodes-in-host.sh

+ 1 - 0
.ci/docker-compose-file/python/pytest.sh

@@ -19,6 +19,7 @@ fi
 
 apk update && apk add git curl
 git clone -b develop-5.0 https://github.com/emqx/paho.mqtt.testing.git /paho.mqtt.testing
+
 pip install pytest==7.1.2 pytest-retry
 
 pytest --retries 3 -v /paho.mqtt.testing/interoperability/test_client/V5/test_connect.py -k test_basic --host "$TARGET_HOST"

+ 1 - 1
.github/workflows/build_and_push_docker_images.yaml

@@ -169,7 +169,7 @@ jobs:
         fi
         extra_deps=
         if [[ "${{ matrix.profile }}" = *enterprise* ]]; then
-          extra_deps='libsasl2-2'
+          extra_deps='libsasl2-2,libsasl2-modules-gssapi-mit'
         fi
 
         echo "img_suffix=$img_suffix" >> $GITHUB_OUTPUT

+ 1 - 1
.gitignore

@@ -6,7 +6,7 @@ deps
 *.o
 *.beam
 *.plt
-*.example
+#*.example
 erl_crash.dump
 ebin
 !ebin/.placeholder

+ 1 - 1
Makefile

@@ -16,7 +16,7 @@ endif
 # Dashboard version
 # from https://github.com/emqx/emqx-dashboard5
 export EMQX_DASHBOARD_VERSION ?= v1.3.0-1
-export EMQX_EE_DASHBOARD_VERSION ?= e1.1.0-beta.9
+export EMQX_EE_DASHBOARD_VERSION ?= e1.1.0
 
 # `:=` should be used here, otherwise the `$(shell ...)` will be executed every time when the variable is used
 # In make 4.4+, for backward-compatibility the value from the original environment is used.

+ 0 - 7
apps/emqx/include/emqx.hrl

@@ -25,13 +25,6 @@
 -define(ROUTE_SHARD, route_shard).
 -define(PERSISTENT_SESSION_SHARD, emqx_persistent_session_shard).
 
--define(BOOT_SHARDS, [
-    ?ROUTE_SHARD,
-    ?COMMON_SHARD,
-    ?SHARED_SUB_SHARD,
-    ?PERSISTENT_SESSION_SHARD
-]).
-
 %% Banner
 %%--------------------------------------------------------------------
 

+ 2 - 2
apps/emqx/include/emqx_release.hrl

@@ -32,10 +32,10 @@
 %% `apps/emqx/src/bpapi/README.md'
 
 %% Opensource edition
--define(EMQX_RELEASE_CE, "5.1.0-alpha.5").
+-define(EMQX_RELEASE_CE, "5.1.0").
 
 %% Enterprise edition
--define(EMQX_RELEASE_EE, "5.1.0-alpha.8").
+-define(EMQX_RELEASE_EE, "5.1.0").
 
 %% The HTTP API version
 -define(EMQX_API_VERSION, "5.0").

+ 1 - 1
apps/emqx/rebar.config

@@ -27,7 +27,7 @@
     {gproc, {git, "https://github.com/emqx/gproc", {tag, "0.9.0.1"}}},
     {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}},
     {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.6"}}},
-    {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.15.2"}}},
+    {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.15.3"}}},
     {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.1"}}},
     {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.39.10"}}},
     {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.2"}}},

+ 1 - 1
apps/emqx/src/emqx.app.src

@@ -2,7 +2,7 @@
 {application, emqx, [
     {id, "emqx"},
     {description, "EMQX Core"},
-    {vsn, "5.1.0"},
+    {vsn, "5.1.1"},
     {modules, []},
     {registered, []},
     {applications, [

+ 0 - 4
apps/emqx/src/emqx_app.erl

@@ -44,7 +44,6 @@ start(_Type, _Args) ->
     ok = emqx_persistent_session:init_db_backend(),
     ok = maybe_start_quicer(),
     ok = emqx_bpapi:start(),
-    wait_boot_shards(),
     ok = emqx_alarm_handler:load(),
     {ok, Sup} = emqx_sup:start_link(),
     ok = maybe_start_listeners(),
@@ -60,9 +59,6 @@ prep_stop(_State) ->
 
 stop(_State) -> ok.
 
-wait_boot_shards() ->
-    ok = mria_rlog:wait_for_shards(?BOOT_SHARDS, infinity).
-
 %% @doc Call this function to make emqx boot without loading config,
 %% in case we want to delegate the config load to a higher level app
 %% which manages emqx app.

+ 6 - 3
apps/emqx/src/emqx_release.erl

@@ -132,10 +132,13 @@ parse_vsn(Vsn) ->
         Suffix =
             case Suffix0 of
                 "" ->
-                    %% For the case like "5.1.0"
+                    %% "5.1.0"
                     "";
-                [ReleaseStage, Number] ->
-                    %% For the case like "5.1.0-rc.1"
+                ["g" ++ _] ->
+                    %% "5.1.0-g53ab85b1"
+                    "";
+                [ReleaseStage, Number | _] ->
+                    %% "5.1.0-rc.1" or "5.1.0-rc.1-g53ab85b1"
                     {ReleaseStage, list_to_integer(Number)}
             end,
         {{list_to_integer(V1), list_to_integer(V2), list_to_integer(V3)}, Suffix}

+ 4 - 0
apps/emqx/test/emqx_release_tests.erl

@@ -47,6 +47,10 @@ vsn_compre_test_() ->
             ?assertEqual(older, emqx_release:vsn_compare("1.1.1", "1.1.1-rc.1")),
             ?assertEqual(newer, emqx_release:vsn_compare("1.1.1-rc.1", "1.1.1"))
         end},
+        {"git hash suffix is ignored", fun() ->
+            ?assertEqual(older, emqx_release:vsn_compare("1.1.1-gabcd", "1.1.1-rc.1-g1234")),
+            ?assertEqual(newer, emqx_release:vsn_compare("1.1.1-rc.1-gabcd", "1.1.1-g1234"))
+        end},
         {"invalid version string will crash", fun() ->
             ?assertError({invalid_version_string, "1.1.a"}, emqx_release:vsn_compare("v1.1.a")),
             ?assertError(

+ 1 - 1
apps/emqx_authn/src/emqx_authn.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_authn, [
     {description, "EMQX Authentication"},
-    {vsn, "0.1.21"},
+    {vsn, "0.1.22"},
     {modules, []},
     {registered, [emqx_authn_sup, emqx_authn_registry]},
     {applications, [kernel, stdlib, emqx_resource, emqx_connector, ehttpc, epgsql, mysql, jose]},

+ 1 - 1
apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_kafka, [
     {description, "EMQX Enterprise Kafka Bridge"},
-    {vsn, "0.1.3"},
+    {vsn, "0.1.4"},
     {registered, [emqx_bridge_kafka_consumer_sup]},
     {applications, [
         kernel,

+ 0 - 1
apps/emqx_conf/README.md

@@ -5,7 +5,6 @@ This application provides configuration management capabilities for EMQX.
 At compile time it reads all configuration schemas and generates the following files:
   * `config-en.md`: documentation for all configuration options.
   * `schema-en.json`: JSON description of all configuration schema options.
-  * `emqx.conf.example`: an example of a complete configuration file.
 
 At runtime, it provides:
 - Cluster configuration synchronization capability.

+ 1 - 1
apps/emqx_conf/etc/emqx_conf.conf

@@ -7,7 +7,7 @@
 ## To avoid confusion, please do not store the same configs in both files.
 ##
 ## See {{ emqx_configuration_doc }} for more details.
-## Configuration full example can be found in emqx.conf.example
+## Configuration full example can be found in etc/examples
 
 node {
   name = "emqx@127.0.0.1"

+ 1 - 19
apps/emqx_conf/src/emqx_conf.erl

@@ -30,7 +30,6 @@
 -export([reset/2, reset/3]).
 -export([dump_schema/2]).
 -export([schema_module/0]).
--export([gen_example_conf/2]).
 -export([check_config/2]).
 
 %% TODO: move to emqx_dashboard when we stop building api schema at build time
@@ -161,8 +160,7 @@ dump_schema(Dir, SchemaModule) ->
             ok = gen_schema_json(Dir, SchemaModule, Lang)
         end,
         ["en", "zh"]
-    ),
-    ok = gen_example_conf(Dir, SchemaModule).
+    ).
 
 %% for scripts/spellcheck.
 gen_schema_json(Dir, SchemaModule, Lang) ->
@@ -202,11 +200,6 @@ gen_config_md(Dir, SchemaModule, Lang) ->
     io:format(user, "===< Generating: ~s~n", [SchemaMdFile]),
     ok = gen_doc(SchemaMdFile, SchemaModule, Lang).
 
-gen_example_conf(Dir, SchemaModule) ->
-    SchemaMdFile = filename:join([Dir, "emqx.conf.example"]),
-    io:format(user, "===< Generating: ~s~n", [SchemaMdFile]),
-    ok = gen_example(SchemaMdFile, SchemaModule).
-
 %% @doc return the root schema module.
 -spec schema_module() -> module().
 schema_module() ->
@@ -250,17 +243,6 @@ gen_doc(File, SchemaModule, Lang) ->
     Doc = hocon_schema_md:gen(SchemaModule, Opts),
     file:write_file(File, Doc).
 
-gen_example(File, SchemaModule) ->
-    %% we do not generate description in example files
-    %% so there is no need for a desc_resolver
-    Opts = #{
-        title => <<"EMQX Configuration Example">>,
-        body => <<"">>,
-        include_importance_up_from => ?IMPORTANCE_MEDIUM
-    },
-    Example = hocon_schema_example:gen(SchemaModule, Opts),
-    file:write_file(File, Example).
-
 gen_api_schema_json_iodata(SchemaMod, SchemaInfo) ->
     emqx_dashboard_swagger:gen_api_schema_json_iodata(
         SchemaMod,

+ 24 - 13
apps/emqx_conf/src/emqx_conf_app.erl

@@ -134,7 +134,7 @@ sync_cluster_conf2(Nodes) ->
                 msg => "ignored_nodes_when_sync_cluster_conf"
             },
             ?SLOG(warning, Warning);
-        true ->
+        true when Failed =/= [] ->
             %% There are core nodes running but no one was able to reply.
             ?SLOG(error, #{
                 msg => "failed_to_sync_cluster_conf",
@@ -142,6 +142,14 @@ sync_cluster_conf2(Nodes) ->
                 failed => Failed,
                 not_ready => NotReady
             });
+        true ->
+            %% There are core nodes booting up
+            ?SLOG(info, #{
+                msg => "peer_not_ready_for_config_sync",
+                reason => "The 'not_ready' peer node(s) are loading configs",
+                nodes => Nodes,
+                not_ready => NotReady
+            });
         false ->
             ok
     end,
@@ -180,17 +188,7 @@ sync_cluster_conf2(Nodes) ->
 
 %% @private Filter out the nodes which are running a newer version than this node.
 sync_cluster_conf3(Ready) ->
-    NotNewer = fun({ok, #{release := RemoteRelease}}) ->
-        try
-            emqx_release:vsn_compare(RemoteRelease) =/= newer
-        catch
-            _:_ ->
-                %% If the version is not valid (without v or e prefix),
-                %% we know it's older than v5.1.0/e5.1.0
-                true
-        end
-    end,
-    case lists:filter(NotNewer, Ready) of
+    case lists:filter(fun is_older_or_same_version/1, Ready) of
         [] ->
             %% All available core nodes are running a newer version than this node.
             %% Start this node without syncing cluster config from them.
@@ -213,6 +211,19 @@ sync_cluster_conf3(Ready) ->
             sync_cluster_conf4(Ready2)
     end.
 
+is_older_or_same_version({ok, #{release := RemoteRelease}}) ->
+    try
+        emqx_release:vsn_compare(RemoteRelease) =/= newer
+    catch
+        _:_ ->
+            %% If the version is not valid (without v or e prefix),
+            %% we know it's older than v5.1.0/e5.1.0
+            true
+    end;
+is_older_or_same_version(_) ->
+    %% older version has no 'release' field
+    true.
+
 %% @private Some core nodes are running and replied with their configs successfully.
 %% Try to sort the results and save the first one for local use.
 sync_cluster_conf4(Ready) ->
@@ -223,7 +234,7 @@ sync_cluster_conf4(Ready) ->
         msg => "sync_cluster_conf_success",
         synced_from_node => Node,
         has_deprecated_file => HasDeprecatedFile,
-        local_release => emqx_app:get_release(),
+        local_release => emqx_release:version_with_prefix(),
         remote_release => maps:get(release, Info, "before_v5.0.24|e5.0.3"),
         data_dir => emqx:data_dir(),
         tnx_id => TnxId

+ 1 - 1
apps/emqx_conf/src/emqx_conf_schema.erl

@@ -165,7 +165,7 @@ fields("cluster") ->
                 emqx_schema:duration(),
                 #{
                     mapping => "mria.cluster_autoclean",
-                    default => <<"5m">>,
+                    default => <<"24h">>,
                     desc => ?DESC(cluster_autoclean),
                     'readOnly' => true
                 }

+ 1 - 1
apps/emqx_connector/src/emqx_connector.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_connector, [
     {description, "EMQX Data Integration Connectors"},
-    {vsn, "0.1.25"},
+    {vsn, "0.1.26"},
     {registered, []},
     {mod, {emqx_connector_app, []}},
     {applications, [

+ 1 - 1
apps/emqx_dashboard/src/emqx_dashboard.app.src

@@ -2,7 +2,7 @@
 {application, emqx_dashboard, [
     {description, "EMQX Web Dashboard"},
     % strict semver, bump manually!
-    {vsn, "5.0.23"},
+    {vsn, "5.0.24"},
     {modules, []},
     {registered, [emqx_dashboard_sup]},
     {applications, [kernel, stdlib, mnesia, minirest, emqx, emqx_ctl]},

+ 1 - 1
apps/emqx_ft/src/emqx_ft.app.src

@@ -1,6 +1,6 @@
 {application, emqx_ft, [
     {description, "EMQX file transfer over MQTT"},
-    {vsn, "0.1.2"},
+    {vsn, "0.1.3"},
     {registered, []},
     {mod, {emqx_ft_app, []}},
     {applications, [

+ 1 - 1
apps/emqx_gateway/src/emqx_gateway.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_gateway, [
     {description, "The Gateway management application"},
-    {vsn, "0.1.19"},
+    {vsn, "0.1.20"},
     {registered, []},
     {mod, {emqx_gateway_app, []}},
     {applications, [kernel, stdlib, emqx, emqx_authn, emqx_ctl]},

+ 1 - 1
apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src

@@ -1,6 +1,6 @@
 {application, emqx_gateway_exproto, [
     {description, "ExProto Gateway"},
-    {vsn, "0.1.1"},
+    {vsn, "0.1.2"},
     {registered, []},
     {applications, [kernel, stdlib, grpc, emqx, emqx_gateway]},
     {env, []},

+ 0 - 2
apps/emqx_management/include/emqx_mgmt.hrl

@@ -14,6 +14,4 @@
 %% limitations under the License.
 %%--------------------------------------------------------------------
 
--define(MANAGEMENT_SHARD, emqx_management_shard).
-
 -define(DEFAULT_ROW_LIMIT, 100).

+ 1 - 1
apps/emqx_management/src/emqx_management.app.src

@@ -2,7 +2,7 @@
 {application, emqx_management, [
     {description, "EMQX Management API and CLI"},
     % strict semver, bump manually!
-    {vsn, "5.0.24"},
+    {vsn, "5.0.25"},
     {modules, []},
     {registered, [emqx_management_sup]},
     {applications, [kernel, stdlib, emqx_plugins, minirest, emqx, emqx_ctl]},

+ 0 - 1
apps/emqx_management/src/emqx_mgmt_app.erl

@@ -28,7 +28,6 @@
 -include("emqx_mgmt.hrl").
 
 start(_Type, _Args) ->
-    ok = mria_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity),
     case emqx_mgmt_auth:init_bootstrap_file() of
         ok ->
             emqx_conf:add_handler([api_key], emqx_mgmt_auth),

+ 22 - 15
apps/emqx_management/src/emqx_mgmt_cli.erl

@@ -616,21 +616,28 @@ listeners([]) ->
             Acceptors = maps:get(acceptors, Conf),
             ProxyProtocol = maps:get(proxy_protocol, Conf, undefined),
             Running = maps:get(running, Conf),
-            CurrentConns =
-                case emqx_listeners:current_conns(ID, Bind) of
-                    {error, _} -> [];
-                    CC -> [{current_conn, CC}]
-                end,
-            MaxConn =
-                case emqx_listeners:max_conns(ID, Bind) of
-                    {error, _} -> [];
-                    MC -> [{max_conns, MC}]
-                end,
-            ShutdownCount =
-                case emqx_listeners:shutdown_count(ID, Bind) of
-                    {error, _} -> [];
-                    SC -> [{shutdown_count, SC}]
-                end,
+            case Running of
+                true ->
+                    CurrentConns =
+                        case emqx_listeners:current_conns(ID, Bind) of
+                            {error, _} -> [];
+                            CC -> [{current_conn, CC}]
+                        end,
+                    MaxConn =
+                        case emqx_listeners:max_conns(ID, Bind) of
+                            {error, _} -> [];
+                            MC -> [{max_conns, MC}]
+                        end,
+                    ShutdownCount =
+                        case emqx_listeners:shutdown_count(ID, Bind) of
+                            {error, _} -> [];
+                            SC -> [{shutdown_count, SC}]
+                        end;
+                false ->
+                    CurrentConns = [],
+                    MaxConn = [],
+                    ShutdownCount = []
+            end,
             Info =
                 [
                     {listen_on, {string, emqx_listeners:format_bind(Bind)}},

+ 1 - 1
apps/emqx_modules/src/emqx_modules.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_modules, [
     {description, "EMQX Modules"},
-    {vsn, "5.0.16"},
+    {vsn, "5.0.17"},
     {modules, []},
     {applications, [kernel, stdlib, emqx, emqx_ctl]},
     {mod, {emqx_modules_app, []}},

+ 1 - 1
apps/emqx_node_rebalance/src/emqx_node_rebalance.app.src

@@ -1,6 +1,6 @@
 {application, emqx_node_rebalance, [
     {description, "EMQX Node Rebalance"},
-    {vsn, "5.0.2"},
+    {vsn, "5.0.3"},
     {registered, [
         emqx_node_rebalance_sup,
         emqx_node_rebalance,

+ 1 - 1
apps/emqx_oracle/src/emqx_oracle.app.src

@@ -1,6 +1,6 @@
 {application, emqx_oracle, [
     {description, "EMQX Enterprise Oracle Database Connector"},
-    {vsn, "0.1.2"},
+    {vsn, "0.1.3"},
     {registered, []},
     {applications, [
         kernel,

+ 1 - 1
apps/emqx_resource/src/emqx_resource.app.src

@@ -1,7 +1,7 @@
 %% -*- mode: erlang -*-
 {application, emqx_resource, [
     {description, "Manager for all external resources"},
-    {vsn, "0.1.18"},
+    {vsn, "0.1.19"},
     {registered, []},
     {mod, {emqx_resource_app, []}},
     {applications, [

+ 1 - 1
apps/emqx_rule_engine/src/emqx_rule_engine.app.src

@@ -2,7 +2,7 @@
 {application, emqx_rule_engine, [
     {description, "EMQX Rule Engine"},
     % strict semver, bump manually!
-    {vsn, "5.0.19"},
+    {vsn, "5.0.20"},
     {modules, []},
     {registered, [emqx_rule_engine_sup, emqx_rule_engine]},
     {applications, [kernel, stdlib, rulesql, getopt, emqx_ctl]},

+ 1 - 1
apps/emqx_slow_subs/src/emqx_slow_subs.app.src

@@ -1,7 +1,7 @@
 {application, emqx_slow_subs, [
     {description, "EMQX Slow Subscribers Statistics"},
     % strict semver, bump manually!
-    {vsn, "1.0.6"},
+    {vsn, "1.0.7"},
     {modules, []},
     {registered, [emqx_slow_subs_sup]},
     {applications, [kernel, stdlib, emqx]},

+ 1 - 1
apps/emqx_utils/src/emqx_utils.app.src

@@ -2,7 +2,7 @@
 {application, emqx_utils, [
     {description, "Miscellaneous utilities for EMQX apps"},
     % strict semver, bump manually!
-    {vsn, "5.0.3"},
+    {vsn, "5.0.4"},
     {modules, [
         emqx_utils,
         emqx_utils_api,

+ 3 - 1
build

@@ -367,7 +367,9 @@ docker_cleanup() {
     rm -f ./.dockerignore >/dev/null
 }
 
-## This function builds the default docker image based on debian 11
+## Build the default docker image based on debian 11.
+## NOTE: docker image build in github action does not call this
+##       function, see build_and_push_docker_images.yaml
 make_docker() {
     EMQX_BUILDER="${EMQX_BUILDER:-${EMQX_DEFAULT_BUILDER}}"
     EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}"

+ 2 - 0
changes/ce/fix-11092.en.md

@@ -0,0 +1,2 @@
+Fix problem when replicants were unable to connect to the core node due to timeout in `mria_lb:core_nodes()` call.
+Relevant mria pull request: https://github.com/emqx/mria/pull/143

Разлика између датотеке није приказан због своје велике величине
+ 138 - 0
changes/e5.1.0.en.md


Разлика између датотеке није приказан због своје велике величине
+ 94 - 0
changes/v5.1.0.en.md


+ 16 - 0
examples/README.md

@@ -0,0 +1,16 @@
+# Examples
+
+Here are examples of how to configure features In EMQX,  most of them can be used directly by copy-paste content into the `emqx.conf` file, others may need to be slightly modified to use, for example, you should change the listener port or HTTP URL to what you actually used.
+
+Although we have tried to show every configurable field in the example,
+you do not need to care about each one, since most of them already have default values and can be omitted in the configuration file.
+
+If you are confused about some fields, please refer to our documents, here are just some simple configuration examples with necessary descriptions.
+
+
+## Documentation
+
+The EMQX documentation is available at [www.emqx.io/docs/en/latest/](https://www.emqx.io/docs/en/latest/).
+
+The EMQX Enterprise documentation is available at [docs.emqx.com/en/](https://docs.emqx.com/en/).
+

+ 22 - 0
examples/alarm.conf.example

@@ -0,0 +1,22 @@
+##--------------------------------------------------------------------
+## Alarm
+##
+## Configuring how to handle the alarms generated from sysmon.*.conf.example
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+alarm {
+    ## The actions triggered when the alarm is activated
+    ## Type: Array of the below enum
+    ##   - log :: write the alarm to log
+    ##   - publish :: publish the alarm as an MQTT message to the system topics
+    actions = [log, publish]
+
+    ## Maximum total number of deactivated alarms to keep as history
+    ## Type: Range from 1 to 3000
+    size_limit = 1000
+
+    ## Retention time of deactivated alarms
+    validity_period = 24h
+}

+ 30 - 0
examples/cluster-with-dns.conf.example

@@ -0,0 +1,30 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery via DNS SRV records mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = dns
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+
+    dns {
+      ## The domain name from which to discover peer EMQX nodes' IP addresses
+      name = localhost
+
+      ## DNS record type
+      ## Type: enum: a | srv
+      record_type = a
+     }
+ }

+ 81 - 0
examples/cluster-with-etcd-ssl.conf.example

@@ -0,0 +1,81 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery using 'etcd' service mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = etcd
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+
+    etcd {
+      ## List of endpoint URLs of the etcd cluster
+      server = "http://ur1,http://ur2"
+
+      ## Key prefix used for EMQX service discovery
+      prefix = emqxcl
+
+      ## Expiration time of the etcd key associated with the node.
+      node_ttl = 1m
+
+      ssl_options {
+          ## Trusted PEM format CA certificates bundle file
+          cacertfile = "data/certs/cacert.pem"
+
+          ## PEM format certificates chain file
+          certfile = "data/certs/cert.pem"
+
+          ## PEM format private key file
+          keyfile = "data/certs/key.pem"
+
+          ## Enable or disable peer verification
+          verify = verify_none ## use verify_peer to enable
+
+          ## if `verify' is ebabled, whit true, the connection fails if the client does not have a certificate to send
+          fail_if_no_peer_cert = false
+
+          ## Enable TLS session reuse
+          reuse_sessions = true
+
+          ## Maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path
+          depth = 10
+
+          ## Which versions are to be supported
+          versions = [tlsv1.3, tlsv1.2]
+
+          ## TLS cipher suite names
+          ## Note: By default, all available suites are supported, you do not need to set this
+          ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+
+          ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
+          secure_renegotiate = true
+
+          ## Log level for SSL communication
+          ## Type: emergency | alert | critical | error | warning | notice | info | debug | none | all
+          log_level = notice
+
+          ## Hibernate the SSL process after idling for amount of time reducing its memory footprint
+          hibernate_after = 5s
+
+          ## Forces the cipher to be set based on the server-specified order instead of the client-specified order
+           honor_cipher_order = true
+
+          ##  Setting this to false to disable client-initiated renegotiation
+           client_renegotiation = true
+
+          ## Maximum time duration allowed for the handshake to complete
+           handshake_timeout = 15s
+      }
+    }
+}

+ 33 - 0
examples/cluster-with-etcd.conf.example

@@ -0,0 +1,33 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery using 'etcd' service mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = etcd
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+
+    etcd {
+      ## List of endpoint URLs of the etcd cluster
+      ## Type: Comma Separated String
+      server = "http://ur1,http://ur2"
+
+      ## Key prefix used for EMQX service discovery
+      prefix = emqxcl
+
+      ## Expiration time of the etcd key associated with the node
+      node_ttl = 1m
+    }
+}

+ 39 - 0
examples/cluster-with-k8s.conf.example

@@ -0,0 +1,39 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery via Kubernetes API server mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = k8s
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+
+    k8s {
+      ## Kubernetes API endpoint URL
+      apiserver = "https://kubernetes.default.svc:443"
+
+      ## EMQX broker service name
+      service_name = emqx
+
+      ## Address type used for connecting to the discovered nodes
+      ## Type: ip | dns | hostname
+      address_type = ip
+
+      ## Kubernetes namespace
+      namespace = default
+
+      ## Node name suffix
+      suffix = "pod.local"
+    }
+}

+ 21 - 0
examples/cluster-with-manual.conf.example

@@ -0,0 +1,21 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery via manual join mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = manual
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+ }

+ 24 - 0
examples/cluster-with-static.conf.example

@@ -0,0 +1,24 @@
+##--------------------------------------------------------------------
+## Cluster in service discovery via static nodes mode
+##
+## Configs to instruct how individual nodes can discover each other
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+cluster {
+    ## Human-friendly name of the EMQX cluster.
+    name = emqxcl
+
+    ## Service discovery method for the cluster nodes
+    discovery_strategy = static
+
+    ## List of core nodes that the replicant will connect to
+    core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+
+    ## If true, the node will try to heal network partitions automatically
+    autoheal = true
+
+    ## List EMQX node names in the static cluster
+    static.seeds = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+ }

+ 15 - 0
examples/conn_congestion.conf.example

@@ -0,0 +1,15 @@
+##--------------------------------------------------------------------
+## Connection Congestion
+##
+## Generating alarm when MQTT connection congested
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+conn_congestion {
+    ## Enable or disable connection congestion alarm
+    enable_alarm = true
+
+    ## Minimal time before clearing the alarm
+    min_alarm_sustain_duration = 1m
+}

+ 41 - 0
examples/dashboard-with-http.conf.example

@@ -0,0 +1,41 @@
+##--------------------------------------------------------------------
+## Dashboard with HTTP Listener
+##
+## Configuration for EMQX dashboard
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+dashboard {
+    ## JWT token expiration time
+    token_expired_time = 60m
+
+    ## Support Cross-Origin Resource Sharing (CORS)
+    cors = false
+
+    listeners.http {
+        ## Port or Address to listen on, 0 means disable
+        bind = "0.0.0.0:18083" ## or just a port number, e.g. 18083
+
+        ## Socket acceptor pool size for TCP protocols
+        num_acceptors = 8
+
+        ## Maximum number of simultaneous connections
+        max_connections = 512
+
+        ## Defines the maximum length that the queue of pending connections can grow to
+        backlog = 1024
+
+        ## Send timeout for the socket
+        send_timeout = 10s
+
+        ## Enable IPv6 support, default is false, which means IPv4 only
+        inet6 = false
+
+        ## Disable IPv4-to-IPv6 mapping for the listener
+        ipv6_v6only = false
+
+        ## Enable support for `HAProxy` header
+        proxy_header = false
+    }
+}

+ 86 - 0
examples/dashboard-with-https.conf.example

@@ -0,0 +1,86 @@
+##--------------------------------------------------------------------
+## Dashboard with HTTPS Listener
+##
+## Configuration for EMQX dashboard
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+dashboard {
+    ## JWT token expiration time
+    token_expired_time = 60m
+
+    ## Support Cross-Origin Resource Sharing (CORS)
+    cors = false
+
+    listeners.https {
+
+        ## Port or Address to listen on, 0 means disable
+        bind = "0.0.0.0:18084" ## or just a port number, e.g. 18084
+
+        ## Socket acceptor pool size for TCP protocols
+        num_acceptors = 8
+
+        ## Maximum number of simultaneous connections
+        max_connections = 512
+
+        ## Defines the maximum length that the queue of pending connections can grow to
+        backlog = 1024
+
+        ## Send timeout for the socket
+        send_timeout = 10s
+
+        ## Enable IPv6 support, default is false, which means IPv4 only
+        inet6 = false
+
+        ## Disable IPv4-to-IPv6 mapping for the listener
+        ipv6_v6only = false
+
+        ## Enable support for `HAProxy` header
+        proxy_header = false
+
+        ## Trusted PEM format CA certificates bundle file
+        cacertfile = "data/certs/cacert.pem"
+
+        ## PEM format certificates chain file
+        certfile = "data/certs/cert.pem"
+
+        ## PEM format private key file
+        keyfile = "data/certs/key.pem"
+
+        ## Enable or disable peer verification
+        verify = verify_none  ## use verify_peer to enable
+
+        ## Enable TLS session reuse
+        reuse_sessions = true
+
+        ## Maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path
+        depth = 10
+
+        ## Which versions are to be supported
+        versions = [tlsv1.3, tlsv1.2]
+
+        ## TLS cipher suite names
+        ## Note: By default, all available suites are supported, you do not need to set this
+        ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+
+        ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
+        secure_renegotiate = true
+
+        ## Log level for SSL communication
+        ## Type: emergency | alert | critical | error | warning | notice | info | debug | none | all
+        log_level = notice
+
+        ## Hibernate the SSL process after idling for amount of time reducing its memory footprint
+        hibernate_after = 5s
+
+        ## Forces the cipher to be set based on the server-specified order instead of the client-specified order
+        honor_cipher_order = true
+
+        ##  Setting this to false to disable client-initiated renegotiation
+        client_renegotiation = true
+
+        ## Maximum time duration allowed for the handshake to complete
+        handshake_timeout = 15s
+    }
+}

+ 15 - 0
examples/delayed.conf.example

@@ -0,0 +1,15 @@
+##--------------------------------------------------------------------
+## Delayed publish
+##
+## Configuring the delayed publish feature
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+delayed {
+    enable = true ## false for disabled
+
+    ## Maximum number of delayed messages
+    ## Default: 0 (0 is no limit)
+    max_delayed_messages = 0
+}

+ 52 - 0
examples/exhook.conf.example

@@ -0,0 +1,52 @@
+##--------------------------------------------------------------------
+## gRPC Hook Extension
+##
+## Allows users to process EMQX Hooks using other programming languages
+##--------------------------------------------------------------------
+
+exhook.servers = [
+    {
+        ## Name of the exhook server
+        name = "server_1"
+
+        ## Feature switch
+        enable = false
+
+        ## URL of gRPC server
+        url = "http://127.0.0.1:9090"
+
+        ## The timeout of request gRPC server
+        request_timeout = 5s
+
+        ## This value will be returned when the request to the gRPC server fails for any reason
+        ## Type:
+        ## - deny :: stop to execute this hook.
+        ## - ignore :: continue to execute this hook
+        failed_action = deny
+
+        ## Interval of automatically reconnecting the gRPC server when the connection is broken
+        ## Type:
+        ## - false :: Never reconnect
+        ## - Time Duration, e.g.15s, 10m, 1h :: Reconnecting Interval
+        auto_reconnect = 60s
+
+        ## The process pool size for gRPC client
+        pool_size = 8
+
+        ## Connection socket options
+        socket_options {
+            ## Whether periodic transmission on a connected socket when no other data is exchanged
+            keepalive = true
+
+            ## TCP_NODELAY switch
+            nodelay = true
+
+            ## The minimum size of receive buffer to use for the socket
+            recbuf = "64KB"
+
+            ## The minimum size of send buffer to use for the socket
+            sndbuf = "16KB"
+        }
+    },
+    {name = "server_2", url = "http://127.0.0.1:9091"}
+]

+ 50 - 0
examples/file_transfer-with-local-exporter.conf.example

@@ -0,0 +1,50 @@
+##--------------------------------------------------------------------
+## File Transfer
+##
+## Enables the File Transfer over MQTT feature
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: This configuration only works for the EMQX Enterprise version
+
+file_transfer {
+    ## Enable the File Transfer feature
+    enable = true
+
+    ## Storage backend settings
+    storage {
+        ## Local file system backend setting
+        ## Currently, it's the only available storage backend.
+        local {
+            ## Enable the backend
+            enable = true
+
+            ## Segments and temporary files storage settings
+            segments {
+                ## Directory where these files are stored
+                root = "/var/lib/emqx/transfers/segments"
+
+                ## Garbage collection settings
+                gc {
+                    ## How often to run GC
+                    interval = 1h
+
+                    ## Maximum time to keep parts of incomplete transfers for
+                    maximum_segments_ttl = 24h
+                }
+            }
+
+            ## Local filesystem exporter
+            exporter.local {
+
+                ## Enable the backend
+                ## Note: Only one backend may be enabled at a time
+                enable = true
+
+                ## Directory in the local file system where to store transferred files
+                root = "/var/lib/emqx/transfers/exports"
+            }
+        }
+    }
+}

+ 72 - 0
examples/file_transfer-with-s3-exporter.conf.example

@@ -0,0 +1,72 @@
+##--------------------------------------------------------------------
+## File Transfer
+##
+## Enables the File Transfer over MQTT feature
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: This configuration only works for the EMQX Enterprise version
+
+file_transfer {
+    ## Enable the File Transfer feature
+    enable = true
+
+    ## Storage backend settings
+    storage {
+        ## Local file system backend setting
+        ## Currently, it's the only available storage backend.
+        local {
+            ## Enable the backend
+            enable = true
+
+            ## Segments and temporary files storage settings
+            segments {
+                ## Directory where these files are stored
+                root = "/var/lib/emqx/transfers/segments"
+
+                ## Garbage collection settings
+                gc {
+                    ## How often to run GC
+                    interval = 1h
+
+                    ## Maximum time to keep parts of incomplete transfers for
+                    maximum_segments_ttl = 24h
+                }
+            }
+
+            ## S3-compatible object storage exporter
+            exporter.s3 {
+
+                ## Disable the backend
+                ## Note: Only one backend may be enabled at a time.
+                enable = true
+
+                ## Endpoint of S3 API of the object storage service of your choice
+                host = "s3.us-east-1.amazonaws.com"
+                port = 443
+
+                ## Credentials to use to authorize with the S3 API
+                access_key_id = "AKIA27EZDDM9XLINWXFE"
+                secret_access_key = "******"
+
+                ## Which bucket to store transferred files in?
+                bucket = "my-bucket"
+
+                ## TTL of file download URLs exposed through File Transfer API
+                url_expire_time = 1h
+
+                ## Enable the HTTPS
+                transport_options {
+                    ssl.enable = true
+
+                    ## Timeout for connection attempts
+                    connect_timeout = 15s
+
+                    ## Attempt to talk through IPv6 first
+                    ipv6_probe = true
+               }
+           }
+        }
+    }
+}

+ 21 - 0
examples/flapping_detect.conf.example

@@ -0,0 +1,21 @@
+##--------------------------------------------------------------------
+## Flapping Detect
+##
+## Ban the client when the times of connections exceed the limit in the time window
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+flapping_detect {
+    ## use false to disabled
+    enable = true
+
+    ## Time window for flapping detection
+    window_time = 1m
+
+    ## Maximum number of connects allowed for a MQTT Client in window_time
+    max_count = 15
+
+    ## How long the flapping clientid will be banned
+    ban_time = 5m
+}

+ 18 - 0
examples/force_gc.conf.example

@@ -0,0 +1,18 @@
+##--------------------------------------------------------------------
+## Force garbage collection
+##
+## Force garbage collection in MQTT connection process after they process certain number of messages or bytes of data
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+force_gc {
+    ## set to false to disable this
+    enable = true
+
+    ## GC the process after this many received messages
+    count = 16000
+
+    ## GC the process after specified number of bytes have passed through
+    bytes = 16MB
+}

+ 19 - 0
examples/force_shutdown.conf.example

@@ -0,0 +1,19 @@
+##--------------------------------------------------------------------
+## Force Shutdown
+##
+## Forced closing of the overloaded session
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+force_shutdown {
+    ## false to disable this
+    enable = true
+
+    ## Maximum mailbox size for each Erlang process
+    ## Note: Do not modify this unless you know what this is for
+    max_mailbox_size = 1000
+
+    ## Maximum heap size for each session process
+    max_heap_size = 32MB
+}

+ 24 - 0
examples/gateway.coap.conf.example

@@ -0,0 +1,24 @@
+##--------------------------------------------------------------------
+## Gateway CoAP
+##
+## Add a CoAP gateway
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+gateway.coap {
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string.
+    ## It's a way that you can use to implement isolation of message routing between different
+    ## gateway protocols
+    mountpoint = "coap/"
+
+    ## Enable or disable connection mode.
+    ## Connection mode is a feature of non-standard protocols. When connection mode is enabled,
+    ## it is necessary to maintain the creation, authentication and alive of connection resources
+    connection_required = false
+
+    listeners.udp.default {
+        bind = "0.0.0.0:5683"
+    }
+}

+ 31 - 0
examples/gateway.exproto.conf.example

@@ -0,0 +1,31 @@
+##--------------------------------------------------------------------
+## Gateway Exproto
+##
+## Add an Exproto gateway
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+gateway.exproto {
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string.
+    ## It's a way that you can use to implement isolation of message routing between different
+    ## gateway protocols
+    mountpoint = "exproto/"
+
+    ## Configurations for starting the ConnectionAdapter service
+    server {
+        bind = "0.0.0.0:9100"
+        ssl_options {verify = "verify_none"}
+    }
+
+    ## Configurations for request to ConnectionHandler service
+    handler {
+        address = "http://127.0.0.1:9001"
+        ssl_options {enable = false}
+    }
+
+    listeners.tcp.default {
+        bind = "0.0.0.0:7993"
+    }
+}

+ 62 - 0
examples/gateway.lwm2m.conf.example

@@ -0,0 +1,62 @@
+##--------------------------------------------------------------------
+## Gateway LwM2M
+##
+## Add a LwM2M gateway
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+gateway.lwm2m {
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string.
+    ## It's a way that you can use to implement isolation of message routing between different
+    ## gateway protocols
+    mountpoint = "lwm2m/"
+
+    ## The Directory for LwM2M Resource definition.
+    xml_dir = "etc/lwm2m_xml/"
+
+    ## Automatically observe the object list of REGISTER packet.
+    auto_observe = false
+
+    ## Minimum value of lifetime allowed to be set by the LwM2M client.
+    lifetime_min = 1s
+
+    ## Maximum value of lifetime allowed to be set by the LwM2M client.
+    lifetime_max = 86400s
+
+    ## The value of the time window during which the network link is considered valid by
+    ## the LwM2M Gateway in QMode mode.
+    qmode_time_window = 22s
+
+    ## Topic configuration for LwM2M's gateway publishing and subscription.
+    translators {
+        ## The topic for receiving downstream commands.
+        ## For each new LwM2M client that succeeds in going online, the gateway creates a
+        ## subscription relationship to receive downstream commands and send it to the LwM2M client
+        command { topic = "dn/#" }
+
+        ## The topic for gateway to publish the notify events from LwM2M client.
+        ## After succeed observe a resource of LwM2M client, Gateway will send the notify events
+        ## via this topic, if the client reports any resource changes
+        notify { topic = "up/notify" }
+
+        ## The topic for gateway to publish the register events from LwM2M client.
+        register { topic = "up/register" },
+
+        ## The topic for gateway to publish the acknowledge events from LwM2M client.
+        response { topic = "up/resp" },
+
+        ## The topic for gateway to publish the update events from LwM2M client.
+        update { topic = "up/resp" }
+    }
+
+    ## Policy for publishing UPDATE event message.<br/>
+    ##  - always: send update events as long as the UPDATE request is received.<br/>
+    ##  - contains_object_list: send update events only if the UPDATE request carries any Object List"""
+    update_msg_publish_condition = always
+
+    listeners.udp.default {
+        bind = "0.0.0.0:5784"
+    }
+}

+ 38 - 0
examples/gateway.mqttsn.conf.example

@@ -0,0 +1,38 @@
+##--------------------------------------------------------------------
+## Gateway MQTT-SN
+##
+## Add a MQTT-SN gateway
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+gateway.mqttsn {
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string.
+    ## It's a way that you can use to implement isolation of message routing between different
+    ## gateway protocols
+    mountpoint = "mqttsn/"
+
+    ## Whether to periodically broadcast ADVERTISE messages
+    broadcast = true
+
+    ## The Gateway ID.
+    ## When the broadcast option is enabled, the gateway will broadcast ADVERTISE message with this value
+    gateway_id = 1
+
+    ## Allows connectionless clients to publish messages with a Qos of -1.
+    ## This feature is defined for very simple client implementations which do not support any other
+    ## features except this one. There is no connection setup nor tear down, no registration nor
+    ## subscription. The client just sends its 'PUBLISH' messages to a GW
+    enable_qos3 = false
+
+    ## The pre-defined topic IDs and topic names
+    predefined = [
+        {id = 1, topic = "predefined/topic1"},
+        {id = 2, topic = "predefined/topic2"}
+    ]
+
+    listeners.udp.default {
+        bind = "0.0.0.0:1884"
+    }
+}

+ 30 - 0
examples/gateway.stomp.conf.example

@@ -0,0 +1,30 @@
+##--------------------------------------------------------------------
+## Gateway STOMP
+##
+## Add STOMP CoAP gateway
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+gateway.stomp {
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string.
+    ## It's a way that you can use to implement isolation of message routing between different
+    ## gateway protocols
+    mountpoint = "stomp/"
+
+    frame {
+        ## The maximum number of Header
+        max_headers = 10
+
+        ## The maximum string length of the Header name and value.
+        max_headers_length = 1024
+
+        ## The Maximum number of bytes of Body allowed per Stomp packet.
+        max_body_length = 65536
+    }
+
+    listeners.tcp.default {
+        bind = "0.0.0.0:61613"
+    }
+}

+ 19 - 0
examples/license.conf.example

@@ -0,0 +1,19 @@
+##--------------------------------------------------------------------
+## License
+##
+## Defines the EMQX Enterprise license
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: This configuration only works for the EMQX Enterprise version
+
+license {
+    ## License Key
+    key = "MjIwMTExCjAKMTAKRXZhbHVhdGlvbgpjb250YWN0QGVtcXguaW8KZGVmYXVsdAoyMDIzMDEwOQoxODI1CjEwMAo=.MEUCIG62t8W15g05f1cKx3tA3YgJoR0dmyHOPCdbUxBGxgKKAiEAhHKh8dUwhU+OxNEaOn8mgRDtiT3R8RZooqy6dEsOmDI="
+    ## Low watermark limit below which license connection quota usage alarms are deactivated
+    connection_low_watermark = "75%"
+
+    ## High watermark limit above which license connection quota usage alarms are activated
+    connection_high_watermark = "80%"
+}

+ 47 - 0
examples/listeners.quic.conf.example

@@ -0,0 +1,47 @@
+##--------------------------------------------------------------------
+## QUIC Listener
+##
+## Add a QUIC Listener
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: Modifying the 'quicname' to what you need
+listeners.quic.quicname {
+    ## Port or Address to listen on, 0 means disable
+    bind = 14567 ## or with an IP, e.g. "127.0.0.1:14567"
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string
+    mountpoint = "${clientid}/msg"
+
+    ## Client authentication
+    ## Type:
+    ##   - true :: enable
+    ##   - false :: disable
+    ##   - quick_deny_anonymous :: denied immediately without if username is not provided
+    enable_authn = true
+
+    ## Socket acceptor pool size for TCP protocols
+    acceptors = 16
+
+    ## Maximum number of simultaneous connections
+    ## Type: infinity | Integer
+    max_connections = infinity
+
+    ## TLS cipher suite names
+    ciphers = ["TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256"]
+
+    ssl_options {
+        ## Trusted PEM format CA certificates bundle file
+        cacertfile = "data/certs/cacert.pem"
+
+        ## PEM format certificates chain file
+        certfile = "data/certs/cert.pem"
+
+        ## PEM format private key file
+        keyfile = "data/certs/key.pem"
+
+        ## Enable or disable peer verification
+        verify = verify_none ## to verify_peer to enable
+    }
+}

+ 90 - 0
examples/listeners.ssl.conf.example

@@ -0,0 +1,90 @@
+##--------------------------------------------------------------------
+## SSL Listener
+##
+## Add a SSL Listener
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## The SSL listener also supports all the fields listed in listeners.tcp.conf.example
+## only the SSL-specific fields are shown here
+
+## Note: Modifying the 'sslname' to what you need
+listeners.ssl.sslname {
+    ## Port or Address to listen on, 0 means disable
+    bind = 8883 ## or with an IP e.g. "127.0.0.1:8883"
+    enabled = true
+    acceptors = 16
+    enable_authn = true
+    max_connections = infinity
+    mountpoint = ""
+    proxy_protocol = false
+    proxy_protocol_timeout = 3s
+    tcp_options {
+        active_n = 100
+        backlog = 1024
+        buffer = 4KB
+        high_watermark = 1MB
+        keepalive = none
+        nodelay = true
+        reuseaddr = true
+        send_timeout = 15s
+        send_timeout_close = true
+    }
+    ssl_options {
+        ## Trusted PEM format CA certificates bundle file
+        cacertfile = "data/certs/cacert.pem"
+
+        ## PEM format certificates chain file
+        certfile = "data/certs/cert.pem"
+
+        ## PEM format private key file
+        keyfile = "data/certs/key.pem"
+
+        ## Enable or disable peer verification
+        verify = verify_none  ## use verify_peer to enable
+
+        ## if `verify' is enabled, whit true, the connection fails if the client does not have a certificate to send
+        fail_if_no_peer_cert = false
+
+        ## Enable TLS session reuse
+        reuse_sessions = true
+
+        ## Maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path
+        depth = 10
+
+        ## Which versions are to be supported
+        versions = [tlsv1.3, tlsv1.2]
+
+        ## TLS cipher suite names
+        ## Note: By default, all available suites are supported, you do not need to set this
+        ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+
+        ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
+        secure_renegotiate = true
+
+        ## Log level for SSL communication
+        ## Type: emergency | alert | critical | error | warning | notice | info | debug | none | all
+        log_level = notice
+
+        ## Hibernate the SSL process after idling for amount of time reducing its memory footprint
+        hibernate_after = 5s
+
+        ## Forces the cipher to be set based on the server-specified order instead of the client-specified order
+        honor_cipher_order = true
+
+        ##  Setting this to false to disable client-initiated renegotiation
+        client_renegotiation = true
+
+        ## Maximum time duration allowed for the handshake to complete
+        handshake_timeout = 15s
+
+        ocsp {
+             enable_ocsp_stapling = false
+             responder_url = "http://ocsp.example.com"
+             issuer_pem = true
+             refresh_http_timeout = 15s
+             refresh_interval = 5m
+        }
+    }
+}

+ 77 - 0
examples/listeners.tcp.conf.example

@@ -0,0 +1,77 @@
+##--------------------------------------------------------------------
+## TCP Listener
+##
+## Add a TCP Listener
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: Modifying the 'tcpname' to what you need
+listeners.tcp.tcpname {
+    ## Port or Address to listen on, 0 means disable
+    bind = 1883 ## or with an IP e.g. "127.0.0.1:1883"
+
+    ## Enable the Proxy Protocol V1/2 if the EMQX cluster is deployed behind HAProxy or Nginx
+    proxy_protocol = false
+
+    ## Timeout for proxy protocol
+    proxy_protocol_timeout = 8
+
+    ## When publishing or subscribing, prefix all topics with a mountpoint string
+    mountpoint = "mqtt" ## Do not set this unless you know what is it for
+
+    ## Client authentication
+    ## Type:
+    ##   - true :: enable
+    ##   - false :: disable
+    ##   - quick_deny_anonymous :: denied immediately without if username is not provided
+    enable_authn = true
+
+    ## The access control rules for this listener
+    ## Type: See: https://github.com/emqtt/esockd#allowdeny
+    access_rules = ["allow all"]
+
+    ## Socket acceptor pool size for TCP protocols
+    acceptors = 16
+
+    ## Maximum number of simultaneous connections
+    ## Type: infinity | Integer
+    max_connections = infinity
+
+    tcp_options {
+        ## TCP backlog defines the maximum length that the queue of pending connections can grow to
+        backlog = 1024
+
+        ## The TCP send timeout for the connections
+        send_timeout = 15s
+
+        ## Timeout for proxy protocol
+        send_timeout_close = true
+
+        ## The TCP receive buffer (OS kernel) for the connections
+        recbuf = 2KB
+
+        ## The TCP send buffer (OS kernel) for the connections
+        sndbuf = 4KB
+
+        ## The size of the user-space buffer used by the driver
+        buffer = 4KB
+
+        ## The socket is set to a busy state when the amount of data queued internally by the VM socket implementation reaches this limit
+        high_watermark = 1MB
+
+        ## The TCP_NODELAY flag for the connections
+        nodelay = true
+
+        ## The SO_REUSEADDR flag for the connections
+        reuseaddr = true
+
+        ## Enable TCP keepalive for MQTT connections over TCP or SSL
+        ## Type: three comma separated numbers in the format of 'Idle,Interval,Probes'
+        ##    - Idle: The number of seconds a connection needs to be idle before the server begins to send out keep-alive probes (Linux default 7200).
+        ##    - Interval: The number of seconds between TCP keep-alive probes (Linux default 75).
+        ##    - Probes: The maximum number of TCP keep-alive probes to send before giving up and killing the connection if no response is obtained from the other end (Linux default 9).
+        ## For example "240,30,5" means: EMQX should start sending TCP keepalive probes after the connection is in idle for 240 seconds, and the probes are sent every 30 seconds until a response is received from the MQTT client, if it misses 5 consecutive responses, EMQX should close the connection
+        keepalive = "none"
+    }
+}

+ 76 - 0
examples/listeners.ws.conf.example

@@ -0,0 +1,76 @@
+##--------------------------------------------------------------------
+## WebSocket Listener
+##
+## Add a WebSocket Listener
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## The WebSocket listener supports all the fields listed in listeners.tcp.conf.example
+## only the WebSocket-specific fields are shown here
+
+## Note: Modifying the 'wsname' to what you need
+listeners.ws.wsname {
+    ## Port or Address to listen on, 0 means disable
+    bind = "0.0.0.0:8083" # or just a port number, e.g. 8083
+    enabled = true
+    enable_authn = true
+    max_connections = infinity
+    proxy_protocol = false
+    proxy_protocol_timeout = 3s
+    mountpoint = ""
+    tcp_options {
+        active_n = 100
+        backlog = 1024
+        buffer = 4KB
+        high_watermark = 1MB
+        keepalive = none
+        nodelay = true
+        reuseaddr = true
+        send_timeout = 15s
+        send_timeout_close = true
+    }
+
+    websocket {
+        ## WebSocket's MQTT protocol path
+        ## Type: String
+        ##   For Example:
+        ##     with the default value, the address of EMQX Broker's WebSocket is: ws://8083/mqtt
+        mqtt_path = "/mqtt"
+
+        ## Whether a WebSocket message is allowed to contain multiple MQTT packets
+        ## Type: single | multiple
+        mqtt_piggyback = multiple
+
+        ## If true, compress WebSocket messages using zlib
+        compress = false
+
+        ## Close transport-layer connections from the clients that have not sent MQTT CONNECT message within this interval
+        idle_timeout = 7200s
+
+        ## The maximum length of a single MQTT packet
+        ## Type: infinity | Integer
+        max_frame_size = infinity
+
+        ## If true, the server will return an error when the client does not carry the Sec-WebSocket-Protocol field
+        fail_if_no_subprotocol = true
+
+        ## Comma-separated list of supported subprotocols
+        supported_subprotocols = "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5"
+
+        ## If true, origin HTTP header will be validated against the list of allowed origins configured in check_origins parameter
+        check_origin_enable = false
+
+        ## If false and check_origin_enable is true, the server will reject requests that don't have origin HTTP header
+        allow_origin_absence = true
+
+        ## List of allowed origins
+        check_origins = "http://localhost:18083, http://127.0.0.1:18083"
+
+        ## HTTP header used to pass information about the client IP address
+        proxy_address_header = "x-forwarded-for"
+
+        ## The maximum length of a single MQTT packet
+        proxy_port_header = "x-forwarded-port"
+    }
+}

+ 104 - 0
examples/listeners.wss.conf.example

@@ -0,0 +1,104 @@
+##--------------------------------------------------------------------
+## WSS Listener
+##
+## Add a WSS Listener
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## The WSS listener supports all the fields listed in listeners.ws.conf.example
+## only the WSS-specific fields are shown here
+
+## Note: Modifying the 'wssname' to what you need
+listeners.wss.wssname {
+    ## Port or Address to listen on, 0 means disable
+    bind = 8084 ## or with an IP, e.g. "127.0.0.1:8084"
+    enabled = true
+    enable_authn = true
+    max_connections = infinity
+    proxy_protocol = false
+    proxy_protocol_timeout = 3s
+    mountpoint = ""
+    tcp_options {
+        active_n = 100
+        backlog = 1024
+        buffer = 4KB
+        high_watermark = 1MB
+        keepalive = none
+        nodelay = true
+        reuseaddr = true
+        send_timeout = 15s
+        send_timeout_close = true
+      }
+      websocket {
+        allow_origin_absence = true
+        check_origin_enable = false
+        check_origins = "http://localhost:18083, http://127.0.0.1:18083"
+        compress = false
+        deflate_opts {
+          client_context_takeover = "takeover"
+          client_max_window_bits = 15
+          mem_level = 8
+          server_context_takeover = "takeover"
+          server_max_window_bits = 15
+          strategy = "default"
+        }
+        fail_if_no_subprotocol = true
+        idle_timeout = "7200s"
+        max_frame_size = "infinity"
+        mqtt_path = "/mqtt"
+        mqtt_piggyback = "multiple"
+        proxy_address_header = "x-forwarded-for"
+        proxy_port_header = "x-forwarded-port"
+        supported_subprotocols = "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5"
+      }
+
+    ssl_options {
+        ## Trusted PEM format CA certificates bundle file
+        cacertfile = "data/certs/cacert.pem"
+
+        ## PEM format certificates chain file
+        certfile = "data/certs/cert.pem"
+
+        ## PEM format private key file
+        keyfile = "data/certs/key.pem"
+
+        ## Enable or disable peer verification
+        verify = verify_none  ## use verify_peer to enable
+
+        ## if `verify' is enabled, whit true, the connection fails if the client does not have a certificate to send
+        fail_if_no_peer_cert = false
+
+        ## Enable TLS session reuse
+        reuse_sessions = true
+
+        ## Maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path
+        depth = 10
+
+        ## Which versions are to be supported
+        versions = [tlsv1.3, tlsv1.2]
+
+        ## TLS cipher suite names
+        ## Note: By default, all available suites are supported, you do not need to set this
+        ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+
+        ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
+        secure_renegotiate = true
+
+        ## Log level for SSL communication
+        ## Type: emergency | alert | critical | error | warning | notice | info | debug | none | all
+        log_level = notice
+
+        ## Hibernate the SSL process after idling for amount of time reducing its memory footprint
+        hibernate_after = 5s
+
+        ## Forces the cipher to be set based on the server-specified order instead of the client-specified order
+        honor_cipher_order = true
+
+        ##  Setting this to false to disable client-initiated renegotiation
+        client_renegotiation = true
+
+        ## Maximum time duration allowed for the handshake to complete
+        handshake_timeout = 15s
+    }
+}

+ 27 - 0
examples/log.console.conf.example

@@ -0,0 +1,27 @@
+##--------------------------------------------------------------------
+## Log
+##
+## Configure the log output location, log level, log file storage path, and parameters
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+log.console {
+    ## set true to enable this
+    enable = false
+
+    ## Log level
+    ## Type: debug | info | notice | warning | error | critical | alert | emergency
+    level = warning
+
+    ## Log formatter, text for free text, and json for structured logging
+    ## Type: text | json
+    formatter = text
+
+    ## Time offset for formatting the timestamp
+    ## Type:
+    ##   - system :: local system time
+    ##   - utc :: UTC time
+    ##   - +-[hh]:[mm]: user specified time offset, such as "-02:00" or "+00:00" Defaults to: system
+    time_offset = system
+}

+ 38 - 0
examples/log.file.conf.example

@@ -0,0 +1,38 @@
+##--------------------------------------------------------------------
+## Log
+##
+## Configure the log output location, log level, log file storage path, and parameters
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## The default-enabled log handler can use all the above fields listed fields
+log.file {
+    ## use false to disable this
+    enable = true
+
+    ## Log level
+    ## Type: debug | info | notice | warning | error | critical | alert | emergency
+    level = warning
+
+    ## Log formatter, text for free text, and json for structured logging
+    ## Type: text | json
+    formatter = text
+
+    ## Time offset for formatting the timestamp
+    ## Type:
+    ##   - system :: local system time
+    ##   - utc :: UTC time
+    ##   - +-[hh]:[mm]: user specified time offset, such as "-02:00" or "+00:00" Defaults to: system
+    time_offset = system
+
+    ## Maximum number of log files
+    ## Type: Range from 1 to 128
+    rotation_count = 10
+
+    ## This parameter controls log file rotation
+    ## Type:
+    ##  - infinity :: the log file will grow indefinitely
+    ##  - ByteSize :: the log file will be rotated once it reaches this value in bytes
+    rotation_size = 50MB
+}

+ 124 - 0
examples/mqtt.conf.example

@@ -0,0 +1,124 @@
+##--------------------------------------------------------------------
+## MQTT
+##
+##  MQTT configuration
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+mqtt {
+    ## After the TCP connection is established,
+    ## if the MQTT CONNECT packet from the client is not received within the time specified by idle_timeout, the connection will be disconnected
+    ## Type:
+    ##   - infinity :: Never disconnect
+    ##   - Time Duration :: The idle time
+    idle_timeout = 15s
+
+    ## Maximum MQTT packet size allowed
+    max_packet_size = 1MB
+
+    ## Maximum allowed length of MQTT Client ID
+    ## Type: Rnage from 23 to 65535
+    max_clientid_len = 65535
+
+    ## Maximum topic levels allowed
+    ## Type: Range from 1 to 65535
+    max_topic_levels = 128
+
+    ## Maximum QoS allowed
+    max_qos_allowed = 2
+
+    ## Maximum topic alias, 0 means no topic alias supported
+    ## Type: Range from 0 to 65535
+    max_topic_alias = 65535
+
+    ## Whether to enable support for MQTT retained message
+    retain_available = true
+
+    ## Whether to enable support for MQTT wildcard subscription
+    wildcard_subscription = true
+
+    ## Whether to enable support for MQTT shared subscription
+    shared_subscription = true
+
+    ## Whether to enable support for MQTT exclusive subscription
+    exclusive_subscription = false
+
+    ## Ignore loop delivery of messages for MQTT v3.1.1/v3.1.0, similar to No Local subscription option in MQTT 5.0
+    ignore_loop_deliver = false
+
+    ## Parse MQTT messages in strict mode.
+    ## When set to true, invalid utf8 strings in for example client ID, topic name, etc. will cause the client to be disconnected
+    strict_mode = false
+
+    ## Specify the response information returned to the client
+    response_information  = ""
+
+    ## The keep alive that EMQX requires the client to use
+    ## Type:
+    ##   - disabled :: the keep alive specified by the client will be used
+    ##   - Integer :: Keepalive time, only applicable to clients using MQTT 5.0 protocol
+    server_keepalive = disabled
+
+    ## Keep-Alive Timeout = Keep-Alive interval × Keep-Alive Multiplier
+    keepalive_multiplier = 1.5
+
+    ## Maximum number of subscriptions allowed per client
+    ## Type: infinity | Integer
+    max_subscriptions = infinity
+
+    ## Force upgrade of QoS level according to subscription
+    upgrade_qos = false
+
+    ## Maximum number of QoS 1 and QoS 2 messages that are allowed to be delivered simultaneously before completing the acknowledgment
+    ## Type: Range from 1 to 65535
+    max_inflight = 32
+
+    ## Retry interval for QoS 1/2 message delivering
+    retry_interval = 30s
+
+    ## For each publisher session, the maximum number of outstanding QoS 2 messages pending on the client to send PUBREL
+    ## Type: infinity | Integer
+    max_awaiting_rel = 100
+
+    ## For client to broker QoS 2 message, the time limit for the broker to wait before the PUBREL message is received
+    await_rel_timeout = 300s
+
+    ## Specifies how long the session will expire after the connection is disconnected, only for non-MQTT 5.0 connections
+    session_expiry_interval = 2h
+
+    ## Maximum queue length. Enqueued messages when persistent client disconnected, or inflight window is full
+    ## Type: infinity | Integer
+    max_mqueue_len = 1000
+
+    ## Specifies whether to store QoS 0 messages in the message queue while the connection is down but the session remains
+    mqueue_store_qos0 = true
+
+    ## Whether to user Client ID as Username
+    use_username_as_clientid = false
+
+    ## Use the CN, DN field in the peer certificate or the entire certificate content as Username
+    ## Type:
+    ##   - disabled
+    ##   - cn :: CN field of the certificate
+    ##   - dn :: DN field of the certificate
+    ##   - crt :: the content of the DER or PEM certificate
+    ##   - pem :: PEM format content converted from DER certificate content
+    ##   - md5 :: the MD5 value of the content of the DER or PEM certificate
+    peer_cert_as_username = disabled
+
+    ## Use the CN, DN field in the peer certificate or the entire certificate content as Client ID
+    ## Type: See the above
+    peer_cert_as_clientid = disabled
+
+    ## Dispatch strategy for shared subscription
+    ## Type:
+    ##   - random :: dispatch the message to a random selected subscriber
+    ##   - round_robin :: select the subscribers in a round-robin manner
+    ##   - round_robin_per_group :: select the subscribers in round-robin fashion within each shared subscriber group
+    ##   - local :: select random local subscriber otherwise select random cluster-wide
+    ##   - sticky :: always use the last selected subscriber to dispatch, until the subscriber disconnects.
+    ##   - hash_clientid :: select the subscribers by hashing the `clientIds`
+    ##   - hash_topic :: select the subscribers by hashing the source topic"""
+    shared_subscription_strategy = round_robin
+ }

+ 43 - 0
examples/node.conf.example

@@ -0,0 +1,43 @@
+##--------------------------------------------------------------------
+## Node
+##
+## configuring for current EMQX node
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+## Note: all fields in this section are immutable after EMQX started, and most of the time you only need to modify the value for the name and cookie.
+node {
+    ## The actions triggered when the alarm is activated
+    ## Type: Formatted String
+    ##   Format: any_name@any_domain or an_name@any_ip
+    ##   Note: Make sure the IP resolve from the domain is deterministic and unique and never change
+    name = "emqx@127.0.0.1"
+
+    ## Secret cookie is a random string that should be the same on all nodes in the given EMQX cluster, but unique per EMQX cluster
+    cookie = "Yzc0NGExM2RjYzYxYzM0YzQ5MWQ0NmI1NWM0MWRhMzY4NzgxYmFkMmI2MWJjZWQ5NTQzYTMxNjE1ODVmYmJmMyAgLQo="
+
+    ## Select a node role
+    ## Type:
+    ##   - core :: nodes provide durability of the data, and take care of writes
+    ##   - replicant :: nodes are ephemeral worker nodes
+    role = core
+
+    ## Maximum number of simultaneously existing processes for this Erlang system
+    ## Type: Range from 1024 to 134217727
+    process_limit = 2097152
+
+    ## Maximum number of simultaneously existing ports for this Erlang system
+    ## Type: Range from 1024 to 134217727
+    max_ports = 1048576
+
+    ## Erlang's distribution buffer busy limit in kilobytes
+    ## Type: Range from 1 to 2097152
+    dist_buffer_size = 8192
+
+    ## Path to the persistent data directory
+    data_dir = "var/emqx/data"
+
+    ## Type: Periodic garbage collection interval
+    global_gc_interval = 15m
+}

+ 27 - 0
examples/plugin.conf.example

@@ -0,0 +1,27 @@
+##--------------------------------------------------------------------
+## Plugin
+##
+## Manage EMQX plugins
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+plugin {
+    ## Plugins declaration
+    ## Note: The plugins are started in the defined order
+    states = [
+        {
+            ## Name and version of this plugin
+            ## Type: Formatted String
+            ##     Format: {name}-{version}
+            ##     Note: name and version should be what it is in the plugin application
+            name_vsn = "my_acl-0.1.0",
+
+            enable = true ## enable this plugin
+        },
+        {name_vsn = "my_rule-0.1.1", enable = false}
+    ]
+
+    ## The installation directory for the external plugins
+    install_dir = "plugins"
+}

+ 28 - 0
examples/prometheus.conf.example

@@ -0,0 +1,28 @@
+##--------------------------------------------------------------------
+## Prometheus
+##
+## Settings for reporting metrics to Prometheus
+##--------------------------------------------------------------------
+
+prometheus {
+    ## URL of Prometheus server
+    push_gateway_server = "http://127.0.0.1:9091"
+
+    ## Data reporting interval
+    interval = 15s
+
+    ## A HTTP Headers when pushing to Push Gateway.
+    headers = {
+        Authorization = "some-authz-tokens",
+        Connection = "keep-alive"
+    }
+
+    ## Job Name that is pushed to the Push Gateway.
+    ## Available variable:
+    ## - ${name}: Name of EMQX node
+    ## - ${host}: Host name of EMQX node
+    job_name = "${name}/instance/${name}~${host}"
+
+    ## set to false to enable this
+    enable = true
+}

+ 21 - 0
examples/psk_authentication.conf.example

@@ -0,0 +1,21 @@
+##--------------------------------------------------------------------
+## Pre-Shared Keys authentication
+##
+## Config to enable TLS-PSK authentication
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+psk_authentication {
+    ## set to false to disable
+    enable = true
+
+    ## If init_file is specified, EMQX will import PSKs from the file into the built-in database at startup for use by the runtime
+    init_file = "psk"
+
+    ## The separator between PSKIdentity and SharedSecret in the PSK file
+    separator = ":"
+
+    ## The size of each chunk used to import to the built-in database from PSK file
+    chunk_size = 50
+ }

+ 40 - 0
examples/retainer.conf.example

@@ -0,0 +1,40 @@
+##--------------------------------------------------------------------
+## Retainer
+##
+## Configuration related to handling PUBLISH packets with a retain flag set to 1
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+retainer {
+    ## set to false to disable this
+    enable = true
+
+    ## Message retention time. 0 means message will never be expired
+    msg_expiry_interval = 0s
+
+    ## Periodic interval for cleaning up expired messages. Never clear if the value is 0
+    msg_clear_interval = 0s
+
+    ## Maximum retained message size
+    max_payload_size = 1MB
+
+    ## When the retained flag of the PUBLISH message is set and Payload is empty, whether to continue to publish the message
+    stop_publish_clear_msg = false
+
+    ## Maximum retained messages delivery rate per session
+    deliver_rate = "1000/s"
+
+    ## Retained messages store backend
+    backend {
+      ## Backend type
+      type = built_in_database
+
+      ## Specifies whether the messages are stored in RAM or persisted on disc
+      ## Type: enum: ram | disc
+      storage_type = ram
+
+      ## Maximum number of retained messages. 0 means no limit
+      max_retained_messages = 0
+     }
+ }

+ 25 - 0
examples/sys_topics.conf.example

@@ -0,0 +1,25 @@
+##--------------------------------------------------------------------
+## System Topic
+##
+## Publishing client lifecycle events to "$SYS" topics
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+sys_topics {
+    ## Time interval of publishing `$SYS` messages
+    sys_msg_interval = 1m
+
+    ## Time interval for publishing following heartbeat messages:
+    ##   - `$SYS/brokers/<node>/uptime`
+    ##   - `$SYS/brokers/<node>/datetime`
+    sys_heartbeat_interval = 30s
+
+    ## Client events messages toggle
+    sys_event_messages = {
+        client_connected = true
+        client_disconnected = true
+        client_subscribed = false
+        client_unsubscribed = false
+    }
+}

+ 30 - 0
examples/sysmon.os.conf.example

@@ -0,0 +1,30 @@
+##--------------------------------------------------------------------
+## System Monitoring For System
+##
+## System monitoring and introspection
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+sysmon.os {
+    ## Time interval for the periodic CPU check
+    cpu_check_interval = 60s
+
+    ## For how much system cpu can be used before the corresponding alarm is raised
+    cpu_high_watermark = 80%
+
+    ## For how much system cpu can be used before the corresponding alarm is cleared
+    cpu_low_watermark = 60%
+
+    ## Time interval for the periodic memory check
+    ## Type:
+    ##   - disabled :: Never check
+    ##   - Time Duration :: The time period
+    mem_check_interval = 60s
+
+    ## For how much system memory can be allocated before the corresponding alarm is raised
+    sysmem_high_watermark = 70%
+
+    ## For how much system memory can be allocated by one Erlang process before the corresponding alarm is raised
+    procmem_high_watermark = 5%
+}

+ 42 - 0
examples/sysmon.vm.conf.example

@@ -0,0 +1,42 @@
+##--------------------------------------------------------------------
+## System Monitoring For Erlang VM
+##
+## System monitoring and introspection
+##--------------------------------------------------------------------
+## Note: This is an example of how to configure this feature
+##       you should copy and paste the below data into the emqx.conf for working
+
+sysmon.vm {
+    ## Time interval for the periodic process limit check
+    process_check_interval = 30s
+
+    ## For how many processes can simultaneously exist at the local node before the corresponding alarm is raised
+    process_high_watermark = 80%
+
+    ## For how many processes can simultaneously exist at the local node before the corresponding alarm is cleared
+    process_low_watermark = 60%
+
+    ## Generated an alarm when an Erlang process spends a long time to perform garbage collection
+    ## Type:
+    ##   - disabled :: Never alarm
+    ##   - Time During :: The maximum GC time for generating an alarm
+    long_gc = 100ms
+
+    ## Generating an alarm is generated when the Erlang VM detect a task scheduled for too long
+    ## Type:
+    ##   - disabled :: Never alarm
+    ##   - Time During :: The maximum schedule time for generating an alarm
+    long_schedule = 240ms
+
+    ## Generating an alarm when an Erlang process consumed a large amount of memory for its heap space
+    ## Type:
+    ##   - disabled :: Never alarm
+    ##   - ByteSize :: The maximum heap size for generating an alarm
+    large_heap = 32MB
+
+    ## Generating an alarm when the RPC connection is overloaded
+    busy_dist_port = true
+
+    ## Generating an alarm when a port (e.g. TCP socket) is overloaded
+    busy_port = true
+}

+ 4 - 4
mix.exs

@@ -55,7 +55,7 @@ defmodule EMQXUmbrella.MixProject do
       {:cowboy, github: "emqx/cowboy", tag: "2.9.2", override: true},
       {:esockd, github: "emqx/esockd", tag: "5.9.6", override: true},
       {:rocksdb, github: "emqx/erlang-rocksdb", tag: "1.7.2-emqx-11", override: true},
-      {:ekka, github: "emqx/ekka", tag: "0.15.2", override: true},
+      {:ekka, github: "emqx/ekka", tag: "0.15.3", override: true},
       {:gen_rpc, github: "emqx/gen_rpc", tag: "2.8.1", override: true},
       {:grpc, github: "emqx/grpc-erl", tag: "0.6.8", override: true},
       {:minirest, github: "emqx/minirest", tag: "1.3.11", override: true},
@@ -536,9 +536,9 @@ defmodule EMQXUmbrella.MixProject do
 
     profile = System.get_env("MIX_ENV")
 
-    Mix.Generator.copy_file(
-      "_build/docgen/#{profile}/emqx.conf.example",
-      Path.join(etc, "emqx.conf.example"),
+    File.cp_r!(
+      "examples",
+      Path.join(etc, "examples"),
       force: overwrite?
     )
 

+ 1 - 1
rebar.config

@@ -62,7 +62,7 @@
     , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}}
     , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.6"}}}
     , {rocksdb, {git, "https://github.com/emqx/erlang-rocksdb", {tag, "1.7.2-emqx-11"}}}
-    , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.15.2"}}}
+    , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.15.3"}}}
     , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.1"}}}
     , {grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.8"}}}
     , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.3.11"}}}

+ 1 - 14
rebar.config.erl

@@ -524,7 +524,7 @@ etc_overlay(ReleaseType, _Edition) ->
     [
         {mkdir, "etc/"},
         {copy, "{{base_dir}}/lib/emqx/etc/certs", "etc/"},
-        {copy, "_build/docgen/" ++ profile() ++ "/emqx.conf.example", "etc/emqx.conf.example"}
+        {copy, "examples", "etc/"}
     ] ++
         lists:map(
             fun
@@ -652,16 +652,3 @@ list_dir(Dir) ->
         false ->
             []
     end.
-
-profile() ->
-    case os:getenv("PROFILE") of
-        Profile = "emqx-enterprise" ++ _ ->
-            Profile;
-        Profile = "emqx" ++ _ ->
-            Profile;
-        false ->
-            "emqx-enterprise";
-        Profile ->
-            io:format(standard_error, "ERROR: bad_PROFILE ~p~n", [Profile]),
-            exit(bad_PROFILE)
-    end.

+ 1 - 1
rel/i18n/emqx_prometheus_schema.hocon

@@ -4,7 +4,7 @@ enable.desc:
 """Turn Prometheus data pushing on or off"""
 
 headers.desc:
-"""A list of HTTP Headers when pushing to Push Gateway.<br/>
+"""An HTTP Headers when pushing to Push Gateway.<br/>
 For example, <code> { Authorization = "some-authz-tokens"}</code>"""
 
 interval.desc:

+ 52 - 5
scripts/test/start-two-nodes-in-host.sh

@@ -12,10 +12,40 @@ set -euo pipefail
 # ensure dir
 cd -P -- "$(dirname -- "$0")/../../"
 
-DEFAULT_BOOT='./_build/emqx/rel/emqx/bin/emqx'
+help() {
+    echo
+    echo "-h|--help: To display this usage info"
+    echo "-b|--boots: boot scripts, comma separate if more than one"
+    echo "            default is ./_build/emqx/rel/emqx/bin/emqx"
+    echo "-r|--roles: node (db) roles, comma separate"
+}
+
+BOOT='./_build/emqx/rel/emqx/bin/emqx'
+ROLES='core,core'
+while [ "$#" -gt 0 ]; do
+    case $1 in
+        -h|--help)
+            help
+            exit 0
+            ;;
+        -b|--boots)
+            BOOT="$2"
+            shift 2
+            ;;
+        -r|--roles)
+            ROLES="$2"
+            shift 2
+            ;;
+        *)
+            echo "unknown option $1"
+            exit 1
+            ;;
+    esac
+done
 
-BOOT1="${1:-$DEFAULT_BOOT}"
-BOOT2="${2:-$BOOT1}"
+BOOT1="$(echo "$BOOT" | cut -d ',' -f1)"
+BOOT2="$(echo "$BOOT" | cut -d ',' -f2)"
+[ -z "$BOOT2" ] && BOOT2="$BOOT1"
 
 export IP1='127.0.0.1'
 export IP2='127.0.0.2'
@@ -24,6 +54,22 @@ export IP2='127.0.0.2'
 NODE1="emqx1@$IP1"
 NODE2="emqx2@$IP2"
 
+ROLE1="$(echo "$ROLES" | cut -d ',' -f1)"
+ROLE2="$(echo "$ROLES" | cut -d ',' -f2)"
+export ROLE1 ROLE2
+
+if [ "$ROLE1" = 'core' ] && [ "$ROLE2" = 'core' ]; then
+    SEEDS="$NODE1,$NODE2"
+elif [ "$ROLE1" = 'core' ]; then
+    SEEDS="$NODE1"
+elif [ "$ROLE2" = 'core' ]; then
+    SEEDS="$NODE2"
+else
+    echo "missing 'core' role in -r|--roles option"
+    exit 1
+fi
+export SEEDS
+
 start_cmd() {
     local index="$1"
     local nodehome
@@ -33,11 +79,12 @@ start_cmd() {
     mkdir -p "${nodehome}/data" "${nodehome}/log"
     cat <<-EOF
 env DEBUG="${DEBUG:-0}" \
-EMQX_CLUSTER__STATIC__SEEDS="[\"$NODE1\",\"$NODE2\"]" \
+EMQX_NODE_NAME="emqx${index}@\$IP${index}" \
+EMQX_CLUSTER__STATIC__SEEDS="$SEEDS" \
 EMQX_CLUSTER__DISCOVERY_STRATEGY=static \
+EMQX_NODE__DB_ROLE="\$ROLE${index}" \
 EMQX_LOG__FILE_HANDLERS__DEFAULT__LEVEL="${EMQX_LOG__FILE_HANDLERS__DEFAULT__LEVEL:-debug}" \
 EMQX_LOG__FILE_HANDLERS__DEFAULT__FILE="${nodehome}/log/emqx.log" \
-EMQX_NODE_NAME="emqx${index}@\$IP${index}" \
 EMQX_NODE__COOKIE="${EMQX_NODE__COOKIE:-cookie1}" \
 EMQX_LOG_DIR="${nodehome}/log" \
 EMQX_NODE__DATA_DIR="${nodehome}/data" \