diff --git a/apps/emqx/mix.exs b/apps/emqx/mix.exs new file mode 100644 index 000000000..2daf2cfb9 --- /dev/null +++ b/apps/emqx/mix.exs @@ -0,0 +1,43 @@ +defmodule EMQX.MixProject do + use Mix.Project + + def project do + [ + app: :emqx, + version: "5.0.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X" + ] + end + + def application do + [ + mod: {:emqx_app, []}, + extra_applications: [:logger, :os_mon, :syntax_tools] + ] + end + + defp deps do + [ + # {:gproc, "0.9.0"}, + # {:recon, "2.5.2"}, + {:cowboy, github: "emqx/cowboy", tag: "2.8.3"}, + {:esockd, github: "emqx/esockd", tag: "5.9.0"}, + {:gproc, github: "uwiger", tag: "0.8.0"}, + {:ekka, github: "emqx/ekka", tag: "0.11.1"}, + # {:gen_rpc, github: "emqx/gen_rpc", tag: "2.5.1"}, + # {:cuttlefish, github: "emqx/cuttlefish", tag: "v4.0.1"}, + {:hocon, github: "emqx/hocon", tag: "0.22.0"}, + # {:pbkdf2, github: "emqx/erlang-pbkdf2", tag: "2.0.4"}, + # {:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.14.0"}, + # {:jiffy, github: "emqx/jiffy", tag: "1.0.5"}, + {:lc, github: "qzhuyan/lc", tag: "0.1.2"}, + ] + end +end diff --git a/apps/emqx/src/emqx_config.erl b/apps/emqx/src/emqx_config.erl index b9dabbb27..6856a1c0e 100644 --- a/apps/emqx/src/emqx_config.erl +++ b/apps/emqx/src/emqx_config.erl @@ -245,6 +245,10 @@ put_raw(KeyPath, Config) -> do_put(?RAW_CONF, KeyPath, Config). %%============================================================================ init_load(SchemaMod) -> ConfFiles = application:get_env(emqx, config_files, []), + ?SLOG(warning, #{ msg => ">>>>>>>>> config:init_load enter" + , schema_mod => SchemaMod + , conf_files => ConfFiles + }), init_load(SchemaMod, ConfFiles). %% @doc Initial load of the given config files. @@ -259,7 +263,7 @@ init_load(SchemaMod, Conf) when is_list(Conf) orelse is_binary(Conf) -> false -> fun hocon:files/2 end, Res = Parser(Conf, ParseOptions), - io:format(user, "~n>>>>>>>>>>>>>>>>>> config:init_load parse res ~120p ~n", [Res]), + %% io:format(user, "~n>>>>>>>>>>>>>>>>>> config:init_load parse res ~120p ~n", [Res]), case Res of {ok, RawRichConf} -> init_load(SchemaMod, RawRichConf); @@ -271,8 +275,8 @@ init_load(SchemaMod, Conf) when is_list(Conf) orelse is_binary(Conf) -> error(failed_to_load_hocon_conf) end; init_load(SchemaMod, RawConf) when is_map(RawConf) -> - io:format(user, ">>>>>>>>>> config:init_load is_map ~p ~100p ~n", - [SchemaMod, RawConf]), + %% io:format(user, ">>>>>>>>>> config:init_load is_map ~p ~100p ~n", + %% [SchemaMod, RawConf]), ok = save_schema_mod_and_names(SchemaMod), %% check configs agains the schema, with environment variables applied on top {_AppEnvs, CheckedConf} = @@ -386,8 +390,8 @@ save_to_app_env(AppEnvs) -> -spec save_to_config_map(config(), raw_config()) -> ok. save_to_config_map(Conf, RawConf) -> - io:format(user, ">>>>>>> config:save_to_config_map ~p ~100p ~n", - [Conf, RawConf]), + %% io:format(user, ">>>>>>> config:save_to_config_map ~p ~100p ~n", + %% [Conf, RawConf]), ?MODULE:put(Conf), ?MODULE:put_raw(RawConf). diff --git a/apps/emqx_authn/mix.exs b/apps/emqx_authn/mix.exs new file mode 100644 index 000000000..5477277c0 --- /dev/null +++ b/apps/emqx_authn/mix.exs @@ -0,0 +1,38 @@ +defmodule EMQXAuthn.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_authn, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X Authentication" + ] + end + + def application do + [ + registered: [:emqx_authn_sup, :emqx_authn_registry], + mod: {:emqx_authn_app, []}, + extra_applications: [:logger] + ] + end + + defp deps do + [ + {:emqx, in_umbrella: true, runtime: false}, + {:emqx_resource, in_umbrella: true}, + # {:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"}, + # {:esasl, github: "emqx/esasl", tag: "0.1.0"}, + # {:epgsql, github: "epgsql/epgsql", tag: "4.4.0"}, + # {:mysql, github: "emqx/mysql-otp", tag: "1.7.1"}, + {:jose, "1.11.2"}, + ] + end +end diff --git a/apps/emqx_conf/mix.exs b/apps/emqx_conf/mix.exs new file mode 100644 index 000000000..ca38717d5 --- /dev/null +++ b/apps/emqx_conf/mix.exs @@ -0,0 +1,32 @@ +defmodule EMQXConf.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_conf, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X Configuration Management" + ] + end + + def application do + [ + mod: {:emqx_conf_app, []}, + # extra_applications: [:logger, :os_mon, :syntax_tools] + ] + end + + defp deps do + [ + {:emqx, in_umbrella: true, runtime: false}, + # {:hocon, github: "emqx/hocon"} + ] + end +end diff --git a/apps/emqx_conf/src/emqx_conf_app.erl b/apps/emqx_conf/src/emqx_conf_app.erl index 65cd88503..4128fb4f3 100644 --- a/apps/emqx_conf/src/emqx_conf_app.erl +++ b/apps/emqx_conf/src/emqx_conf_app.erl @@ -25,8 +25,11 @@ -include("emqx_conf.hrl"). start(_StartType, _StartArgs) -> - io:format(user, ">>>>>>>>>>>>>> emqx_conf_app starting <<<<<<<<<<<~n", []), + ?SLOG(warning, #{ msg => ">>>>>>>>>>>>>> emqx_conf_app starting <<<<<<<<<<<~n" + }), init_conf(), + ?SLOG(warning, #{ msg => ">>>>>>>>>>>>>> emqx_conf_app conf init done <<<<<<<<<<<~n" + }), emqx_conf_sup:start_link(). stop(_State) -> diff --git a/apps/emqx_connector/mix.exs b/apps/emqx_connector/mix.exs index 97cfa9490..ae6fb0b09 100644 --- a/apps/emqx_connector/mix.exs +++ b/apps/emqx_connector/mix.exs @@ -27,6 +27,7 @@ defmodule EMQXConnector.MixProject do {:emqx_resource, in_umbrella: true, runtime: false}, {:epgsql, github: "epgsql/epgsql", tag: "4.4.0"}, {:mysql, github: "emqx/mysql-otp", tag: "1.7.1"}, + {:emqtt, github: "emqx/emqtt", tag: "1.4.3"}, # {:ecpool, github: "emqx/ecpool", tag: "0.5.1"}, # {:emqtt, github: "emqx/emqtt", tag: "1.4.3"} ] diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 1b0be02de..be01e472f 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -221,8 +221,8 @@ binenv(Key) -> add_default_user(Username, Password) when ?EMPTY_KEY(Username) orelse ?EMPTY_KEY(Password) -> %% FIXME!!! io:format(user, "~n>>>>>>>>>>> add_default_user empty ~n", []), - %% {ok, empty}, - ok; + {ok, empty}; + %% ok; add_default_user(Username, Password) -> case lookup_user(Username) of diff --git a/apps/emqx_exhook/mix.exs b/apps/emqx_exhook/mix.exs index 52d00a23b..4a90501b0 100644 --- a/apps/emqx_exhook/mix.exs +++ b/apps/emqx_exhook/mix.exs @@ -29,7 +29,7 @@ defmodule EMQXExhook.MixProject do defp deps do [ {:emqx, in_umbrella: true, runtime: false}, - # {:grpc, github: "emqx/grpc-erl", tag: "0.6.2"} + {:grpc, github: "emqx/grpc-erl", tag: "0.6.2"}, ] end diff --git a/apps/emqx_gateway/mix.exs b/apps/emqx_gateway/mix.exs index 3cdebd4b0..32c3b856c 100644 --- a/apps/emqx_gateway/mix.exs +++ b/apps/emqx_gateway/mix.exs @@ -54,8 +54,8 @@ defmodule EMQXGateway.MixProject do [ # {:gpb, "4.19.1", runtime: false}, {:emqx, in_umbrella: true, runtime: false}, + {:grpc, github: "emqx/grpc-erl", tag: "0.6.2"}, # {:lwm2m_coap, github: "emqx/lwm2m-coap", tag: "v2.0.0"}, - # {:grpc, github: "emqx/grpc-erl", tag: "0.6.2"}, # {:esockd, github: "emqx/esockd", tag: "5.7.4"} ] end diff --git a/apps/emqx_machine/mix.exs b/apps/emqx_machine/mix.exs new file mode 100644 index 000000000..489d1c9df --- /dev/null +++ b/apps/emqx_machine/mix.exs @@ -0,0 +1,30 @@ +defmodule EMQXMachine.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_machine, + version: "0.1.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "The EMQ X Machine" + ] + end + + def application do + [ + registered: [], + mod: {:emqx_machine_app, []}, + extra_applications: [:logger] + ] + end + + defp deps do + [] + end +end diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index fae21eece..26b459803 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -25,6 +25,8 @@ %% @doc EMQ X boot entrypoint. start() -> + ?SLOG(warning, #{ msg => ">>>>>>>>> machine:start enter" + }), case os:type() of {win32, nt} -> ok; _nix -> diff --git a/apps/emqx_machine/src/emqx_machine_boot.erl b/apps/emqx_machine/src/emqx_machine_boot.erl index 49b3eb9e0..d1347693f 100644 --- a/apps/emqx_machine/src/emqx_machine_boot.erl +++ b/apps/emqx_machine/src/emqx_machine_boot.erl @@ -27,8 +27,8 @@ -endif. post_boot() -> - io:format(user, ">>>>>>>>>>>>>>>>>>>> roots ~p~n", - [emqx_conf_schema:roots()]), + %% io:format(user, ">>>>>>>>>>>>>>>>>>>> roots ~p~n", + %% [emqx_conf_schema:roots()]), ok = ensure_apps_started(), _ = emqx_plugins:load(), ok = print_vsn(), @@ -110,7 +110,9 @@ reboot_apps() -> sorted_reboot_apps() -> Apps = [{App, app_deps(App)} || App <- reboot_apps()], - sorted_reboot_apps(Apps). + Res = sorted_reboot_apps(Apps), + io:format(user, "~n>>>>>>>>>>>>>> sorted_reboot_apps~n ~100p~n", [Res]), + Res. app_deps(App) -> case application:get_key(App, applications) of @@ -121,7 +123,13 @@ app_deps(App) -> sorted_reboot_apps(Apps) -> G = digraph:new(), try - lists:foreach(fun({App, Deps}) -> add_app(G, App, Deps) end, Apps), + lists:foreach(fun({App, Deps}) -> + ?SLOG(warning, #{ msg => ">>>>>> machine_boot:add_app" + , app => App + , deps => Deps + }), + add_app(G, App, Deps) + end, Apps), case digraph_utils:topsort(G) of Sorted when is_list(Sorted) -> Sorted; diff --git a/apps/emqx_management/mix.exs b/apps/emqx_management/mix.exs index ee6bb533c..b9f8ec078 100644 --- a/apps/emqx_management/mix.exs +++ b/apps/emqx_management/mix.exs @@ -30,7 +30,7 @@ defmodule EMQXManagement.MixProject do # {:emqx_rule_engine, in_umbrella: true}, # {:ekka, github: "emqx/ekka", tag: "0.11.1", runtime: false}, # {:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"}, - # {:minirest, github: "emqx/minirest", tag: "1.2.4"} + {:minirest, github: "emqx/minirest", tag: "1.2.7"}, ] end end diff --git a/apps/emqx_modules/src/emqx_modules_app.erl b/apps/emqx_modules/src/emqx_modules_app.erl index b72c6b9f7..0d0a9a7fc 100644 --- a/apps/emqx_modules/src/emqx_modules_app.erl +++ b/apps/emqx_modules/src/emqx_modules_app.erl @@ -24,18 +24,18 @@ start(_Type, _Args) -> {ok, Sup} = emqx_modules_sup:start_link(), - io:format(user, "~n>>>>>>>>>>>> modules_app:start sup children ~p~n", - [supervisor:which_children(Sup)]), - io:format(user, "~n>>>>>>>>>>>> modules_app:start get_release ~p~n", - [emqx_app:get_release()]), - io:format(user, "~n>>>>>>>>>>>> modules_app:start official_version ~p~n", - [emqx_telemetry:official_version(emqx_app:get_release())]), - io:format(user, "~n>>>>>>>>>>>> modules_app:start config files ~p~n", - [application:get_env(emqx, config_files, [])]), - io:format(user, "~n>>>>>>>>>>>> modules_app:start retainer config ~p~n", - [emqx:get_config([emqx_retainer], undefined)]), - io:format(user, "~n>>>>>>>>>>>> modules_app:start authz_api_settings:api_spec ~p~n", - [emqx_authz_api_settings:api_spec()]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start sup children ~p~n", + %% [supervisor:which_children(Sup)]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start get_release ~p~n", + %% [emqx_app:get_release()]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start official_version ~p~n", + %% [emqx_telemetry:official_version(emqx_app:get_release())]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start config files ~p~n", + %% [application:get_env(emqx, config_files, [])]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start retainer config ~p~n", + %% [emqx:get_config([emqx_retainer], undefined)]), + %% io:format(user, "~n>>>>>>>>>>>> modules_app:start authz_api_settings:api_spec ~p~n", + %% [emqx_authz_api_settings:api_spec()]), maybe_enable_modules(), {ok, Sup}. diff --git a/apps/emqx_plugin_libs/mix.exs b/apps/emqx_plugin_libs/mix.exs new file mode 100644 index 000000000..7eff5b961 --- /dev/null +++ b/apps/emqx_plugin_libs/mix.exs @@ -0,0 +1,28 @@ +defmodule EMQXPluginLibs.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_plugin_libs, + version: "4.3.1", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X Plugin utility libs" + ] + end + + def application do + [ + extra_applications: [:logger] + ] + end + + defp deps do + [] + end +end diff --git a/apps/emqx_prometheus/mix.exs b/apps/emqx_prometheus/mix.exs index d4b13b3b8..caac0c13a 100644 --- a/apps/emqx_prometheus/mix.exs +++ b/apps/emqx_prometheus/mix.exs @@ -10,7 +10,7 @@ defmodule EMQXPrometheus.MixProject do deps_path: "../../deps", lockfile: "../../mix.lock", elixir: "~> 1.12", - # start_permanent: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, deps: deps(), description: "Prometheus for EMQ X" ] @@ -27,7 +27,7 @@ defmodule EMQXPrometheus.MixProject do defp deps do [ {:emqx, in_umbrella: true, runtime: false}, - # {:prometheus, github: "emqx/prometheus.erl", tag: "v3.1.1"} + {:prometheus, github: "emqx/prometheus.erl", tag: "v3.1.1"} ] end end diff --git a/apps/emqx_psk/mix.exs b/apps/emqx_psk/mix.exs new file mode 100644 index 000000000..ac6288731 --- /dev/null +++ b/apps/emqx_psk/mix.exs @@ -0,0 +1,32 @@ +defmodule EmqxPSK.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_psk, + version: "5.0.0", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X PSK" + ] + end + + def application do + [ + registered: [:emqx_psk_sup], + mod: {:emqx_psk_app, []}, + extra_applications: [:logger] + ] + end + + defp deps do + [ + {:emqx, in_umbrella: true, runtime: false} + ] + end +end diff --git a/apps/emqx_retainer/mix.exs b/apps/emqx_retainer/mix.exs index 2565db62e..730079ad4 100644 --- a/apps/emqx_retainer/mix.exs +++ b/apps/emqx_retainer/mix.exs @@ -16,17 +16,17 @@ defmodule EMQXRetainer.MixProject do ] end - def application do - [ - registered: [:emqx_retainer_sup], - mod: {:emqx_retainer_app, []}, - # extra_applications: [:logger] - ] - end + # def application do + # [ + # registered: [:emqx_retainer_sup], + # mod: {:emqx_retainer_app, []}, + # # extra_applications: [:logger] + # ] + # end defp deps do [ - # {:emqx, in_umbrella: true, runtime: false} + {:emqx, in_umbrella: true, runtime: false} ] end end diff --git a/apps/emqx_rule_engine/mix.exs b/apps/emqx_rule_engine/mix.exs new file mode 100644 index 000000000..5b24e2dd8 --- /dev/null +++ b/apps/emqx_rule_engine/mix.exs @@ -0,0 +1,34 @@ +defmodule EMQXRuleEngine.MixProject do + use Mix.Project + + def project do + [ + app: :emqx_rule_engine, + version: "4.3.2", + build_path: "../../_build", + config_path: "../../config/config.exs", + deps_path: "../../deps", + lockfile: "../../mix.lock", + elixir: "~> 1.12", + # start_permanent: Mix.env() == :prod, + deps: deps(), + description: "EMQ X Rule Engine" + ] + end + + def application do + [ + registered: [:emqx_rule_engine_sup, :emqx_rule_registry], + mod: {:emqx_rule_engine_app, []}, + extra_applications: [:logger, :syntax_tools] + ] + end + + defp deps do + [ + {:emqx, in_umbrella: true, runtime: false}, + # {:ekka, github: "emqx/ekka", tag: "0.11.1", runtime: false}, + # {:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"} + ] + end +end diff --git a/config/config.exs b/config/config.exs index becde7693..49a546d15 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1 +1,7 @@ import Config + +config :logger, + format: "$message\n", + level: :debug, + handle_otp_reports: true, + handle_sasl_reports: true diff --git a/mix.exs b/mix.exs index 05c035b3d..06b9eed1a 100644 --- a/mix.exs +++ b/mix.exs @@ -3,8 +3,8 @@ defmodule EMQXUmbrella.MixProject do def project do [ - # apps_path: "apps", - app: :emqx_mix, + apps_path: "apps", + # app: :emqx_mix, version: pkg_vsn(), # start_permanent: Mix.env() == :prod, start_permanent: false, @@ -56,29 +56,31 @@ defmodule EMQXUmbrella.MixProject do {:mria, github: "emqx/mria", tag: "0.1.4", override: true}, {:minirest, github: "emqx/minirest", tag: "1.2.7"}, {:rulesql, github: "emqx/rulesql", tag: "0.1.4"}, + {:emqtt, github: "emqx/emqtt", tag: "1.4.3"}, + {:esasl, github: "emqx/esasl", tag: "0.2.0"}, #### - {:emqx, path: "apps/emqx", in_umbrella: true}, - {:emqx_authz, path: "apps/emqx_authz", in_umbrella: true}, - {:emqx_conf, path: "apps/emqx_conf", in_umbrella: true}, - {:emqx_connector, path: "apps/emqx_connector", in_umbrella: true}, - {:emqx_resource, path: "apps/emqx_resource", in_umbrella: true, complile: :mix}, - {:emqx_authn, path: "apps/emqx_authn", in_umbrella: true}, - {:emqx_plugin_libs, path: "apps/emqx_plugin_libs", in_umbrella: true}, - {:emqx_bridge, path: "apps/emqx_bridge", in_umbrella: true}, - {:emqx_retainer, path: "apps/emqx_retainer", in_umbrella: true}, - {:emqx_statsd, path: "apps/emqx_statsd", in_umbrella: true}, - {:emqx_auto_subscribe, path: "apps/emqx_auto_subscribe", in_umbrella: true}, - {:emqx_machine, path: "apps/emqx_machine", in_umbrella: true}, - {:emqx_modules, path: "apps/emqx_modules", in_umbrella: true}, - {:emqx_dashboard, path: "apps/emqx_dashboard", in_umbrella: true}, - {:emqx_gateway, path: "apps/emqx_gateway", in_umbrella: true}, - {:emqx_prometheus, path: "apps/emqx_prometheus", in_umbrella: true}, - {:emqx_rule_engine, path: "apps/emqx_rule_engine", in_umbrella: true}, - {:emqx_exhook, path: "apps/emqx_exhook", in_umbrella: true}, - {:emqx_psk, path: "apps/emqx_psk", in_umbrella: true}, - {:emqx_limiter, path: "apps/emqx_limiter", in_umbrella: true}, - # undef minirest error without this one... - {:emqx_management, path: "apps/emqx_management", in_umbrella: true}, + # {:emqx, path: "apps/emqx", in_umbrella: true}, + # {:emqx_authz, path: "apps/emqx_authz", in_umbrella: true}, + # {:emqx_conf, path: "apps/emqx_conf", in_umbrella: true}, + # {:emqx_connector, path: "apps/emqx_connector", in_umbrella: true}, + # {:emqx_resource, path: "apps/emqx_resource", in_umbrella: true, complile: :mix}, + # {:emqx_authn, path: "apps/emqx_authn", in_umbrella: true}, + # {:emqx_plugin_libs, path: "apps/emqx_plugin_libs", in_umbrella: true}, + # {:emqx_bridge, path: "apps/emqx_bridge", in_umbrella: true}, + # {:emqx_retainer, path: "apps/emqx_retainer", in_umbrella: true}, + # {:emqx_statsd, path: "apps/emqx_statsd", in_umbrella: true}, + # {:emqx_auto_subscribe, path: "apps/emqx_auto_subscribe", in_umbrella: true}, + # {:emqx_machine, path: "apps/emqx_machine", in_umbrella: true}, + # {:emqx_modules, path: "apps/emqx_modules", in_umbrella: true}, + # {:emqx_dashboard, path: "apps/emqx_dashboard", in_umbrella: true}, + # {:emqx_gateway, path: "apps/emqx_gateway", in_umbrella: true}, + # {:emqx_prometheus, path: "apps/emqx_prometheus", in_umbrella: true}, + # {:emqx_rule_engine, path: "apps/emqx_rule_engine", in_umbrella: true}, + # {:emqx_exhook, path: "apps/emqx_exhook", in_umbrella: true}, + # {:emqx_psk, path: "apps/emqx_psk", in_umbrella: true}, + # {:emqx_limiter, path: "apps/emqx_limiter", in_umbrella: true}, + # # undef minirest error without this one... + # {:emqx_management, path: "apps/emqx_management", in_umbrella: true}, ] ++ ((enable_bcrypt() && [{:bcrypt, github: "emqx/erlang-bcrypt", tag: "0.6.0"}]) || []) end @@ -92,14 +94,27 @@ defmodule EMQXUmbrella.MixProject do # end emqx: [ applications: [ + logger: :permanent, + # lc: :load, + esasl: :load, + crypto: :permanent, + public_key: :permanent, + asn1: :permanent, + syntax_tools: :permanent, + ssl: :permanent, + os_mon: :permanent, + inets: :permanent, + compiler: :permanent, runtime_tools: :permanent, + # emqx_conf: :permanent, emqx: :load, - # emqx_conf: :load, # as per rebar.config.erl - emqx_conf: :permanent, + emqx_conf: :load, # as per rebar.config.erl emqx_machine: :permanent, + mria: :load, mnesia: :load, ekka: :load, emqx_plugin_libs: :load, + emqx_http_lib: :permanent, emqx_resource: :permanent, emqx_connector: :permanent, emqx_authn: :permanent, @@ -112,13 +127,17 @@ defmodule EMQXUmbrella.MixProject do emqx_modules: :permanent, emqx_management: :permanent, emqx_dashboard: :permanent, - emqx_retainer: :permanent, emqx_statsd: :permanent, + # emqx_retainer: :permanent, + emqx_retainer: :none, emqx_prometheus: :permanent, - emqx_psk: :permanent, - emqx_limiter: :permanent, - emqx_mix: :none, - ] + # emqx_psk: :permanent, + emqx_psk: :none, + # emqx_limiter: :permanent, + emqx_limiter: :none, + observer: :load, + # emqx_mix: :none, + ], ] ] end diff --git a/mix.lock b/mix.lock index 3bdd0360c..916c6f6ed 100644 --- a/mix.lock +++ b/mix.lock @@ -8,13 +8,14 @@ "ecpool": {:git, "https://github.com/emqx/ecpool.git", "0516d2cebd14654ef8c583c347e4a0b01363b86d", [tag: "0.5.1"]}, "eetcd": {:hex, :eetcd, "0.3.4", "27e8b4775230c53a9ef602f62a1603591302b40b2eb195d567edffb35b6cf1a2", [:rebar3], [{:gun, "1.3.3", [hex: :gun, repo: "hexpm", optional: false]}], "hexpm", "b763c0e1a9741d39a62f5a19186a342863eacbc769151c4e81db5790efecefca"}, "ehttpc": {:git, "https://github.com/emqx/ehttpc.git", "7b1a76b2353b385725e62f948cd399c7040467f8", [tag: "0.1.12"]}, - "ekka": {:git, "https://github.com/emqx/ekka", "005fd6bb94199dc2ecb4ba03284f253b408e02d9", [tag: "0.11.1"]}, + "ekka": {:git, "https://github.com/emqx/ekka.git", "005fd6bb94199dc2ecb4ba03284f253b408e02d9", [tag: "0.11.1"]}, "eldap2": {:git, "https://github.com/emqx/eldap2", "f595f67b094db3b9dc07941337706621e815431f", [tag: "v0.2.2"]}, - "emqtt": {:git, "https://github.com/emqx/emqtt", "25892ef48a979a9dfbd74d86133cb28cf11f3cf4", [tag: "1.4.3"]}, + "emqtt": {:git, "https://github.com/emqx/emqtt.git", "25892ef48a979a9dfbd74d86133cb28cf11f3cf4", [tag: "1.4.3"]}, "emqx_http_lib": {:git, "https://github.com/emqx/emqx_http_lib.git", "9a1aafcbad1bb35392ebabc0cf102c7bce660432", [tag: "0.4.0"]}, "epgsql": {:git, "https://github.com/epgsql/epgsql.git", "895c8f9d53f08d09ec6a0301c56d3d6f270929f2", [tag: "4.4.0"]}, "eredis": {:git, "https://github.com/emqx/eredis", "75f2b8eedbe631136326680225efbcd2684e93e7", [tag: "1.2.5"]}, "eredis_cluster": {:git, "https://github.com/emqx/eredis_cluster", "624749b4aef25668e9c7a545427fdc663a04faef", [tag: "0.6.7"]}, + "esasl": {:git, "https://github.com/emqx/esasl.git", "96d7ac9f6c156017dd35b30df2dd722ae469c7f0", [tag: "0.2.0"]}, "esockd": {:git, "https://github.com/emqx/esockd.git", "9b959fc11a1c398a589892f335235be6c5b4a454", [tag: "5.8.0"]}, "estatsd": {:git, "https://github.com/emqx/estatsd.git", "5184d846b7ecb83509bd4d32695c60428c0198cd", [tag: "0.1.0"]}, "gen_coap": {:git, "https://github.com/emqx/gen_coap.git", "9bf5e7f795badf68e2fb4eb226f576308f5b1bb4", [tag: "v0.3.2"]}, @@ -36,7 +37,7 @@ "mysql": {:git, "https://github.com/emqx/mysql-otp.git", "bdabac44cc8836a9e23897b7e1b77c7df7e04f70", [tag: "1.7.1"]}, "pbkdf2": {:git, "https://github.com/emqx/erlang-pbkdf2.git", "45d9981209ea07a83a58cf85aaf8236457da4342", [tag: "2.0.4"]}, "poolboy": {:git, "https://github.com/emqx/poolboy.git", "29be47db8c2be38b18c908e43a80ebb7b9b6116b", [tag: "1.5.2"]}, - "prometheus": {:git, "https://github.com/emqx/prometheus.erl", "a41488df09472448057d264ef520cf2f71d925f8", [tag: "v3.1.1"]}, + "prometheus": {:git, "https://github.com/emqx/prometheus.erl.git", "a41488df09472448057d264ef520cf2f71d925f8", [tag: "v3.1.1"]}, "quicer": {:git, "https://github.com/emqx/quic.git", "ef73617d0f10f0f30f3aa77eb4a2f6ae071a2e29", [tag: "0.0.9"]}, "ranch": {:hex, :ranch, "2.1.0", "2261f9ed9574dcfcc444106b9f6da155e6e540b2f82ba3d42b339b93673b72a3", [:make, :rebar3], [], "hexpm", "244ee3fa2a6175270d8e1fc59024fd9dbc76294a321057de8f803b1479e76916"}, "recon": {:git, "https://github.com/ferd/recon", "f7b6c08e6e9e2219db58bfb012c58c178822e01e", [tag: "2.5.1"]}, diff --git a/mix_release.sh b/mix_release.sh new file mode 100755 index 000000000..24a572301 --- /dev/null +++ b/mix_release.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +mix release --overwrite +cp -r apps/emqx/etc/certs _build/dev/rel/emqx/etc/certs +cp temp/sys.config _build/dev/rel/emqx/releases/5.0.0-beta.2-3fdc075b/ diff --git a/rel/overlays/bin/emqx b/rel/overlays/bin/emqx.old similarity index 100% rename from rel/overlays/bin/emqx rename to rel/overlays/bin/emqx.old diff --git a/rel/overlays/etc/emqx.conf b/rel/overlays/etc/emqx.conf new file mode 100644 index 000000000..4b88815e0 --- /dev/null +++ b/rel/overlays/etc/emqx.conf @@ -0,0 +1,3064 @@ +## NOTE: The configurations in this file will be overridden by +## `/data/emqx_overrides.conf` + +##================================================================== +## Node +##================================================================== +node { + ## Node name. + ## See: http://erlang.org/doc/reference_manual/distributed.html + ## + ## @doc node.name + ## ValueType: NodeName + ## Default: emqx@127.0.0.1 + name = "emqx@127.0.0.1" + + ## Cookie for distributed node communication. + ## + ## @doc node.cookie + ## ValueType: String + ## Default: emqxsecretcookie + cookie = emqxsecretcookie + + ## Data dir for the node + ## + ## @doc node.data_dir + ## ValueType: Folder + ## Default: "data/" + data_dir = "data/" + + ## Location of crash dump file. + ## + ## @doc node.crash_dump_file + ## ValueType: File + ## Default: "log/erl_crash.dump" + crash_dump_file = "log/erl_crash.dump" + + ## The number of seconds that the broker is allowed to spend writing + ## a crash dump + ## + ## @doc node.crash_dump_seconds + ## ValueType: seconds + ## Default: 30s + crash_dump_seconds = 30s + + ## The maximum size of a crash dump file in bytes. + ## + ## @doc node.crash_dump_bytes + ## ValueType: bytes + ## Default: 100MB + crash_dump_bytes = 100MB + + ## Global GC Interval. + ## + ## @doc node.global_gc_interval + ## ValueType: Duration + ## Default: 15m + global_gc_interval = 15m + + ## Sets the etc directory + etc_dir = "etc" + + ## Sets the net_kernel tick time in seconds. + ## Notice that all communicating nodes are to have the same + ## TickTime value specified. + ## + ## See: http://www.erlang.org/doc/man/kernel_app.html#net_ticktime + ## + ## @doc node.dist_net_ticktime + ## ValueType: Number + ## Default: 2m + dist_net_ticktime = 2m + + ## Sets the port range for the listener socket of a distributed + ## Erlang node. + ## Note that if there are firewalls between clustered nodes, this + ## port segment for nodes’ communication should be allowed. + ## + ## See: http://www.erlang.org/doc/man/kernel_app.html + ## + ## @doc node.dist_listen_min + ## ValueType: Integer + ## Range: [1024,65535] + ## Default: 6369 + dist_listen_min = 6369 + + ## Sets the port range for the listener socket of a distributed + ## Erlang node. + ## Note that if there are firewalls between clustered nodes, this + ## port segment for nodes’ communication should be allowed. + ## + ## See: http://www.erlang.org/doc/man/kernel_app.html + ## + ## @doc node.dist_listen_max + ## ValueType: Integer + ## Range: [1024,65535] + ## Default: 6369 + dist_listen_max = 6369 + + ## Sets the maximum depth of call stack back-traces in the exit + ## reason element of 'EXIT' tuples. + ## The flag also limits the stacktrace depth returned by + ## process_info item current_stacktrace. + ## + ## @doc node.backtrace_depth + ## ValueType: Integer + ## Range: [0,1024] + ## Default: 23 + backtrace_depth = 23 + + cluster_call { + retry_interval = 1s + max_history = 100 + cleanup_interval = 5m + } +} + +##================================================================== +## Cluster +##================================================================== +cluster { + ## Cluster name. + ## + ## @doc cluster.name + ## ValueType: String + ## Default: emqxcl + name = emqxcl + + ## Enable cluster autoheal from network partition. + ## + ## @doc cluster.autoheal + ## ValueType: Boolean + ## Default: true + autoheal = true + + ## Autoclean down node. A down node will be removed from the cluster + ## if this value > 0. + ## + ## @doc cluster.autoclean + ## ValueType: Duration + ## Default: 5m + autoclean = 5m + + ## Node discovery strategy to join the cluster. + ## + ## @doc cluster.discovery_strategy + ## ValueType: manual | static | mcast | dns | etcd | k8s + ## - manual: Manual join command + ## - static: Static node list + ## - mcast: IP Multicast + ## - dns: DNS A Record + ## - etcd: etcd + ## - k8s: Kubernetes + ## + ## Default: manual + discovery_strategy = manual + + ##---------------------------------------------------------------- + ## Cluster using static node list + ##---------------------------------------------------------------- + static { + ## Node list of the cluster + ## + ## @doc cluster.static.seeds + ## ValueType: Array + ## Default: [] + seeds = ["emqx1@127.0.0.1", "emqx2@127.0.0.1"] + } + + ##---------------------------------------------------------------- + ## Cluster using IP Multicast + ##---------------------------------------------------------------- + mcast { + ## IP Multicast Address. + ## + ## @doc cluster.mcast.addr + ## ValueType: IPAddress + ## Default: "239.192.0.1" + addr = "239.192.0.1" + + ## Multicast Ports. + ## + ## @doc cluster.mcast.ports + ## ValueType: Array + ## Default: [4369, 4370] + ports = [4369, 4370] + + ## Multicast Iface. + ## + ## @doc cluster.mcast.iface + ## ValueType: IPAddress + ## Default: "0.0.0.0" + iface = "0.0.0.0" + + ## Multicast Ttl. + ## + ## @doc cluster.mcast.ttl + ## ValueType: Integer + ## Range: [0,255] + ## Default: 255 + ttl = 255 + + ## Multicast loop. + ## + ## @doc cluster.mcast.loop + ## ValueType: Boolean + ## Default: true + loop = true + } + + ##---------------------------------------------------------------- + ## Cluster using DNS A records + ##---------------------------------------------------------------- + dns { + ## DNS name. + ## + ## @doc cluster.dns.name + ## ValueType: String + ## Default: localhost + name = localhost + + ## The App name is used to build 'node.name' with IP address. + ## + ## @doc cluster.dns.app + ## ValueType: String + ## Default: emqx + app = emqx + } + + ##---------------------------------------------------------------- + ## Cluster using etcd + ##---------------------------------------------------------------- + etcd { + ## Etcd server list, seperated by ','. + ## + ## @doc cluster.etcd.server + ## ValueType: URL + ## Required: true + server = "http://127.0.0.1:2379" + + ## The prefix helps build nodes path in etcd. Each node in the cluster + ## will create a path in etcd: v2/keys/// + ## + ## @doc cluster.etcd.prefix + ## ValueType: String + ## Default: emqxcl + prefix = emqxcl + + ## The TTL for node's path in etcd. + ## + ## @doc cluster.etcd.node_ttl + ## ValueType: Duration + ## Default: 1m + node_ttl = 1m + + ## Path to the file containing the user's private PEM-encoded key. + ## + ## @doc cluster.etcd.ssl.keyfile + ## ValueType: File + ## Default: "etc/certs/key.pem" + ssl.keyfile = "etc/certs/key.pem" + + ## Path to a file containing the user certificate. + ## + ## @doc cluster.etcd.ssl.certfile + ## ValueType: File + ## Default: "etc/certs/cert.pem" + ssl.certfile = "etc/certs/cert.pem" + + ## Path to the file containing PEM-encoded CA certificates. The CA certificates + ## are used during server authentication and when building the client certificate chain. + ## + ## @doc cluster.etcd.ssl.cacertfile + ## ValueType: File + ## Default: "etc/certs/cacert.pem" + ssl.cacertfile = "etc/certs/cacert.pem" + } + + ##---------------------------------------------------------------- + ## Cluster using Kubernetes + ##---------------------------------------------------------------- + k8s { + ## Kubernetes API server list, seperated by ','. + ## + ## @doc cluster.k8s.apiserver + ## ValueType: URL + ## Required: true + apiserver = "http://10.110.111.204:8080" + + ## The service name helps lookup EMQ nodes in the cluster. + ## + ## @doc cluster.k8s.service_name + ## ValueType: String + ## Default: emqx + service_name = emqx + + ## The address type is used to extract host from k8s service. + ## + ## @doc cluster.k8s.address_type + ## ValueType: ip | dns | hostname + ## Default: ip + address_type = ip + + ## The app name helps build 'node.name'. + ## + ## @doc cluster.k8s.app_name + ## ValueType: String + ## Default: emqx + app_name = emqx + + ## The suffix added to dns and hostname get from k8s service + ## + ## @doc cluster.k8s.suffix + ## ValueType: String + ## Default: "pod.local" + suffix = "pod.local" + + ## Kubernetes Namespace + ## + ## @doc cluster.k8s.namespace + ## ValueType: String + ## Default: default + namespace = default + } +} + +##================================================================== +## Internal database +##================================================================== +db { + ## Database backend + ## + ## @doc db.backend + ## ValueType: mnesia | rlog + ## Default: mnesia + backend = mnesia + + ## RLOG role + ## + ## @doc db.role + ## ValueType: core | replicant + ## Default: core + role = core + + ## Replicant core nodes + ## + ## @doc db.core_nodes + ## ValueType: comma-separated node list + ## Default: "" + core_nodes = "" +} + +##================================================================== +## Log +##================================================================== +log { + ##---------------------------------------------------------------- + ## The console log handler send log messages to emqx console + ##---------------------------------------------------------------- + console_handler { + ## Log to single line + ## @doc log.console_handler..enable + ## ValueType: Boolean + ## Default: false + enable = true + + ## The log level of this handler + ## All the log messages with levels lower than this level will + ## be dropped. + ## + ## @doc log.console_handler..level + ## ValueType: debug | info | notice | warning | error | critical | alert | emergency + ## Default: warning + level = debug + + ## Timezone offset to display in logs + ## + ## @doc log.console_handler..time_offset + ## ValueType: system | utc | String + ## - "system" use system zone + ## - "utc" for Universal Coordinated Time (UTC) + ## - "+hh:mm" or "-hh:mm" for a specified offset + ## Default: system + time_offset = system + + ## Limits the total number of characters printed for each log event. + ## + ## @doc log.console_handler..chars_limit + ## ValueType: unlimited | Integer + ## Range: [0, +Inf) + ## Default: unlimited + chars_limit = unlimited + + ## Maximum depth for Erlang term log formatting + ## and Erlang process message queue inspection. + ## + ## @doc log.console_handler..max_depth + ## ValueType: unlimited | Integer + ## Default: 100 + max_depth = 100 + + ## Log formatter + ## @doc log.console_handler..formatter + ## ValueType: text | json + ## Default: text + formatter = text + + ## Log to single line + ## @doc log.console_handler..single_line + ## ValueType: Boolean + ## Default: true + single_line = true + + ## The max allowed queue length before switching to sync mode. + ## + ## Log overload protection parameter. If the message queue grows + ## larger than this value the handler switches from anync to sync mode. + ## + ## @doc log.console_handler..sync_mode_qlen + ## ValueType: Integer + ## Range: [0, ${log.console_handler..drop_mode_qlen}] + ## Default: 100 + sync_mode_qlen = 100 + + ## The max allowed queue length before switching to drop mode. + ## + ## Log overload protection parameter. When the message queue grows + ## larger than this threshold, the handler switches to a mode in which + ## it drops all new events that senders want to log. + ## + ## @doc log.console_handler..drop_mode_qlen + ## ValueType: Integer + ## Range: [${log.console_handler..sync_mode_qlen}, ${log.console_handler..flush_qlen}] + ## Default: 3000 + drop_mode_qlen = 3000 + + ## The max allowed queue length before switching to flush mode. + ## + ## Log overload protection parameter. If the length of the message queue + ## grows larger than this threshold, a flush (delete) operation takes place. + ## To flush events, the handler discards the messages in the message queue + ## by receiving them in a loop without logging. + ## + ## @doc log.console_handler..flush_qlen + ## ValueType: Integer + ## Range: [${log.console_handler..drop_mode_qlen}, infinity) + ## Default: 8000 + flush_qlen = 8000 + + ## Kill the log handler when it gets overloaded. + ## + ## Log overload protection parameter. It is possible that a handler, + ## even if it can successfully manage peaks of high load without crashing, + ## can build up a large message queue, or use a large amount of memory. + ## We could kill the log handler in these cases and restart it after a + ## few seconds. + ## + ## @doc log.console_handler..overload_kill.enable + ## ValueType: Boolean + ## Default: true + overload_kill.enable = true + + ## The max allowed queue length before killing the log hanlder. + ## + ## Log overload protection parameter. This is the maximum allowed queue + ## length. If the message queue grows larger than this, the handler + ## process is terminated. + ## + ## @doc log.console_handler..overload_kill.qlen + ## ValueType: Integer + ## Range: [0, 1048576] + ## Default: 20000 + overload_kill.qlen = 20000 + + ## The max allowed memory size before killing the log hanlder. + ## + ## Log overload protection parameter. This is the maximum memory size + ## that the handler process is allowed to use. If the handler grows + ## larger than this, the process is terminated. + ## + ## @doc log.console_handler..overload_kill.mem_size + ## ValueType: Size + ## Default: 30MB + overload_kill.mem_size = 30MB + + ## Restart the log hanlder after some seconds. + ## + ## Log overload protection parameter. If the handler is terminated, + ## it restarts automatically after a delay specified in seconds. + ## + ## @doc log.console_handler..overload_kill.restart_after + ## ValueType: Duration + ## Default: 5s + overload_kill.restart_after = 5s + + ## Controlling Bursts of Log Requests. + ## + ## Log overload protection parameter. Large bursts of log events - many + ## events received by the handler under a short period of time - can + ## potentially cause problems. By specifying the maximum number of events + ## to be handled within a certain time frame, the handler can avoid + ## choking the log with massive amounts of printouts. + ## + ## Note that there would be no warning if any messages were + ## dropped because of burst control. + ## + ## @doc log.console_handler..burst_limit.enable + ## ValueType: Boolean + ## Default: false + burst_limit.enable = false + + ## This config controls the maximum number of events to handle within + ## a time frame. After the limit is reached, successive events are + ## dropped until the end of the time frame defined by `window_time`. + ## + ## @doc log.console_handler..burst_limit.max_count + ## ValueType: Integer + ## Default: 10000 + burst_limit.max_count = 10000 + + ## See the previous description of burst_limit_max_count. + ## + ## @doc log.console_handler..burst_limit.window_time + ## ValueType: duration + ## Default: 1s + burst_limit.window_time = 1s + } + + ##---------------------------------------------------------------- + ## The file log handlers send log messages to files + ##---------------------------------------------------------------- + ## file_handlers. + file_handlers.default { + ## The log level filter of this handler + ## All the log messages with levels lower than this level will + ## be dropped. + ## + ## @doc log.file_handlers..level + ## ValueType: debug | info | notice | warning | error | critical | alert | emergency + ## Default: warning + level = warning + + ## The log file for specified level. + ## + ## If `rotation` is disabled, this is the file of the log files. + ## + ## If `rotation` is enabled, this is the base name of the files. + ## Each file in a rotated log is named .N, where N is an integer. + ## + ## Note: Log files for a specific log level will only contain all the logs + ## that higher than or equal to that level + ## + ## @doc log.file_handlers..file + ## ValueType: File + ## Required: true + file = "log/emqx.log" + + ## Enables the log rotation. + ## With this enabled, new log files will be created when the current + ## log file is full, max to `rotation_count` files will be created. + ## + ## @doc log.file_handlers..rotation.enable + ## ValueType: Boolean + ## Default: true + rotation.enable = true + + ## Maximum rotation count of log files. + ## + ## @doc log.file_handlers..rotation.count + ## ValueType: Integer + ## Range: [1, 2048] + ## Default: 10 + rotation.count = 10 + + ## Maximum size of each log file. + ## + ## If the max_size reached and `rotation` is disabled, the handler + ## will stop sending log messages, if the `rotation` is enabled, + ## the file rotates. + ## + ## @doc log.file_handlers..max_size + ## ValueType: Size | infinity + ## Default: 10MB + max_size = 10MB + + ## Timezone offset to display in logs + ## + ## @doc log.file_handlers..time_offset + ## ValueType: system | utc | String + ## - "system" use system zone + ## - "utc" for Universal Coordinated Time (UTC) + ## - "+hh:mm" or "-hh:mm" for a specified offset + ## Default: system + time_offset = system + + ## Limits the total number of characters printed for each log event. + ## + ## @doc log.file_handlers..chars_limit + ## ValueType: unlimited | Integer + ## Range: [0, +Inf) + ## Default: unlimited + chars_limit = unlimited + + ## Maximum depth for Erlang term log formatting + ## and Erlang process message queue inspection. + ## + ## @doc log.file_handlers..max_depth + ## ValueType: unlimited | Integer + ## Default: 100 + max_depth = 100 + + ## Log formatter + ## @doc log.file_handlers..formatter + ## ValueType: text | json + ## Default: text + formatter = text + + ## Log to single line + ## @doc log.file_handlers..single_line + ## ValueType: Boolean + ## Default: true + single_line = true + + ## The max allowed queue length before switching to sync mode. + ## + ## Log overload protection parameter. If the message queue grows + ## larger than this value the handler switches from anync to sync mode. + ## + ## @doc log.file_handlers..sync_mode_qlen + ## ValueType: Integer + ## Range: [0, ${log.file_handlers..drop_mode_qlen}] + ## Default: 100 + sync_mode_qlen = 100 + + ## The max allowed queue length before switching to drop mode. + ## + ## Log overload protection parameter. When the message queue grows + ## larger than this threshold, the handler switches to a mode in which + ## it drops all new events that senders want to log. + ## + ## @doc log.file_handlers..drop_mode_qlen + ## ValueType: Integer + ## Range: [${log.file_handlers..sync_mode_qlen}, ${log.file_handlers..flush_qlen}] + ## Default: 3000 + drop_mode_qlen = 3000 + + ## The max allowed queue length before switching to flush mode. + ## + ## Log overload protection parameter. If the length of the message queue + ## grows larger than this threshold, a flush (delete) operation takes place. + ## To flush events, the handler discards the messages in the message queue + ## by receiving them in a loop without logging. + ## + ## @doc log.file_handlers..flush_qlen + ## ValueType: Integer + ## Range: [${log.file_handlers..drop_mode_qlen}, infinity) + ## Default: 8000 + flush_qlen = 8000 + + ## Kill the log handler when it gets overloaded. + ## + ## Log overload protection parameter. It is possible that a handler, + ## even if it can successfully manage peaks of high load without crashing, + ## can build up a large message queue, or use a large amount of memory. + ## We could kill the log handler in these cases and restart it after a + ## few seconds. + ## + ## @doc log.file_handlers..overload_kill.enable + ## ValueType: Boolean + ## Default: true + overload_kill.enable = true + + ## The max allowed queue length before killing the log hanlder. + ## + ## Log overload protection parameter. This is the maximum allowed queue + ## length. If the message queue grows larger than this, the handler + ## process is terminated. + ## + ## @doc log.file_handlers..overload_kill.qlen + ## ValueType: Integer + ## Range: [0, 1048576] + ## Default: 20000 + overload_kill.qlen = 20000 + + ## The max allowed memory size before killing the log hanlder. + ## + ## Log overload protection parameter. This is the maximum memory size + ## that the handler process is allowed to use. If the handler grows + ## larger than this, the process is terminated. + ## + ## @doc log.file_handlers..overload_kill.mem_size + ## ValueType: Size + ## Default: 30MB + overload_kill.mem_size = 30MB + + ## Restart the log hanlder after some seconds. + ## + ## Log overload protection parameter. If the handler is terminated, + ## it restarts automatically after a delay specified in seconds. + ## + ## @doc log.file_handlers..overload_kill.restart_after + ## ValueType: Duration + ## Default: 5s + overload_kill.restart_after = 5s + + ## Controlling Bursts of Log Requests. + ## + ## Log overload protection parameter. Large bursts of log events - many + ## events received by the handler under a short period of time - can + ## potentially cause problems. By specifying the maximum number of events + ## to be handled within a certain time frame, the handler can avoid + ## choking the log with massive amounts of printouts. + ## + ## Note that there would be no warning if any messages were + ## dropped because of burst control. + ## + ## @doc log.file_handlers..burst_limit.enable + ## ValueType: Boolean + ## Default: false + burst_limit.enable = false + + ## This config controls the maximum number of events to handle within + ## a time frame. After the limit is reached, successive events are + ## dropped until the end of the time frame defined by `window_time`. + ## + ## @doc log.file_handlers..burst_limit.max_count + ## ValueType: Integer + ## Default: 10000 + burst_limit.max_count = 10000 + + ## See the previous description of burst_limit_max_count. + ## + ## @doc log.file_handlers..burst_limit.window_time + ## ValueType: duration + ## Default: 1s + burst_limit.window_time = 1s + } +} + +##================================================================== +## RPC +##================================================================== +rpc { + ## RPC Mode. + ## + ## @doc rpc.mode + ## ValueType: sync | async + ## Default: async + mode = async + + ## Max batch size of async RPC requests. + ## + ## NOTE: RPC batch won't work when rpc.mode = sync + ## Zero value disables rpc batching. + ## + ## @doc rpc.async_batch_size + ## ValueType: Integer + ## Range: [0, 1048576] + ## Default: 0 + async_batch_size = 256 + + ## RPC port discovery + ## + ## The strategy for discovering the RPC listening port of + ## other nodes. + ## + ## @doc cluster.discovery_strategy + ## ValueType: manual | stateless + ## - manual: discover ports by `tcp_server_port`. + ## - stateless: discover ports in a stateless manner. + ## If node name is `emqx@127.0.0.1`, where the `` is + ## an integer, then the listening port will be `5370 + ` + ## + ## Default: `stateless`. + port_discovery = stateless + + ## TCP server port for RPC. + ## + ## Only takes effect when `rpc.port_discovery` = `manual`. + ## + ## @doc rpc.tcp_server_port + ## ValueType: Integer + ## Range: [1024-65535] + ## Defaults: 5369 + tcp_server_port = 5369 + + ## Number of outgoing RPC connections. + ## + ## Set this to 1 to keep the message order sent from the same + ## client. + ## + ## @doc rpc.tcp_client_num + ## ValueType: Integer + ## Range: [1, 256] + ## Defaults: 1 + tcp_client_num = 1 + + ## RCP Client connect timeout. + ## + ## @doc rpc.connect_timeout + ## ValueType: Duration + ## Default: 5s + connect_timeout = 5s + + ## TCP send timeout of RPC client and server. + ## + ## @doc rpc.send_timeout + ## ValueType: Duration + ## Default: 5s + send_timeout = 5s + + ## Authentication timeout + ## + ## @doc rpc.authentication_timeout + ## ValueType: Duration + ## Default: 5s + authentication_timeout = 5s + + ## Default receive timeout for call() functions + ## + ## @doc rpc.call_receive_timeout + ## ValueType: Duration + ## Default: 15s + call_receive_timeout = 15s + + ## Socket idle keepalive. + ## + ## @doc rpc.socket_keepalive_idle + ## ValueType: Duration + ## Default: 900s + socket_keepalive_idle = 900s + + ## TCP Keepalive probes interval. + ## + ## @doc rpc.socket_keepalive_interval + ## ValueType: Duration + ## Default: 75s + socket_keepalive_interval = 75s + + ## Probes lost to close the connection + ## + ## @doc rpc.socket_keepalive_count + ## ValueType: Integer + ## Default: 9 + socket_keepalive_count = 9 + + ## Size of TCP send buffer. + ## + ## @doc rpc.socket_sndbuf + ## ValueType: Size + ## Default: 1MB + socket_sndbuf = 1MB + + ## Size of TCP receive buffer. + ## + ## @doc rpc.socket_recbuf + ## ValueType: Size + ## Default: 1MB + socket_recbuf = 1MB + + ## Size of user-level software socket buffer. + ## + ## @doc rpc.socket_buffer + ## ValueType: Size + ## Default: 1MB + socket_buffer = 1MB +} + +##================================================================== +## Listeners +##================================================================== +## MQTT/TCP - TCP Listeners for MQTT Protocol +## syntax: listeners.tcp. +## example: listeners.tcp.my_tcp_listener +listeners.tcp.default { + ## The IP address and port that the listener will bind. + ## + ## @doc listeners.tcp..bind + ## ValueType: IPAddress | Port | IPAddrPort + ## Required: true + ## Examples: 1883, 127.0.0.1:1883, ::1:1883 + bind = "0.0.0.0:1883" + + ## The configuration zone this listener is using. + ## If not set, the global configs are used for this listener. + ## + ## See `zones.` for more details. + ## + ## @doc listeners.tcp..zone + ## ValueType: String + ## Required: false + #zone = default + + ## The size of the acceptor pool for this listener. + ## + ## @doc listeners.tcp..acceptors + ## ValueType: Number + ## Default: 16 + acceptors = 16 + + ## Maximum number of concurrent connections. + ## + ## @doc listeners.tcp..max_connections + ## ValueType: Number | infinity + ## Default: infinity + max_connections = 1024000 + + ## The access control rules for this listener. + ## + ## See: https://github.com/emqtt/esockd#allowdeny + ## + ## @doc listeners.tcp..access_rules + ## ValueType: Array + ## Default: [] + ## Examples: + ## access_rules: [ + ## "deny 192.168.0.0/24", + ## "all all" + ## ] + access_rules = [ + "allow all" + ] + + ## Enable the Proxy Protocol V1/2 if the EMQ X cluster is deployed + ## behind HAProxy or Nginx. + ## + ## See: https://www.haproxy.com/blog/haproxy/proxy-protocol/ + ## + ## @doc listeners.tcp..proxy_protocol + ## ValueType: Boolean + ## Default: false + proxy_protocol = false + + ## Sets the timeout for proxy protocol. EMQ X will close the TCP connection + ## if no proxy protocol packet received within the timeout. + ## + ## @doc listeners.tcp..proxy_protocol_timeout + ## ValueType: Duration + ## Default: 3s + proxy_protocol_timeout = 3s + + ## When publishing or subscribing, prefix all topics with a mountpoint string. + ## The prefixed string will be removed from the topic name when the message + ## is delivered to the subscriber. The mountpoint is a way that users can use + ## to implement isolation of message routing between different listeners. + ## + ## For example if a clientA subscribes to "t" with `listeners.tcp..mountpoint` + ## set to "some_tenant", then the client accually subscribes to the topic + ## "some_tenant/t". Similarly if another clientB (connected to the same listener + ## with the clientA) send a message to topic "t", the message is accually route + ## to all the clients subscribed "some_tenant/t", so clientA will receive the + ## message, with topic name "t". + ## + ## Set to "" to disable the feature. + ## + ## Variables in mountpoint string: + ## - ${clientid}: clientid + ## - ${username}: username + ## + ## @doc listeners.tcp..mountpoint + ## ValueType: String + ## Default: "" + mountpoint = "" + + ## TCP options + ## See ${example_common_tcp_options} for more information + tcp.backlog = 1024 + tcp.buffer = 4KB +} + +## MQTT/SSL - SSL Listeners for MQTT Protocol +## syntax: listeners.ssl. +## example: listeners.ssl.my_ssl_listener +listeners.ssl.default { + ## The IP address and port that the listener will bind. + ## + ## @doc listeners.ssl..bind + ## ValueType: IPAddress | Port | IPAddrPort + ## Required: true + ## Examples: 8883, 127.0.0.1:8883, ::1:8883 + bind = "0.0.0.0:8883" + + ## The configuration zone this listener is using. + ## If not set, the global configs are used for this listener. + ## + ## See `zones.` for more details. + ## + ## @doc listeners.ssl..zone + ## ValueType: String + ## Required: false + #zone = default + + ## The size of the acceptor pool for this listener. + ## + ## @doc listeners.ssl..acceptors + ## ValueType: Number + ## Default: 16 + acceptors = 16 + + ## Maximum number of concurrent connections. + ## + ## @doc listeners.ssl..max_connections + ## ValueType: Number | infinity + ## Default: infinity + max_connections = 512000 + + ## The access control rules for this listener. + ## + ## See: https://github.com/emqtt/esockd#allowdeny + ## + ## @doc listeners.ssl..access_rules + ## ValueType: Array + ## Default: [] + ## Examples: + ## access_rules: [ + ## "deny 192.168.0.0/24", + ## "all all" + ## ] + access_rules = [ + "allow all" + ] + + ## Enable the Proxy Protocol V1/2 if the EMQ X cluster is deployed + ## behind HAProxy or Nginx. + ## + ## See: https://www.haproxy.com/blog/haproxy/proxy-protocol/ + ## + ## @doc listeners.ssl..proxy_protocol + ## ValueType: Boolean + ## Default: true + proxy_protocol = false + + ## Sets the timeout for proxy protocol. EMQ X will close the TCP connection + ## if no proxy protocol packet received within the timeout. + ## + ## @doc listeners.ssl..proxy_protocol_timeout + ## ValueType: Duration + ## Default: 3s + proxy_protocol_timeout = 3s + + ## When publishing or subscribing, prefix all topics with a mountpoint string. + ## The prefixed string will be removed from the topic name when the message + ## is delivered to the subscriber. The mountpoint is a way that users can use + ## to implement isolation of message routing between different listeners. + ## + ## For example if a clientA subscribes to "t" with `listeners.ssl..mountpoint` + ## set to "some_tenant", then the client accually subscribes to the topic + ## "some_tenant/t". Similarly if another clientB (connected to the same listener + ## with the clientA) send a message to topic "t", the message is accually route + ## to all the clients subscribed "some_tenant/t", so clientA will receive the + ## message, with topic name "t". + ## + ## Set to "" to disable the feature. + ## + ## Variables in mountpoint string: + ## - ${clientid}: clientid + ## - ${username}: username + ## + ## @doc listeners.ssl..mountpoint + ## ValueType: String + ## Default: "" + mountpoint = "" + + ## SSL options + ssl.keyfile = "etc/certs/key.pem" + ssl.certfile = "etc/certs/cert.pem" + ssl.cacertfile = "etc/certs/cacert.pem" + + # ssl.versions = ["tlsv1.3", "tlsv1.2", "tlsv1.1", "tlsv1"] + # TLS 1.3: "TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_SHA256,TLS_AES_128_CCM_8_SHA256" + # TLS 1-1.2 "ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES256-SHA384,ECDHE-RSA-AES256-SHA384,ECDHE-ECDSA-DES-CBC3-SHA,ECDH-ECDSA-AES256-GCM-SHA384,ECDH-RSA-AES256-GCM-SHA384,ECDH-ECDSA-AES256-SHA384,ECDH-RSA-AES256-SHA384,DHE-DSS-AES256-GCM-SHA384,DHE-DSS-AES256-SHA256,AES256-GCM-SHA384,AES256-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-SHA256,ECDHE-RSA-AES128-SHA256,ECDH-ECDSA-AES128-GCM-SHA256,ECDH-RSA-AES128-GCM-SHA256,ECDH-ECDSA-AES128-SHA256,ECDH-RSA-AES128-SHA256,DHE-DSS-AES128-GCM-SHA256,DHE-DSS-AES128-SHA256,AES128-GCM-SHA256,AES128-SHA256,ECDHE-ECDSA-AES256-SHA,ECDHE-RSA-AES256-SHA,DHE-DSS-AES256-SHA,ECDH-ECDSA-AES256-SHA,ECDH-RSA-AES256-SHA,AES256-SHA,ECDHE-ECDSA-AES128-SHA,ECDHE-RSA-AES128-SHA,DHE-DSS-AES128-SHA,ECDH-ECDSA-AES128-SHA,ECDH-RSA-AES128-SHA,AES128-SHA" + # PSK: "PSK-AES128-CBC-SHA,PSK-AES256-CBC-SHA,PSK-3DES-EDE-CBC-SHA,PSK-RC4-SHA" + # NOTE: If PSK cipher-suites are intended, tlsv1.3 should not be enabled in 'versions' config + # ssl.ciphers = "" + + ## TCP options + ## See ${example_common_tcp_options} for more information + tcp.backlog = 1024 + tcp.buffer = 4KB +} + +## MQTT/QUIC - QUIC Listeners for MQTT Protocol +## syntax: listeners.quic. +## example: listeners.quic.my_quic_listener +listeners.quic.default { + ## The IP address and port that the listener will bind. + ## + ## @doc listeners.quic..bind + ## ValueType: IPAddress | Port | IPAddrPort + ## Required: true + ## Examples: 14567, 127.0.0.1:14567, ::1:14567 + bind = "0.0.0.0:14567" + + ## The configuration zone this listener is using. + ## If not set, the global configs are used for this listener. + ## + ## See `zones.` for more details. + ## NOTE: This is a cluster-wide configuration. + ## It requires all nodes to be stopped before changing it. + ## + ## @doc listeners.quic..zone + ## ValueType: String + ## Required: false + #zone = default + + ## The size of the acceptor pool for this listener. + ## + ## @doc listeners.quic..acceptors + ## ValueType: Number + ## Default: 16 + acceptors = 16 + + ## Maximum number of concurrent connections. + ## + ## @doc listeners.quic..max_connections + ## ValueType: Number | infinity + ## Default: infinity + max_connections = 1024000 + + ## Path to the file containing the user's private PEM-encoded key. + ## + ## @doc listeners.quic..keyfile + ## ValueType: String + ## Default: "etc/certs/key.pem" + keyfile = "etc/certs/key.pem" + + ## Path to a file containing the user certificate. + ## + ## @doc listeners.quic..certfile + ## ValueType: String + ## Default: "etc/certs/cert.pem" + certfile = "etc/certs/cert.pem" + + ## When publishing or subscribing, prefix all topics with a mountpoint string. + ## The prefixed string will be removed from the topic name when the message + ## is delivered to the subscriber. The mountpoint is a way that users can use + ## to implement isolation of message routing between different listeners. + ## + ## For example if a clientA subscribes to "t" with `listeners.quic..mountpoint` + ## set to "some_tenant", then the client accually subscribes to the topic + ## "some_tenant/t". Similarly if another clientB (connected to the same listener + ## with the clientA) send a message to topic "t", the message is accually route + ## to all the clients subscribed "some_tenant/t", so clientA will receive the + ## message, with topic name "t". + ## + ## Set to "" to disable the feature. + ## + ## Variables in mountpoint string: + ## - ${clientid}: clientid + ## - ${username}: username + ## + ## @doc listeners.quic..mountpoint + ## ValueType: String + ## Default: "" + mountpoint = "" +} + +## MQTT/WS - Websocket Listeners for MQTT Protocol +## syntax: listeners.ws. +## example: listeners.ws.my_ws_listener +listeners.ws.default { + ## The IP address and port that the listener will bind. + ## + ## @doc listeners.ws..bind + ## ValueType: IPAddress | Port | IPAddrPort + ## Required: true + ## Examples: 8083, 127.0.0.1:8083, ::1:8083 + bind = "0.0.0.0:8083" + + ## The configuration zone this listener is using. + ## If not set, the global configs are used for this listener. + ## + ## See `zones.` for more details. + ## + ## @doc listeners.ws..zone + ## ValueType: String + ## Required: false + #zone = default + + ## The size of the acceptor pool for this listener. + ## + ## @doc listeners.ws..acceptors + ## ValueType: Number + ## Default: 16 + acceptors = 16 + + ## Maximum number of concurrent connections. + ## + ## @doc listeners.ws..max_connections + ## ValueType: Number | infinity + ## Default: infinity + max_connections = 1024000 + + ## The access control rules for this listener. + ## + ## See: https://github.com/emqtt/esockd#allowdeny + ## + ## @doc listeners.ws..access_rules + ## ValueType: Array + ## Default: [] + ## Examples: + ## access_rules: [ + ## "deny 192.168.0.0/24", + ## "all all" + ## ] + access_rules = [ + "allow all" + ] + + ## Enable the Proxy Protocol V1/2 if the EMQ X cluster is deployed + ## behind HAProxy or Nginx. + ## + ## See: https://www.haproxy.com/blog/haproxy/proxy-protocol/ + ## + ## @doc listeners.ws..proxy_protocol + ## ValueType: Boolean + ## Default: true + proxy_protocol = false + + ## Sets the timeout for proxy protocol. EMQ X will close the TCP connection + ## if no proxy protocol packet received within the timeout. + ## + ## @doc listeners.ws..proxy_protocol_timeout + ## ValueType: Duration + ## Default: 3s + proxy_protocol_timeout = 3s + + ## When publishing or subscribing, prefix all topics with a mountpoint string. + ## The prefixed string will be removed from the topic name when the message + ## is delivered to the subscriber. The mountpoint is a way that users can use + ## to implement isolation of message routing between different listeners. + ## + ## For example if a clientA subscribes to "t" with `listeners.ws..mountpoint` + ## set to "some_tenant", then the client accually subscribes to the topic + ## "some_tenant/t". Similarly if another clientB (connected to the same listener + ## with the clientA) send a message to topic "t", the message is accually route + ## to all the clients subscribed "some_tenant/t", so clientA will receive the + ## message, with topic name "t". + ## + ## Set to "" to disable the feature. + ## + ## Variables in mountpoint string: + ## - ${clientid}: clientid + ## - ${username}: username + ## + ## @doc listeners.ws..mountpoint + ## ValueType: String + ## Default: "" + mountpoint = "" + + ## TCP options + ## See ${example_common_tcp_options} for more information + tcp.backlog = 1024 + tcp.buffer = 4KB + + ## Websocket options + ## See ${example_common_websocket_options} for more information + websocket.idle_timeout = 86400s +} + +## MQTT/WSS - WebSocket Secure Listeners for MQTT Protocol +## syntax: listeners.wss. +## example: listeners.wss.my_wss_listener +listeners.wss.default { + ## The IP address and port that the listener will bind. + ## + ## @doc listeners.wss..bind + ## ValueType: IPAddress | Port | IPAddrPort + ## Required: true + ## Examples: 8084, 127.0.0.1:8084, ::1:8084 + bind = "0.0.0.0:8084" + + ## The configuration zone this listener is using. + ## If not set, the global configs are used for this listener. + ## + ## See `zones.` for more details. + ## + ## @doc listeners.wss..zone + ## ValueType: String + ## Required: false + #zone = default + + ## The size of the acceptor pool for this listener. + ## + ## @doc listeners.wss..acceptors + ## ValueType: Number + ## Default: 16 + acceptors = 16 + + ## Maximum number of concurrent connections. + ## + ## @doc listeners.wss..max_connections + ## ValueType: Number | infinity + ## Default: infinity + max_connections = 512000 + + ## The access control rules for this listener. + ## + ## See: https://github.com/emqtt/esockd#allowdeny + ## + ## @doc listeners.wss..access_rules + ## ValueType: Array + ## Default: [] + ## Examples: + ## access_rules: [ + ## "deny 192.168.0.0/24", + ## "all all" + ## ] + access_rules = [ + "allow all" + ] + + ## Enable the Proxy Protocol V1/2 if the EMQ X cluster is deployed + ## behind HAProxy or Nginx. + ## + ## See: https://www.haproxy.com/blog/haproxy/proxy-protocol/ + ## + ## @doc listeners.wss..proxy_protocol + ## ValueType: Boolean + ## Default: true + proxy_protocol = false + + ## Sets the timeout for proxy protocol. EMQ X will close the TCP connection + ## if no proxy protocol packet received within the timeout. + ## + ## @doc listeners.wss..proxy_protocol_timeout + ## ValueType: Duration + ## Default: 3s + proxy_protocol_timeout = 3s + + ## When publishing or subscribing, prefix all topics with a mountpoint string. + ## The prefixed string will be removed from the topic name when the message + ## is delivered to the subscriber. The mountpoint is a way that users can use + ## to implement isolation of message routing between different listeners. + ## + ## For example if a clientA subscribes to "t" with `listeners.wss..mountpoint` + ## set to "some_tenant", then the client accually subscribes to the topic + ## "some_tenant/t". Similarly if another clientB (connected to the same listener + ## with the clientA) send a message to topic "t", the message is accually route + ## to all the clients subscribed "some_tenant/t", so clientA will receive the + ## message, with topic name "t". + ## + ## Set to "" to disable the feature. + ## + ## Variables in mountpoint string: + ## - ${clientid}: clientid + ## - ${username}: username + ## + ## @doc listeners.wss..mountpoint + ## ValueType: String + ## Default: "" + mountpoint = "" + + ## SSL options + ## See ${example_common_ssl_options} for more information + ssl.keyfile = "etc/certs/key.pem" + ssl.certfile = "etc/certs/cert.pem" + ssl.cacertfile = "etc/certs/cacert.pem" + + ## TCP options + ## See ${example_common_tcp_options} for more information + tcp.backlog = 1024 + tcp.buffer = 4KB + + ## Websocket options + ## See ${example_common_websocket_options} for more information + websocket.idle_timeout = 86400s + +} + +## Enable per connection statistics. +## +## @doc stats.enable +## ValueType: Boolean +## Default: true +stats.enable = true + +authorization { + ## Behaviour after not matching a rule. + ## + ## @doc authorization.no_match + ## ValueType: allow | deny + ## Default: allow + no_match: allow + + ## The action when authorization check reject current operation + ## + ## @doc authorization.deny_action + ## ValueType: ignore | disconnect + ## Default: ignore + deny_action: ignore + + ## Whether to enable Authorization cache. + ## + ## If enabled, Authorization roles for each client will be cached in the memory + ## + ## @doc authorization.cache.enable + ## ValueType: Boolean + ## Default: true + cache.enable: true + + ## The maximum count of Authorization entries can be cached for a client. + ## + ## @doc authorization.cache.max_size + ## ValueType: Integer + ## Range: [0, 1048576] + ## Default: 32 + cache.max_size: 32 + + ## The time after which an Authorization cache entry will be deleted + ## + ## @doc authorization.cache.ttl + ## ValueType: Duration + ## Default: 1m + cache.ttl: 1m +} + +mqtt { + ## How long time the MQTT connection will be disconnected if the + ## TCP connection is established but MQTT CONNECT has not been + ## received. + ## + ## @doc mqtt.idle_timeout + ## ValueType: Duration + ## Default: 15s + idle_timeout = 15s + + ## Maximum MQTT packet size allowed. + ## + ## @doc mqtt.max_packet_size + ## ValueType: Bytes + ## Default: 1MB + max_packet_size = 1MB + + ## Maximum length of MQTT clientId allowed. + ## + ## @doc mqtt.max_clientid_len + ## ValueType: Integer + ## Range: [23, 65535] + ## Default: 65535 + max_clientid_len = 65535 + + ## Maximum topic levels allowed. + ## + ## @doc mqtt.max_topic_levels + ## ValueType: Integer + ## Range: [1, 65535] + ## Default: 128 + ## Depth so big may lead to subscribing performance issues + max_topic_levels = 128 + + ## Maximum QoS allowed. + ## + ## @doc mqtt.max_qos_allowed + ## ValueType: 0 | 1 | 2 + ## Default: 2 + max_qos_allowed = 2 + + ## Maximum Topic Alias, 0 means no topic alias supported. + ## + ## @doc mqtt.max_topic_alias + ## ValueType: Integer + ## Range: [0, 65535] + ## Default: 65535 + max_topic_alias = 65535 + + ## Whether the Server supports MQTT retained messages. + ## + ## @doc mqtt.retain_available + ## ValueType: Boolean + ## Default: true + retain_available = true + + ## Whether the Server supports MQTT Wildcard Subscriptions + ## + ## @doc mqtt.wildcard_subscription + ## ValueType: Boolean + ## Default: true + wildcard_subscription = true + + ## Whether the Server supports MQTT Shared Subscriptions. + ## + ## @doc mqtt.shared_subscription + ## ValueType: Boolean + ## Default: true + shared_subscription = true + + ## Whether to ignore loop delivery of messages.(for mqtt v3.1.1) + ## + ## @doc mqtt.ignore_loop_deliver + ## ValueType: Boolean + ## Default: false + ignore_loop_deliver = false + + ## Whether to parse the MQTT frame in strict mode + ## + ## @doc mqtt.strict_mode + ## ValueType: Boolean + ## Default: false + strict_mode = false + + ## Specify the response information returned to the client + ## + ## This feature is disabled if is set to "" + ## + ## @doc mqtt.response_information + ## ValueType: String + ## Default: "" + response_information = "" + + ## Server Keep Alive of MQTT 5.0 + ## + ## @doc mqtt.server_keepalive + ## ValueType: Number | disabled + ## Default: disabled + server_keepalive = disabled + + ## The backoff for MQTT keepalive timeout. The broker will kick a connection out + ## until 'Keepalive * backoff * 2' timeout. + ## + ## @doc mqtt.keepalive_backoff + ## ValueType: Float + ## Range: (0.5, 1] + ## Default: 0.75 + keepalive_backoff = 0.75 + + ## Maximum number of subscriptions allowed. + ## + ## @doc mqtt.max_subscriptions + ## ValueType: Integer | infinity + ## Range: [1, infinity) + ## Default: infinity + max_subscriptions = infinity + + ## Force to upgrade QoS according to subscription. + ## + ## @doc mqtt.upgrade_qos + ## ValueType: Boolean + ## Default: false + upgrade_qos = false + + ## Maximum size of the Inflight Window storing QoS1/2 messages delivered but unacked. + ## + ## @doc mqtt.max_inflight + ## ValueType: Integer + ## Range: [1, 65535] + ## Default: 32 + max_inflight = 32 + + ## Retry interval for QoS1/2 message delivering. + ## + ## @doc mqtt.retry_interval + ## ValueType: Duration + ## Default: 30s + retry_interval = 30s + + ## Maximum QoS2 packets (Client -> Broker) awaiting PUBREL. + ## + ## @doc mqtt.max_awaiting_rel + ## ValueType: Integer | infinity + ## Range: [1, infinity) + ## Default: 100 + max_awaiting_rel = 100 + + ## The QoS2 messages (Client -> Broker) will be dropped if awaiting PUBREL timeout. + ## + ## @doc mqtt.await_rel_timeout + ## ValueType: Duration + ## Default: 300s + await_rel_timeout = 300s + + ## Default session expiry interval for MQTT V3.1.1 connections. + ## + ## @doc mqtt.session_expiry_interval + ## ValueType: Duration + ## Default: 2h + session_expiry_interval = 2h + + ## Maximum queue length. Enqueued messages when persistent client disconnected, + ## or inflight window is full. + ## + ## @doc mqtt.max_mqueue_len + ## ValueType: Integer | infinity + ## Range: [0, infinity) + ## Default: 1000 + max_mqueue_len = 1000 + + ## Topic priorities. + ## + ## There's no priority table by default, hence all messages + ## are treated equal. + ## + ## Priority number [1-255] + ## + ## NOTE: comma and equal signs are not allowed for priority topic names + ## NOTE: Messages for topics not in the priority table are treated as + ## either highest or lowest priority depending on the configured + ## value for mqtt.mqueue_default_priority + ## + ## @doc mqtt.mqueue_priorities + ## ValueType: Map | disabled + ## Examples: + ## To configure "topic/1" > "topic/2": + ## mqueue_priorities: {"topic/1": 10, "topic/2": 8} + ## Default: disabled + mqueue_priorities = disabled + + ## Default to highest priority for topics not matching priority table + ## + ## @doc mqtt.mqueue_default_priority + ## ValueType: highest | lowest + ## Default: lowest + mqueue_default_priority = lowest + + ## Whether to enqueue QoS0 messages. + ## + ## @doc mqtt.mqueue_store_qos0 + ## ValueType: Boolean + ## Default: true + mqueue_store_qos0 = true + + ## Whether use username replace client id + ## + ## @doc mqtt.use_username_as_clientid + ## ValueType: Boolean + ## Default: false + use_username_as_clientid = false + + ## Use the CN, DN or CRT field from the client certificate as a username. + ## Only works for SSL connection. + ## + ## @doc mqtt.peer_cert_as_username + ## ValueType: cn | dn | crt | disabled + ## Default: disabled + peer_cert_as_username = disabled + + ## Use the CN, DN or CRT field from the client certificate as a clientid. + ## Only works for SSL connection. + ## + ## @doc mqtt.peer_cert_as_clientid + ## ValueType: cn | dn | crt | disabled + ## Default: disabled + peer_cert_as_clientid = disabled +} + +flapping_detect { + ## Enable Flapping Detection. + ## + ## This config controls the allowed maximum number of CONNECT received + ## from the same clientid in a time frame defined by `window_time`. + ## After the limit is reached, successive CONNECT requests are forbidden + ## (banned) until the end of the time period defined by `ban_time`. + ## + ## @doc flapping_detect.enable + ## ValueType: Boolean + ## Default: true + enable = false + + ## The max disconnect allowed of a MQTT Client in `window_time` + ## + ## @doc flapping_detect.max_count + ## ValueType: Integer + ## Default: 15 + max_count = 15 + + ## The time window for flapping detect + ## + ## @doc flapping_detect.window_time + ## ValueType: Duration + ## Default: 1m + window_time = 1m + + ## How long the clientid will be banned + ## + ## @doc flapping_detect.ban_time + ## ValueType: Duration + ## Default: 5m + ban_time = 5m + +} + +force_shutdown { + ## Enable force_shutdown + ## + ## @doc force_shutdown.enable + ## ValueType: Boolean + ## Default: true + enable = true + + ## Max message queue length + ## @doc force_shutdown.max_message_queue_len + ## ValueType: Integer + ## Range: (0, infinity) + ## Default: 1000 + max_message_queue_len = 1000 + + ## Total heap size + ## + ## @doc force_shutdown.max_heap_size + ## ValueType: Size + ## Default: 32MB + max_heap_size = 32MB +} + +overload_protection { + ## React on system overload or not + ## @doc overload_protection.enable + ## ValueType: Boolean + ## Default: false + enable = false + + ## Backoff delay in ms + ## @doc overload_protection.backoff_delay + ## ValueType: Integer + ## Range: (0, infinity) + ## Default: 1 + backoff_delay = 1 + + ## Backoff GC enabled + ## @doc overload_protection.backoff_gc + ## ValueType: Boolean + ## Default: false + backoff_gc = false + + ## Backoff hibernation enabled + ## @doc overload_protection.backoff_hibernation + ## ValueType: Boolean + ## Default: true + backoff_hibernation = true + + ## Backoff hibernation enabled + ## @doc overload_protection.backoff_hibernation + ## ValueType: Boolean + ## Default: true + backoff_new_conn = true +} + +force_gc { + ## Force the MQTT connection process GC after this number of + ## messages or bytes passed through. + ## + ## @doc force_gc.enable + ## ValueType: Boolean + ## Default: true + enable = true + + ## GC the process after how many messages received + ## @doc force_gc.max_message_queue_len + ## ValueType: Integer + ## Range: (0, infinity) + ## Default: 16000 + count = 16000 + + ## GC the process after how much bytes passed through + ## + ## @doc force_gc.bytes + ## ValueType: Size + ## Default: 16MB + bytes = 16MB +} + +conn_congestion { + ## Whether to alarm the congested connections. + ## + ## Sometimes the mqtt connection (usually an MQTT subscriber) may + ## get "congested" because there're too many packets to sent. + ## The socket trys to buffer the packets until the buffer is + ## full. If more packets comes after that, the packets will be + ## "pending" in a queue and we consider the connection is + ## "congested". + ## + ## Enable this to send an alarm when there's any bytes pending in + ## the queue. You could set the `sndbuf` to a larger value if the + ## alarm is triggered too often. + ## + ## The name of the alarm is of format "conn_congestion//". + ## Where the is the client-id of the congested MQTT connection. + ## And the is the username or "unknown_user" of not provided by the client. + ## + ## @doc conn_congestion.enable_alarm + ## ValueType: Boolean + ## Default: true + enable_alarm = true + + ## Won't clear the congested alarm in how long time. + ## The alarm is cleared only when there're no pending bytes in + ## the queue, and also it has been `min_alarm_sustain_duration` + ## time since the last time we considered the connection is "congested". + ## + ## This is to avoid clearing and sending the alarm again too often. + ## + ## @doc conn_congestion.min_alarm_sustain_duration + ## ValueType: Duration + ## Default: 1m + min_alarm_sustain_duration = 1m +} + +rate_limit { + ## Maximum connections per second. + ## + ## @doc zones..max_conn_rate + ## ValueType: Number | infinity + ## Default: 1000 + ## Examples: + ## max_conn_rate: 1000 + max_conn_rate = 1000 + + ## Message limit for the a external MQTT connection. + ## + ## @doc rate_limit.conn_messages_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messages per 10 seconds. + ## conn_messages_in: "100,10s" + conn_messages_in = "100,10s" + + ## Limit the rate of receiving packets for a MQTT connection. + ## The rate is counted by bytes of packets per second. + ## + ## The connection won't accept more messages if the messages come + ## faster than the limit. + ## + ## @doc rate_limit.conn_bytes_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100KB incoming per 10 seconds. + ## conn_bytes_in: "100KB,10s" + ## + conn_bytes_in = "100KB,10s" +} + +quota { + ## Messages quota for the each of external MQTT connection. + ## This value consumed by the number of recipient on a message. + ## + ## @doc quota.conn_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messaegs per 1s: + ## quota.conn_messages_routing: "100,1s" + conn_messages_routing = "100,1s" + + ## Messages quota for the all of external MQTT connections. + ## This value consumed by the number of recipient on a message. + ## + ## @doc quota.overall_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 200000 messages per 1s: + ## quota.overall_messages_routing: "200000,1s" + ## + overall_messages_routing = "200000,1s" +} + +##================================================================== +## Zones +##================================================================== +## A zone contains a set of configurations for listeners. +## +## A zone can be used by a listener via `listener...zone`. +## +## The configs defined in zones will override the global configs with the same key. +## +## For example given the following config: +## +## ``` +## a { +## b: 1, c: 1 +## } +## +## zone.my_zone { +## a { +## b:2 +## } +## } +## ``` +## +## The global config "a" is overridden by the configs "a" inside the zone "my_zone". +## If there is a listener uses the zone "my_zone", the value of config "a" will be: +## `{b:2, c: 1}`. +## Note that although the default value of `a.c` is `0`, the global value is used. +## i.e. configs in the zone have no default values. To overridde `a.c` we must configure +## it explicitly in the zone. +## +## All the global configs that can be overridden in zones are: +## - `stats.*` +## - `mqtt.*` +## - `authorization.*` +## - `flapping_detect.*` +## - `force_shutdown.*` +## - `conn_congestion.*` +## - `rate_limit.*` +## - `quota.*` +## - `force_gc.*` +## +## syntax: zones. +## example: zones.my_zone +zones.default { + +} + +##================================================================== +## Broker +##================================================================== +broker { + ## System interval of publishing $SYS messages. + ## + ## @doc broker.sys_msg_interval + ## ValueType: Duration | disabled + ## Default: 1m + sys_msg_interval = 1m + + ## System heartbeat interval of publishing following heart beat message: + ## - "$SYS/brokers//uptime" + ## - "$SYS/brokers//datetime" + ## + ## @doc broker.sys_heartbeat_interval + ## ValueType: Duration + ## Default: 30s | disabled + sys_heartbeat_interval = 30s + + ## Session locking strategy in a cluster. + ## + ## @doc broker.session_locking_strategy + ## ValueType: local | one | quorum | all + ## - local: only lock the session locally on the current node + ## - one: select only one remove node to lock the session + ## - quorum: select some nodes to lock the session + ## - all: lock the session on all of the nodes in the cluster + ## Default: quorum + session_locking_strategy = quorum + + ## Dispatch strategy for shared subscription + ## + ## @doc broker.shared_subscription_strategy + ## ValueType: random | round_robin | sticky | hash + ## - random: dispatch the message to a random selected subscriber + ## - round_robin: select the subscribers in a round-robin manner + ## - sticky: always use the last selected subscriber to dispatch, + ## until the susbcriber disconnected. + ## - hash: select the subscribers by the hash of clientIds + ## Default: round_robin + shared_subscription_strategy = round_robin + + ## Enable/disable shared dispatch acknowledgement for QoS1 and QoS2 messages + ## This should allow messages to be dispatched to a different subscriber in + ## the group in case the picked (based on shared_subscription_strategy) one # is offline + ## + ## @doc broker.shared_dispatch_ack_enabled + ## ValueType: Boolean + ## Default: false + shared_dispatch_ack_enabled = false + + ## Enable batch clean for deleted routes. + ## + ## @doc broker.route_batch_clean + ## ValueType: Boolean + ## Default: true + route_batch_clean = true + + ## Performance toggle for subscribe/unsubscribe wildcard topic. + ## Change this toggle only when there are many wildcard topics. + ## + ## NOTE: when changing from/to 'global' lock, it requires all + ## nodes in the cluster to be stopped before the change. + ## + ## @doc broker.perf.route_lock_type + ## ValueType: key | tab | global + ## - key: mnesia translational updates with per-key locks. recommended for single node setup. + ## - tab: mnesia translational updates with table lock. recommended for multi-nodes setup. + ## - global: global lock protected updates. recommended for larger cluster. + ## Default: key + perf.route_lock_type = key + + ## Enable trie path compaction. + ## Enabling it significantly improves wildcard topic subscribe + ## rate, if wildcard topics have unique prefixes like: + ## 'sensor//+/', where ID is unique per subscriber. + ## + ## Topic match performance (when publishing) may degrade if messages + ## are mostly published to topics with large number of levels. + ## + ## NOTE: This is a cluster-wide configuration. + ## It requires all nodes to be stopped before changing it. + ## + ## @doc broker.perf.trie_compaction + ## ValueType: Boolean + ## Default: true + perf.trie_compaction = true +} + +##================================================================== +## System Monitor +##================================================================== +sysmon { + ## The time interval for the periodic process limit check + ## + ## @doc sysmon.vm.process_check_interval + ## ValueType: Duration + ## Default: 30s + vm.process_check_interval = 30s + + ## The threshold, as percentage of processes, for how many processes can simultaneously exist at the local node before the corresponding alarm is set. + ## + ## @doc sysmon.vm.process_high_watermark + ## ValueType: Percentage + ## Default: 80% + vm.process_high_watermark = 80% + + ## The threshold, as percentage of processes, for how many processes can simultaneously exist at the local node before the corresponding alarm is clear. + ## + ## @doc sysmon.vm.process_low_watermark + ## ValueType: Percentage + ## Default: 60% + vm.process_low_watermark = 60% + + ## Enable Long GC monitoring. + ## Notice: don't enable the monitor in production for: + ## https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421 + ## + ## @doc sysmon.vm.long_gc + ## ValueType: Duration | disabled + ## Default: disabled + vm.long_gc = disabled + + ## Enable Long Schedule(ms) monitoring. + ## + ## See: http://erlang.org/doc/man/erlang.html#system_monitor-2 + ## + ## @doc sysmon.vm.long_schedule + ## ValueType: Duration | disabled + ## Default: disabled + vm.long_schedule = 240ms + + ## Enable Large Heap monitoring. + ## + ## See: http://erlang.org/doc/man/erlang.html#system_monitor-2 + ## + ## @doc sysmon.vm.large_heap + ## ValueType: Size | disabled + ## Default: 32MB + vm.large_heap = 32MB + + ## Enable Busy Port monitoring. + ## + ## See: http://erlang.org/doc/man/erlang.html#system_monitor-2 + ## + ## @doc sysmon.vm.busy_port + ## ValueType: Boolean + ## Default: true + vm.busy_port = true + + ## Enable Busy Dist Port monitoring. + ## + ## See: http://erlang.org/doc/man/erlang.html#system_monitor-2 + ## + ## @doc sysmon.vm.busy_dist_port + ## ValueType: Boolean + ## Default: true + vm.busy_dist_port = true + + ## The time interval for the periodic cpu check + ## + ## @doc sysmon.os.cpu_check_interval + ## ValueType: Duration + ## Default: 60s + os.cpu_check_interval = 60s + + ## The threshold, as percentage of system cpu, for how much system cpu can be used before the corresponding alarm is set. + ## + ## @doc sysmon.os.cpu_high_watermark + ## ValueType: Percentage + ## Default: 80% + os.cpu_high_watermark = 80% + + ## The threshold, as percentage of system cpu, for how much system cpu can be used before the corresponding alarm is clear. + ## + ## @doc sysmon.os.cpu_low_watermark + ## ValueType: Percentage + ## Default: 60% + os.cpu_low_watermark = 60% + + ## The time interval for the periodic memory check + ## + ## @doc sysmon.os.mem_check_interval + ## ValueType: Duration | disabled + ## Default: 60s + os.mem_check_interval = 60s + + ## The threshold, as percentage of system memory, for how much system memory can be allocated before the corresponding alarm is set. + ## + ## @doc sysmon.os.sysmem_high_watermark + ## ValueType: Percentage + ## Default: 70% + os.sysmem_high_watermark = 70% + + ## The threshold, as percentage of system memory, for how much system memory can be allocated by one Erlang process before the corresponding alarm is set. + ## + ## @doc sysmon.os.procmem_high_watermark + ## ValueType: Percentage + ## Default: 5% + os.procmem_high_watermark = 5% +} + +##================================================================== +## Alarm +##================================================================== +alarm { + ## Specifies the actions to take when an alarm is activated + ## + ## @doc alarm.actions + ## ValueType: Array + ## Default: [log, publish] + actions = [log, publish] + + ## The maximum number of deactivated alarms + ## + ## @doc alarm.size_limit + ## ValueType: Integer + ## Default: 1000 + size_limit = 1000 + + ## Validity Period of deactivated alarms + ## + ## @doc alarm.validity_period + ## ValueType: Duration + ## Default: 24h + validity_period = 24h +} + +## Config references for listeners + +## Socket options for TCP connections +## See: http://erlang.org/doc/man/inet.html +example_common_tcp_options { + ## Specify the {active, N} option for this Socket. + ## + ## See: https://erlang.org/doc/man/inet.html#setopts-2 + ## + ## @doc listeners..tcp.active_n + ## ValueType: Number + ## Default: 100 + tcp.active_n = 100 + + ## TCP backlog defines the maximum length that the queue of + ## pending connections can grow to. + ## + ## @doc listeners..tcp.backlog + ## ValueType: Number + ## Range: [0, 1048576] + ## Default: 1024 + tcp.backlog = 1024 + + ## The TCP send timeout for the connections. + ## + ## @doc listeners..tcp.send_timeout + ## ValueType: Duration + ## Default: 15s + tcp.send_timeout = 15s + + ## Close the connection if send timeout. + ## + ## @doc listeners..tcp.send_timeout_close + ## ValueType: Boolean + ## Default: true + tcp.send_timeout_close = true + + ## The TCP receive buffer(os kernel) for the connections. + ## + ## @doc listeners..tcp.recbuf + ## ValueType: Size + ## Default: notset + #tcp.recbuf: 2KB + + ## The TCP send buffer(os kernel) for the connections. + ## + ## @doc listeners..tcp.sndbuf + ## ValueType: Size + ## Default: notset + #tcp.sndbuf: 4KB + + ## The size of the user-level software buffer used by the driver. + ## + ## @doc listeners..tcp.buffer + ## ValueType: Size + ## Default: notset + #tcp.buffer: 4KB + + ## The socket is set to a busy state when the amount of data queued internally + ## by the ERTS socket implementation reaches this limit. + ## + ## @doc listeners..tcp.high_watermark + ## ValueType: Size + ## Default: 1MB + tcp.high_watermark = 1MB + + ## The TCP_NODELAY flag for the connections. + ## + ## @doc listeners..tcp.nodelay + ## ValueType: Boolean + ## Default: false + tcp.nodelay = false + + ## The SO_REUSEADDR flag for the connections. + ## + ## @doc listeners..tcp.reuseaddr + ## ValueType: Boolean + ## Default: true + tcp.reuseaddr = true +} + +## Socket options for SSL connections +## See: http://erlang.org/doc/man/ssl.html +example_common_ssl_options { + + ## A performance optimization setting, it allows clients to reuse + ## pre-existing sessions, instead of initializing new ones. + ## Read more about it here. + ## + ## @doc listeners..ssl.reuse_sessions + ## ValueType: Boolean + ## Default: true + ssl.reuse_sessions = true + + ## SSL parameter renegotiation is a feature that allows a client and a server + ## to renegotiate the parameters of the SSL connection on the fly. + ## RFC 5746 defines a more secure way of doing this. By enabling secure renegotiation, + ## you drop support for the insecure renegotiation, prone to MitM attacks. + ## + ## @doc listeners..ssl.secure_renegotiate + ## ValueType: Boolean + ## Default: true + ssl.secure_renegotiate = true + + ## In protocols that support client-initiated renegotiation, + ## the cost of resources of such an operation is higher for the server than the client. + ## This can act as a vector for denial of service attacks. + ## The SSL application already takes measures to counter-act such attempts, + ## but client-initiated renegotiation can be strictly disabled by setting this option to false. + ## The default value is true. Note that disabling renegotiation can result in + ## long-lived connections becoming unusable due to limits on + ## the number of messages the underlying cipher suite can encipher. + ssl.client_renegotiation = true + + ## An important security setting, it forces the cipher to be set based + ## on the server-specified order instead of the client-specified order, + ## hence enforcing the (usually more properly configured) security + ## ordering of the server administrator. + ## + ## @doc listeners..ssl.honor_cipher_order + ## ValueType: Boolean + ## Default: true + ssl.honor_cipher_order = true + + # ssl.versions = ["tlsv1.3", "tlsv1.2", "tlsv1.1", "tlsv1"] + # TLS 1.3: "TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_SHA256,TLS_AES_128_CCM_8_SHA256" + # TLS 1-1.2 "ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES256-SHA384,ECDHE-RSA-AES256-SHA384,ECDHE-ECDSA-DES-CBC3-SHA,ECDH-ECDSA-AES256-GCM-SHA384,ECDH-RSA-AES256-GCM-SHA384,ECDH-ECDSA-AES256-SHA384,ECDH-RSA-AES256-SHA384,DHE-DSS-AES256-GCM-SHA384,DHE-DSS-AES256-SHA256,AES256-GCM-SHA384,AES256-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-SHA256,ECDHE-RSA-AES128-SHA256,ECDH-ECDSA-AES128-GCM-SHA256,ECDH-RSA-AES128-GCM-SHA256,ECDH-ECDSA-AES128-SHA256,ECDH-RSA-AES128-SHA256,DHE-DSS-AES128-GCM-SHA256,DHE-DSS-AES128-SHA256,AES128-GCM-SHA256,AES128-SHA256,ECDHE-ECDSA-AES256-SHA,ECDHE-RSA-AES256-SHA,DHE-DSS-AES256-SHA,ECDH-ECDSA-AES256-SHA,ECDH-RSA-AES256-SHA,AES256-SHA,ECDHE-ECDSA-AES128-SHA,ECDHE-RSA-AES128-SHA,DHE-DSS-AES128-SHA,ECDH-ECDSA-AES128-SHA,ECDH-RSA-AES128-SHA,AES128-SHA" + # PSK: "PSK-AES128-CBC-SHA,PSK-AES256-CBC-SHA,PSK-3DES-EDE-CBC-SHA,PSK-RC4-SHA" + # NOTE: If PSK cipher-suites are intended, tlsv1.3 should not be enabled in 'versions' config + # NOTE: by default, ALL ciphers are enabled + # ssl.ciphers = "" + + ## TLS Handshake timeout. + ## + ## @doc listeners..ssl.handshake_timeout + ## ValueType: Duration + ## Default: 15s + ssl.handshake_timeout = 15s + + ## Maximum number of non-self-issued intermediate certificates that + ## can follow the peer certificate in a valid certification path. + ## + ## @doc listeners..ssl.depth + ## ValueType: Integer + ## Default: 10 + ssl.depth = 10 + + ## Path to the file containing the user's private PEM-encoded key. + ## + ## @doc listeners..ssl.keyfile + ## ValueType: File + ## Default: "etc/certs/key.pem" + ssl.keyfile = "etc/certs/key.pem" + + ## Path to a file containing the user certificate. + ## + ## @doc listeners..ssl.certfile + ## ValueType: File + ## Default: "etc/certs/cert.pem" + ssl.certfile = "etc/certs/cert.pem" + + ## Path to the file containing PEM-encoded CA certificates. The CA certificates + ## are used during server authentication and when building the client certificate chain. + ## + ## @doc listeners..ssl.cacertfile + ## ValueType: File + ## Default: "etc/certs/cacert.pem" + ssl.cacertfile = "etc/certs/cacert.pem" + + ## Maximum number of non-self-issued intermediate certificates that + ## can follow the peer certificate in a valid certification path. + ## + ## @doc listeners..ssl.depth + ## ValueType: Number + ## Default: 10 + ssl.depth = 10 + + ## String containing the user's password. Only used if the private keyfile + ## is password-protected. + ## + ## See: listener.ssl.$name.key_password + ## + ## @doc listeners..ssl.depth + ## ValueType: String + ## Default: "" + #ssl.key_password: "" + + ## The Ephemeral Diffie-Helman key exchange is a very effective way of + ## ensuring Forward Secrecy by exchanging a set of keys that never hit + ## the wire. Since the DH key is effectively signed by the private key, + ## it needs to be at least as strong as the private key. In addition, + ## the default DH groups that most of the OpenSSL installations have + ## are only a handful (since they are distributed with the OpenSSL + ## package that has been built for the operating system it’s running on) + ## and hence predictable (not to mention, 1024 bits only). + ## In order to escape this situation, first we need to generate a fresh, + ## strong DH group, store it in a file and then use the option above, + ## to force our SSL application to use the new DH group. Fortunately, + ## OpenSSL provides us with a tool to do that. Simply run: + ## openssl dhparam -out dh-params.pem 2048 + ## + ## @doc listeners..ssl.dhfile + ## ValueType: File + ## Default: "etc/certs/dh-params.pem" + #ssl.dhfile: "etc/certs/dh-params.pem" + + ## A server only does x509-path validation in mode verify_peer, + ## as it then sends a certificate request to the client (this + ## message is not sent if the verify option is verify_none). + ## You can then also want to specify option fail_if_no_peer_cert. + ## More information at: http://erlang.org/doc/man/ssl.html + ## + ## @doc listeners..ssl.verify + ## ValueType: verify_peer | verify_none + ## Default: verify_none + ssl.verify = verify_none + + ## Used together with {verify, verify_peer} by an SSL server. If set to true, + ## the server fails if the client does not have a certificate to send, that is, + ## sends an empty certificate. + ## + ## @doc listeners..ssl.fail_if_no_peer_cert + ## ValueType: Boolean + ## Default: true + ssl.fail_if_no_peer_cert = false + +} + +## Socket options for websocket connections +example_common_websocket_options { + ## The path of WebSocket MQTT endpoint + ## + ## @doc listeners..websocket.mqtt_path + ## ValueType: Path + ## Default: "/mqtt" + websocket.mqtt_path = "/mqtt" + + ## Whether a WebSocket message is allowed to contain multiple MQTT packets + ## + ## @doc listeners..websocket.mqtt_piggyback + ## ValueType: single | multiple + ## Default: multiple + websocket.mqtt_piggyback = multiple + + ## The compress flag for external WebSocket connections. + ## + ## If this Value is set true,the websocket message would be compressed + ## + ## @doc listeners..websocket.compress + ## ValueType: Boolean + ## Default: false + websocket.compress = false + + ## The idle timeout for external WebSocket connections. + ## + ## @doc listeners..websocket.idle_timeout + ## ValueType: Duration | infinity + ## Default: infinity + websocket.idle_timeout = infinity + + ## The max frame size for external WebSocket connections. + ## + ## @doc listeners..websocket.max_frame_size + ## ValueType: Size + ## Default: infinity + websocket.max_frame_size = infinity + + ## If set to true, the server fails if the client does not + ## have a Sec-WebSocket-Protocol to send. + ## Set to false for WeChat MiniApp. + ## + ## @doc listeners..websocket.fail_if_no_subprotocol + ## ValueType: Boolean + ## Default: true + websocket.fail_if_no_subprotocol = true + + ## Supported subprotocols + ## + ## @doc listeners..websocket.supported_subprotocols + ## ValueType: String + ## Default: mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5 + websocket.supported_subprotocols = "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5" + + ## Enable origin check in header for websocket connection + ## + ## @doc listeners..websocket.check_origin_enable + ## ValueType: Boolean + ## Default: false + websocket.check_origin_enable = false + + ## Allow origin to be absent in header in websocket connection + ## when check_origin_enable is true + ## + ## @doc listeners..websocket.allow_origin_absence + ## ValueType: Boolean + ## Default: true + websocket.allow_origin_absence = true + + ## Comma separated list of allowed origin in header for websocket connection + ## + ## @doc listeners..websocket.check_origins + ## ValueType: String + ## Examples: + ## local http dashboard url + ## check_origins: "http://localhost:18083, http://127.0.0.1:18083" + ## Default: "" + websocket.check_origins = "http://localhost:18083, http://127.0.0.1:18083" + + ## Specify which HTTP header for real source IP if the EMQ X cluster is + ## deployed behind NGINX or HAProxy. + ## + ## @doc listeners..websocket.proxy_address_header + ## ValueType: String + ## Default: X-Forwarded-For + websocket.proxy_address_header = X-Forwarded-For + + ## Specify which HTTP header for real source port if the EMQ X cluster is + ## deployed behind NGINX or HAProxy. + ## + ## @doc listeners..websocket.proxy_port_header + ## ValueType: String + ## Default: X-Forwarded-Port + websocket.proxy_port_header = X-Forwarded-Port + + websocket.deflate_opts { + ## The level of deflate options for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.level + ## ValueType: none | default | best_compression | best_speed + ## Default: default + level = default + + ## The mem_level of deflate options for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.mem_level + ## ValueType: Integer + ## Range: [1,9] + ## Default: 8 + mem_level = 8 + + ## The strategy of deflate options for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.strategy + ## ValueType: default | filtered | huffman_only | rle + ## Default: default + strategy = default + + ## The deflate option for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.server_context_takeover + ## ValueType: takeover | no_takeover + ## Default: takeover + server_context_takeover = takeover + + ## The deflate option for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.client_context_takeover + ## ValueType: takeover | no_takeover + ## Default: takeover + client_context_takeover = takeover + + ## The deflate options for external WebSocket connections. + ## + ## + ## @doc listeners..websocket.deflate_opts.server_max_window_bits + ## ValueType: Integer + ## Range: [8,15] + ## Default: 15 + server_max_window_bits = 15 + + ## The deflate options for external WebSocket connections. + ## + ## @doc listeners..websocket.deflate_opts.client_max_window_bits + ## ValueType: Integer + ## Range: [8,15] + ## Default: 15 + client_max_window_bits = 15 + } +} + +persistent_session_store { + ## Enable/disable internal persistent session store. + ## + ## @doc persistent_session_store.enabled + ## ValueType: Boolean + ## Default: false + enabled = false + + ## How long are undelivered messages retained in the store + ## + ## @doc persistent_session_store.max_retain_undelivered + ## ValueType: Duration + ## Default: 1h + max_retain_undelivered = 1h + + ## The time interval in which to try to run garbage collection of persistent session messages + ## + ## @doc persistent_session_store.message_gc_interval + ## ValueType: Duration + ## Default: 1h + message_gc_interval = 1h + + ## The time interval in which to try to run garbage collection of persistent session transient data + ## + ## @doc persistent_session_store.session_message_gc_interval + ## ValueType: Duration + ## Default: 1m + session_message_gc_interval = 1m +} + +authentication: [] + +authorization { + # sources = [ + # # { + # # type: http + # # url: "https://emqx.com" + # # headers: { + # # Accept: "application/json" + # # Content-Type: "application/json" + # # } + # # }, + # # { + # # type: mysql + # # server: "127.0.0.1:3306" + # # database: mqtt + # # pool_size: 1 + # # username: root + # # password: public + # # auto_reconnect: true + # # ssl: { + # # enable: true + # # cacertfile: "etc/certs/cacert.pem" + # # certfile: "etc/certs/client-cert.pem" + # # keyfile: "etc/certs/client-key.pem" + # # } + # # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or clientid = ${clientid}" + # # }, + # # { + # # type: postgresql + # # server: "127.0.0.1:5432" + # # database: mqtt + # # pool_size: 1 + # # username: root + # # password: public + # # auto_reconnect: true + # # ssl: {enable: false} + # # query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or username = '$all' or clientid = ${clientid}" + # # }, + # # { + # # type: redis + # # server: "127.0.0.1:6379" + # # database: 0 + # # pool_size: 1 + # # password: public + # # auto_reconnect: true + # # ssl: {enable: false} + # # cmd: "HGETALL mqtt_authz:${username}" + # # }, + # # { + # # type: mongodb + # # mongo_type: single + # # server: "127.0.0.1:27017" + # # pool_size: 1 + # # database: mqtt + # # ssl: {enable: false} + # # collection: mqtt_authz + # # selector: { "$or": [ { "username": "${username}" }, { "clientid": "${clientid}" } ] } + # # }, + # { + # type: built-in-database + # }, + # { + # type: file + # # file is loaded into cache + # path: "etc/acl.conf" + # } + # ] +} + + +auto_subscribe { + topics = [ + ## { + ## topic = "/c/${clientid}" + ## qos = 0 + ## rh = 0 + ## rap = 0 + ## nl = 0 + ## }, + ## { + ## topic = "/u/${username}" + ## }, + ## { + ## topic = "/h/${host}" + ## qos = 2 + ## }, + ## { + ## topic = "/p/${port}" + ## }, + ## { + ## topic = "/topic/abc" + ## }, + ## { + ## topic = "/client/${clientid}/username/${username}/host/${host}/port/${port}" + ## } + ] +} + +##-------------------------------------------------------------------- +## EMQ X Bridge +##-------------------------------------------------------------------- + +## MQTT bridges to/from another MQTT broker +#bridges.mqtt.my_ingress_mqtt_bridge { +# connector = "mqtt:my_mqtt_connector" +# direction = ingress +# ## topic mappings for this bridge +# from_remote_topic = "aws/#" +# subscribe_qos = 1 +# to_local_topic = "from_aws/${topic}" +# payload = "${payload}" +# qos = "${qos}" +# retain = "${retain}" +#} +# +#bridges.mqtt.my_egress_mqtt_bridge { +# connector = "mqtt:my_mqtt_connector" +# direction = egress +# ## topic mappings for this bridge +# from_local_topic = "emqx/#" +# to_remote_topic = "from_emqx/${topic}" +# payload = "${payload}" +# qos = 1 +# retain = false +#} +# +## HTTP bridges to an HTTP server +#bridges.http.my_http_bridge { +# ## NOTE: we cannot use placehodler variables in the `scheme://host:port` part of the url +# url = "http://localhost:9901/messages/${topic}" +# request_timeout = "30s" +# connect_timeout = "30s" +# max_retries = 3 +# retry_interval = "10s" +# pool_type = "random" +# pool_size = 4 +# enable_pipelining = true +# ssl { +# enable = false +# keyfile = "etc/certs/client-key.pem" +# certfile = "etc/certs/client-cert.pem" +# cacertfile = "etc/certs/cacert.pem" +# } +# +# from_local_topic = "emqx_http/#" +# ## the following config entries can use placehodler variables: +# ## url, method, body, headers +# method = post +# body = "${payload}" +# headers { +# "content-type": "application/json" +# } +#} + +#connectors.mqtt.my_mqtt_connector { +# mode = cluster_shareload +# server = "127.0.0.1:1883" +# proto_ver = "v4" +# username = "username1" +# password = "" +# clean_start = true +# keepalive = 300 +# retry_interval = "30s" +# max_inflight = 32 +# reconnect_interval = "30s" +# replayq { +# dir = "data/replayq/bridge_mqtt/" +# seg_bytes = "100MB" +# offload = false +# } +# ssl { +# enable = false +# keyfile = "etc/certs/client-key.pem" +# certfile = "etc/certs/client-cert.pem" +# cacertfile = "etc/certs/cacert.pem" +# } +#} + +##-------------------------------------------------------------------- +## EMQ X Dashboard +##-------------------------------------------------------------------- + +emqx_dashboard { + default_username = "admin" + default_password = "public" + ## notice: sample_interval should be divisible by 60. + sample_interval = 10s + ## api jwt timeout. default is 30 minute + token_expired_time = 60m + listeners = [ + { + protocol = http + num_acceptors = 4 + max_connections = 512 + port = 18083 + backlog = 512 + send_timeout = 5s + inet6 = false + ipv6_v6only = false + } + # , + # { + # protocol = https + # port = 18084 + # num_acceptors = 2 + # backlog = 512 + # send_timeout = 5s + # inet6 = false + # ipv6_v6only = false + # certfile = "etc/certs/cert.pem" + # keyfile = "etc/certs/key.pem" + # cacertfile = "etc/certs/cacert.pem" + # verify = verify_peer + # versions = ["tlsv1.3","tlsv1.2","tlsv1.1","tlsv1"] + # ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256","TLS_CHACHA20_POLY1305_SHA256","TLS_AES_128_CCM_SHA256","TLS_AES_128_CCM_8_SHA256","ECDHE-ECDSA-AES256-GCM-SHA384","ECDHE-RSA-AES256-GCM-SHA384","ECDHE-ECDSA-AES256-SHA384","ECDHE-RSA-AES256-SHA384","ECDHE-ECDSA-DES-CBC3-SHA","ECDH-ECDSA-AES256-GCM-SHA384","ECDH-RSA-AES256-GCM-SHA384","ECDH-ECDSA-AES256-SHA384","ECDH-RSA-AES256-SHA384","DHE-DSS-AES256-GCM-SHA384","DHE-DSS-AES256-SHA256","AES256-GCM-SHA384","AES256-SHA256","ECDHE-ECDSA-AES128-GCM-SHA256","ECDHE-RSA-AES128-GCM-SHA256","ECDHE-ECDSA-AES128-SHA256","ECDHE-RSA-AES128-SHA256","ECDH-ECDSA-AES128-GCM-SHA256","ECDH-RSA-AES128-GCM-SHA256","ECDH-ECDSA-AES128-SHA256","ECDH-RSA-AES128-SHA256","DHE-DSS-AES128-GCM-SHA256","DHE-DSS-AES128-SHA256","AES128-GCM-SHA256","AES128-SHA256","ECDHE-ECDSA-AES256-SHA","ECDHE-RSA-AES256-SHA","DHE-DSS-AES256-SHA","ECDH-ECDSA-AES256-SHA","ECDH-RSA-AES256-SHA","AES256-SHA","ECDHE-ECDSA-AES128-SHA","ECDHE-RSA-AES128-SHA","DHE-DSS-AES128-SHA","ECDH-ECDSA-AES128-SHA","ECDH-RSA-AES128-SHA","AES128-SHA"] + # } + ] + + ## CORS Support. don't set cors true if you don't know what it means. + # cors = false +} + +##==================================================================== +## EMQ X Hooks +##==================================================================== + +exhook { + ## The default value or action will be returned, while the request to + ## the gRPC server failed or no available grpc server running. + ## + ## Default: deny + ## Value: ignore | deny + request_failed_action = deny + + ## The timeout to request grpc server + ## + ## Default: 5s + ## Value: Duration + request_timeout = 5s + + ## Whether to automatically reconnect (initialize) the gRPC server + ## + ## When gRPC is not available, exhook tries to request the gRPC service at + ## that interval and reinitialize the list of mounted hooks. + ## + ## Default: false + ## Value: false | Duration + auto_reconnect = 60s + + servers = [ + # { name: "default" + # url: "http://127.0.0.1:9000" + # #ssl: { + # # cacertfile: "etc/certs/cacert.pem" + # # certfile: "etc/certs/cert.pem" + # # keyfile: "etc/certs/key.pem" + # #} + # } + ] +} + +##-------------------------------------------------------------------- +## EMQ X Gateway configurations +##-------------------------------------------------------------------- + +## No gateway by default. +## +## If you want to get how to config it, please see emqx_gateway.conf.example. + +##-------------------------------------------------------------------- +## Emq X Rate Limiter +##-------------------------------------------------------------------- +emqx_limiter { + bytes_in { + global = "100KB/10s" # token generation rate + zone.default = "100kB/10s" + zone.external = "20kB/10s" + bucket.tcp { + zone = default + aggregated = "100kB/10s,1Mb" + per_client = "100KB/10s,10Kb" + } + bucket.ssl { + zone = external + aggregated = "100kB/10s,1Mb" + per_client = "100KB/10s,10Kb" + } + } + + message_in { + global = "100/10s" + zone.default = "100/10s" + bucket.bucket1 { + zone = default + aggregated = "100/10s,1000" + per_client = "100/10s,100" + } + } + + connection { + global = "100/10s" + zone.default = "100/10s" + bucket.bucket1 { + zone = default + aggregated = "100/10s,1000" + per_client = "100/10s,100" + } + } + + message_routing { + global = "100/10s" + zone.default = "100/10s" + bucket.bucket1 { + zone = default + aggregated = "100/10s,100" + per_client = "100/10s,10" + } + } +} + + + +delayed { + enable = true + ## 0 is no limit + max_delayed_messages = 0 +} + +observer_cli { + enable = true +} + +telemetry { + enable = true +} + +event_message { + "$event/client_connected" = true + "$event/client_disconnected" = true + # "$event/client_subscribed": false + # "$event/client_unsubscribed": false + # "$event/message_delivered": false + # "$event/message_acked": false + # "$event/message_dropped": false +} + +topic_metrics: [ + #{topic: "test/1"} +] + +rewrite: [ + # { + # action = publish + # source_topic = "x/#" + # re = "^x/y/(.+)$" + # dest_topic = "z/y/$1" + # }, + # { + # action = subscribe + # source_topic = "x1/#" + # re = "^x1/y/(.+)$" + # dest_topic = "z1/y/$1" + # }, + # { + # action = all + # source_topic = "x2/#" + # re = "^x2/y/(.+)$" + # dest_topic = "z2/y/$1" + # } +] + + +##-------------------------------------------------------------------- +## emqx_prometheus for EMQ X +##-------------------------------------------------------------------- +prometheus { + push_gateway_server = "http://127.0.0.1:9091" + interval = "15s" + enable = true +} + +##-------------------------------------------------------------------- +## EMQ X PSK +##-------------------------------------------------------------------- + +psk_authentication { + ## Whether to enable the PSK feature. + enable = false + + ## If init file is specified, emqx will import PSKs from the file + ## into the built-in database at startup for use by the runtime. + ## + ## The file has to be structured line-by-line, each line must be in + ## the format: : + ## init_file = "data/init.psk" + + ## Specifies the separator for PSKIdentity and SharedSecret in the init file. + ## The default is colon (:) + ## separator = ":" + + ## The size of each chunk used to import to the built-in database from psk file + ## chunk_size = 50 +} + +##-------------------------------------------------------------------- +## EMQ X Retainer +##-------------------------------------------------------------------- + +## Where to store the retained messages. +## +## Notice that all nodes in the same cluster have to be configured to +emqx_retainer { + ## enable/disable emqx_retainer + enable = true + + ## Periodic interval for cleaning up expired messages. Never clear if the value is 0. + ## + ## Value: Duration + ## - h: hour + ## - m: minute + ## - s: second + ## + ## Examples: + ## - 2h: 2 hours + ## - 30m: 30 minutes + ## - 20s: 20 seconds + ## + ## Default: 0s + msg_clear_interval = 0s + + ## Message retention time. 0 means message will never be expired. + ## + ## Default: 0s + msg_expiry_interval = 0s + + ## When the retained flag of the PUBLISH message is set and Payload is empty, + ## whether to continue to publish the message. + ## see: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718038 + ## + ## Default: false + #stop_publish_clear_msg = false + + ## The message read and deliver flow rate control + ## When a client subscribe to a wildcard topic, may many retained messages will be loaded. + ## If you don't want these data loaded to the memory all at once, you can use this to control. + ## The processing flow: + ## load max_read_number retained message from storage -> + ## deliver -> + ## repeat this, until all retianed messages are delivered + ## + flow_control { + ## The max messages number per read from storage. 0 means no limit + ## + ## Default: 0 + max_read_number = 0 + + ## The max number of retained message can be delivered in emqx per quota_release_interval.0 means no limit + ## + ## Default: 0 + msg_deliver_quota = 0 + + ## deliver quota reset interval + ## + ## Default: 0s + quota_release_interval = 0s + } + + ## Maximum retained message size. + ## + ## Value: Bytes + max_payload_size = 1MB + + ## Storage connect parameters + ## + ## Value: built_in_database + ## + config { + + type = built_in_database + + ## storage_type: ram | disc | disc_only + storage_type = ram + + ## Maximum number of retained messages. 0 means no limit. + ## + ## Value: Number >= 0 + max_retained_messages = 0 + } +} + +##==================================================================== +## Rule Engine for EMQ X R5.0 +##==================================================================== +rule_engine { + ignore_sys_message = true + #rules.my_republish_rule { + # description = "A simple rule that republishs MQTT messages from topic 't/1' to 't/2'" + # enable = true + # sql = "SELECT * FROM \"t/1\"" + # outputs = [ + # { + # function = republish + # args = { + # topic = "t/2" + # qos = "${qos}" + # payload = "${payload}" + # } + # } + # ] + #} +} + +##-------------------------------------------------------------------- +## Statsd for EMQ X +##-------------------------------------------------------------------- + +statsd { + enable = true + server = "127.0.0.1:8125" + sample_time_interval = "10s" + flush_time_interval = "10s" +} +include "cluster-override.conf" +include "local-override.conf" diff --git a/rel/overlays/etc/ssl_dist.conf b/rel/overlays/etc/ssl_dist.conf new file mode 100644 index 000000000..e9a24db3a --- /dev/null +++ b/rel/overlays/etc/ssl_dist.conf @@ -0,0 +1,11 @@ +%% The options in the {server, Opts} tuple are used when calling ssl:ssl_accept/3, +%% and the options in the {client, Opts} tuple are used when calling ssl:connect/4. +%% +%% More information at: http://erlang.org/doc/apps/ssl/ssl_distribution.html +[{server, + [{certfile, "etc/certs/cert.pem"}, + {keyfile, "etc/certs/key.pem"}, + {secure_renegotiate, true}, + {depth, 0}]}, + {client, + [{secure_renegotiate, true}]}]. diff --git a/rel/overlays/etc/vm.args b/rel/overlays/etc/vm.args new file mode 100644 index 000000000..4ba084cc7 --- /dev/null +++ b/rel/overlays/etc/vm.args @@ -0,0 +1,122 @@ +###################################################################### +## Erlang VM Args for EMQ X Broker +###################################################################### + +## NOTE: +## +## Arguments configured in this file might be overridden by configs from `emqx.conf`. +## +## Some basic VM arguments are to be configured in `emqx.conf`, +## such as `node.name` for `-name` and `node.cooke` for `-setcookie`. + +## Sets the maximum number of simultaneously existing processes for this system. ++P 2097152 + +## Sets the maximum number of simultaneously existing ports for this system. ++Q 1048576 + +## Sets the maximum number of ETS tables ++e 262144 + +## Sets the maximum number of atoms the virtual machine can handle. +#+t 1048576 + +## Set the location of crash dumps +#-env ERL_CRASH_DUMP log/crash.dump + +## Set how many times generational garbages collections can be done without +## forcing a fullsweep collection. +-env ERL_FULLSWEEP_AFTER 1000 + +## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive +## (Disabled by default..use with caution!) +#-heart + +## Specify the erlang distributed protocol. +## Can be one of: inet_tcp, inet6_tcp, inet_tls +#-proto_dist inet_tcp + +## Specify SSL Options in the file if using SSL for Erlang Distribution. +## Used only when -proto_dist set to inet_tls +#-ssl_dist_optfile etc/ssl_dist.conf + +## Specifies the net_kernel tick time in seconds. +## This is the approximate time a connected node may be unresponsive until +## it is considered down and thereby disconnected. +-kernel net_ticktime 120 + +## Sets the distribution buffer busy limit (dist_buf_busy_limit). +#+zdbbl 8192 + +## Sets default scheduler hint for port parallelism. ++spp true + +## Sets the number of threads in async thread pool. Valid range is 0-1024. +## Increase the parameter if there are many simultaneous file I/O operations. ++A 4 + +## Sets the default heap size of processes to the size Size. +#+hms 233 + +## Sets the default binary virtual heap size of processes to the size Size. +#+hmbs 46422 + +## Sets the default maximum heap size of processes to the size Size. +## Defaults to 0, which means that no maximum heap size is used. +##For more information, see process_flag(max_heap_size, MaxHeapSize). +#+hmax 0 + +## Sets the default value for process flag message_queue_data. Defaults to on_heap. +#+hmqd on_heap | off_heap + +## Sets the number of IO pollsets to use when polling for I/O. +#+IOp 1 + +## Sets the number of IO poll threads to use when polling for I/O. +## Increase this for the busy systems with many concurrent connection. ++IOt 4 + +## Sets the number of scheduler threads to create and scheduler threads to set online. +#+S 8:8 + +## Sets the number of dirty CPU scheduler threads to create and dirty CPU scheduler threads to set online. +#+SDcpu 8:8 + +## Sets the number of dirty I/O scheduler threads to create. ++SDio 8 + +## Suggested stack size, in kilowords, for scheduler threads. +#+sss 32 + +## Suggested stack size, in kilowords, for dirty CPU scheduler threads. +#+sssdcpu 40 + +## Suggested stack size, in kilowords, for dirty IO scheduler threads. +#+sssdio 40 + +## Sets scheduler bind type. +## Can be one of: u, ns, ts, ps, s, nnts, nnps, tnnps, db +#+sbt db + +## Sets a user-defined CPU topology. +#+sct L0-3c0-3p0N0:L4-7c0-3p1N1 + +## Sets the mapping of warning messages for error_logger +#+W w + +## Sets time warp mode: no_time_warp | single_time_warp | multi_time_warp +#+C no_time_warp + +## Prevents loading information about source filenames and line numbers. +#+L + +## Specifies how long time (in milliseconds) to spend shutting down the system. +## See: http://erlang.org/doc/man/erl.html +-shutdown_time 30000 + +## patches dir +-pa data/patches + +## Mnesia thresholds +-mnesia dump_log_write_threshold 5000 +-mnesia dump_log_time_threshold 60000 diff --git a/rel/overlays/releases/emqx_vars b/rel/overlays/releases/emqx_vars new file mode 100644 index 000000000..5036b581c --- /dev/null +++ b/rel/overlays/releases/emqx_vars @@ -0,0 +1,24 @@ +###################################################################### +## NOTE: Do NOT replace this file during release upgrade. +## Update the vars to the end of this file instead. +###################################################################### +## constants from relx template +REL_VSN="5.0-beta.2-3fdc075b-eaa05d72" +ERTS_VSN="12.1.2" +ERL_OPTS="" +RUNNER_ROOT_DIR="$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)" +RUNNER_BIN_DIR="$RUNNER_ROOT_DIR/bin" +RUNNER_LOG_DIR="$RUNNER_ROOT_DIR/log" +RUNNER_LIB_DIR="$RUNNER_ROOT_DIR/lib" +RUNNER_ETC_DIR="$RUNNER_ROOT_DIR/etc" +RUNNER_DATA_DIR="$RUNNER_ROOT_DIR/data" +RUNNER_USER="" + +EMQX_LICENSE_CONF='' +export EMQX_DESCRIPTION='EMQ X Community Edition' + +## computed vars +REL_NAME="emqx" +ERTS_PATH="$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin" + +## updated vars here diff --git a/temp/sys.config b/temp/sys.config new file mode 100644 index 000000000..c22551d0c --- /dev/null +++ b/temp/sys.config @@ -0,0 +1,87 @@ +%% coding: utf-8 +%% RUNTIME_CONFIG=false +[{logger,[{format,<<36,109,101,115,115,97,103,101,10>>},{level,debug},{handle_otp_reports,true},{handle_sasl_reports,true}]}, +{ekka, + [{cluster_discovery,{manual,[]}}, + {proto_dist,inet_tcp}, + {cluster_autoheal,true}, + {cluster_autoclean,300000}, + {cluster_name,emqxcl}]}, + {mria, + [{tlog_push_mode,async}, + {rlog_rpc_module,gen_rpc}, + {core_nodes,[]}, + {node_role,core}, + {db_backend,mnesia}]}, + {gen_rpc, + [{socket_buffer,1048576}, + {socket_recbuf,1048576}, + {socket_sndbuf,1048576}, + {socket_keepalive_count,9}, + {socket_keepalive_interval,75}, + {socket_keepalive_idle,900}, + {call_receive_timeout,15000}, + {authentication_timeout,5000}, + {send_timeout,5000}, + {connect_timeout,5000}, + {tcp_server_port,5369}, + {port_discovery,stateless}, + {max_batch_size,256}]}, + {kernel, + [{error_logger,silent}, + {inet_dist_listen_max,6369}, + {inet_dist_listen_min,6369}, + {logger, + [{handler,default,undefined}, + {handler,console,logger_std_h, + #{config => + #{burst_limit_enable => false,burst_limit_max_count => 10000, + burst_limit_window_time => 1000,drop_mode_qlen => 3000, + flush_qlen => 8000,overload_kill_enable => true, + overload_kill_mem_size => 31457280,overload_kill_qlen => 20000, + overload_kill_restart_after => 5000,sync_mode_qlen => 100, + type => standard_io}, + filters => + [{drop_progress_reports,{fun logger_filters:progress/2,stop}}], + formatter => + {emqx_logger_textfmt, + #{chars_limit => unlimited,depth => 100,single_line => true, + template => + [time," [",level,"] ", + {clientid, + [{peername,[clientid,"@",peername," "],[clientid," "]}], + [{peername,[peername," "],[]}]}, + msg,"\n"], + time_offset => []}}, + level => debug}}, + {handler,default,logger_disk_log_h, + #{config => + #{burst_limit_enable => false,burst_limit_max_count => 10000, + burst_limit_window_time => 1000,drop_mode_qlen => 3000, + file => "log/emqx.log",flush_qlen => 8000,max_no_bytes => 10485760, + max_no_files => 10,overload_kill_enable => true, + overload_kill_mem_size => 31457280,overload_kill_qlen => 20000, + overload_kill_restart_after => 5000,sync_mode_qlen => 100, + type => wrap}, + filesync_repeat_interval => no_repeat, + filters => + [{drop_progress_reports,{fun logger_filters:progress/2,stop}}], + formatter => + {emqx_logger_textfmt, + #{chars_limit => unlimited,depth => 100,single_line => true, + template => + [time," [",level,"] ", + {clientid, + [{peername,[clientid,"@",peername," "],[clientid," "]}], + [{peername,[peername," "],[]}]}, + msg,"\n"], + time_offset => []}}, + level => warning}}]}, + {logger_level,debug}]}, + {emqx_machine,[{backtrace_depth,23},{global_gc_interval,900000}]}, + {emqx, + [{data_dir,"data/"}, + {local_override_conf_file,"data/configs/local-override.conf"}, + {cluster_override_conf_file,"data/configs/cluster-override.conf"}, + {config_files, + ["/home/thales/dev/emqx/emqx_mix/_build/dev/rel/emqx/etc/emqx.conf"]}]}].