diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config
index 3638b37ad..d3386b8cc 100644
--- a/apps/emqx/rebar.config
+++ b/apps/emqx/rebar.config
@@ -19,7 +19,7 @@
, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}}
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.12.1"}}}
, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.0"}}}
- , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
+ , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}
, {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}}
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
diff --git a/apps/emqx/src/emqx_config.erl b/apps/emqx/src/emqx_config.erl
index ebf0baf53..5dedfd285 100644
--- a/apps/emqx/src/emqx_config.erl
+++ b/apps/emqx/src/emqx_config.erl
@@ -295,7 +295,7 @@ include_dirs() ->
[filename:join(emqx:data_dir(), "configs")].
merge_envs(SchemaMod, RawConf) ->
- Opts = #{nullable => true, %% TODO: evil, remove, nullable should be declared in schema
+ Opts = #{required => false, %% TODO: evil, remove, required should be declared in schema
format => map,
apply_override_envs => true
},
@@ -308,7 +308,7 @@ check_config(SchemaMod, RawConf) ->
check_config(SchemaMod, RawConf, Opts0) ->
Opts1 = #{return_plain => true,
- nullable => true, %% TODO: evil, remove, nullable should be declared in schema
+ required => false, %% TODO: evil, remove, required should be declared in schema
format => map
},
Opts = maps:merge(Opts0, Opts1),
@@ -331,7 +331,7 @@ fill_defaults(RawConf) ->
-spec fill_defaults(module(), raw_config()) -> map().
fill_defaults(SchemaMod, RawConf) ->
hocon_tconf:check_plain(SchemaMod, RawConf,
- #{nullable => true, only_fill_defaults => true},
+ #{required => false, only_fill_defaults => true},
root_names_from_conf(RawConf)).
diff --git a/apps/emqx/src/emqx_hocon.erl b/apps/emqx/src/emqx_hocon.erl
index ebf5e0f44..9d9da03de 100644
--- a/apps/emqx/src/emqx_hocon.erl
+++ b/apps/emqx/src/emqx_hocon.erl
@@ -34,9 +34,9 @@ format_path([Name | Rest]) ->
-spec check(module(), hocon:config() | iodata()) ->
{ok, hocon:config()} | {error, any()}.
check(SchemaModule, Conf) when is_map(Conf) ->
- %% TODO: remove nullable
- %% fields should state nullable or not in their schema
- Opts = #{atom_key => true, nullable => true},
+ %% TODO: remove required
+ %% fields should state required or not in their schema
+ Opts = #{atom_key => true, required => false},
try
{ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts)}
catch
diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index 51a9273b3..1a13f82db 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -602,31 +602,31 @@ fields("listeners") ->
[ {"tcp",
sc(map(name, ref("mqtt_tcp_listener")),
#{ desc => "TCP listeners"
- , nullable => {true, recursively}
+ , required => {false, recursively}
})
}
, {"ssl",
sc(map(name, ref("mqtt_ssl_listener")),
#{ desc => "SSL listeners"
- , nullable => {true, recursively}
+ , required => {false, recursively}
})
}
, {"ws",
sc(map(name, ref("mqtt_ws_listener")),
#{ desc => "HTTP websocket listeners"
- , nullable => {true, recursively}
+ , required => {false, recursively}
})
}
, {"wss",
sc(map(name, ref("mqtt_wss_listener")),
#{ desc => "HTTPS websocket listeners"
- , nullable => {true, recursively}
+ , required => {false, recursively}
})
}
, {"quic",
sc(map(name, ref("mqtt_quic_listener")),
#{ desc => "QUIC listeners"
- , nullable => {true, recursively}
+ , required => {false, recursively}
})
}
];
@@ -1145,7 +1145,7 @@ mqtt_listener() ->
base_listener() ->
[ {"bind",
sc(hoconsc:union([ip_port(), integer()]),
- #{ nullable => false
+ #{ required => true
})}
, {"acceptors",
sc(integer(),
@@ -1204,7 +1204,7 @@ common_ssl_opts_schema(Defaults) ->
, {"cacertfile",
sc(string(),
#{ default => D("cacertfile")
- , nullable => true
+ , required => false
, desc =>
"""Trusted PEM format CA certificates bundle file.
The certificates in this file are used to verify the TLS peer's certificates.
@@ -1219,7 +1219,7 @@ already established connections.
, {"certfile",
sc(string(),
#{ default => D("certfile")
- , nullable => true
+ , required => false
, desc =>
"""PEM format certificates chain file.
The certificates in this file should be in reversed order of the certificate
@@ -1233,7 +1233,7 @@ the file if it is to be added.
, {"keyfile",
sc(string(),
#{ default => D("keyfile")
- , nullable => true
+ , required => false
, desc =>
"""PEM format private key file.
"""
@@ -1257,7 +1257,7 @@ the file if it is to be added.
, {"password",
sc(string(),
#{ sensitive => true
- , nullable => true
+ , required => false
, desc =>
"""String containing the user's password. Only used if the private
key file is password-protected."""
@@ -1305,7 +1305,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
[ {"dhfile",
sc(string(),
#{ default => D("dhfile")
- , nullable => true
+ , required => false
, desc =>
"""Path to a file containing PEM-encoded Diffie Hellman parameters
to be used by the server if a cipher suite using Diffie Hellman
@@ -1361,7 +1361,7 @@ client_ssl_opts_schema(Defaults) ->
common_ssl_opts_schema(Defaults) ++
[ { "server_name_indication",
sc(hoconsc:union([disable, string()]),
- #{ nullable => true
+ #{ required => false
, desc =>
"""Specify the host name to be used in TLS Server Name Indication extension.
For instance, when connecting to \"server.example.net\", the genuine server
diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl
index 3219640d4..af4c3da2d 100644
--- a/apps/emqx_authn/src/emqx_authn_api.erl
+++ b/apps/emqx_authn/src/emqx_authn_api.erl
@@ -116,7 +116,7 @@ fields(request_user_create) ->
fields(request_user_update) ->
[
{password, binary()},
- {is_superuser, mk(boolean(), #{default => false, nullable => true})}
+ {is_superuser, mk(boolean(), #{default => false, required => false})}
];
fields(request_move) ->
@@ -128,7 +128,7 @@ fields(request_import_users) ->
fields(response_user) ->
[
{user_id, binary()},
- {is_superuser, mk(boolean(), #{default => false, nullable => true})}
+ {is_superuser, mk(boolean(), #{default => false, required => false})}
];
fields(response_users) ->
@@ -379,8 +379,8 @@ schema("/authentication/:id/users") ->
description => <<"List users in authenticator in global authentication chain">>,
parameters => [
param_auth_id(),
- {page, mk(integer(), #{in => query, desc => <<"Page Index">>, nullable => true})},
- {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
+ {page, mk(integer(), #{in => query, desc => <<"Page Index">>, required => false})},
+ {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, required => false})}
],
responses => #{
200 => emqx_dashboard_swagger:schema_with_example(
@@ -415,8 +415,8 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
description => <<"List users in authenticator in listener authentication chain">>,
parameters => [
param_listener_id(), param_auth_id(),
- {page, mk(integer(), #{in => query, desc => <<"Page Index">>, nullable => true})},
- {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
+ {page, mk(integer(), #{in => query, desc => <<"Page Index">>, required => false})},
+ {limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, required => false})}
],
responses => #{
200 => emqx_dashboard_swagger:schema_with_example(
diff --git a/apps/emqx_authn/src/emqx_authn_password_hashing.erl b/apps/emqx_authn/src/emqx_authn_password_hashing.erl
index 731001498..7c9b0f247 100644
--- a/apps/emqx_authn/src/emqx_authn_password_hashing.erl
+++ b/apps/emqx_authn/src/emqx_authn_password_hashing.erl
@@ -81,8 +81,7 @@ salt_rounds(default) -> 10;
salt_rounds(_) -> undefined.
dk_length(type) -> integer();
-dk_length(nullable) -> true;
-dk_length(default) -> undefined;
+dk_length(required) -> false;
dk_length(_) -> undefined.
type_rw(type) ->
diff --git a/apps/emqx_authn/src/emqx_authn_schema.erl b/apps/emqx_authn/src/emqx_authn_schema.erl
index 46c410b25..7a30e0b72 100644
--- a/apps/emqx_authn/src/emqx_authn_schema.erl
+++ b/apps/emqx_authn/src/emqx_authn_schema.erl
@@ -54,8 +54,8 @@ root_type() ->
mechanism(Name) ->
hoconsc:mk(hoconsc:enum([Name]),
- #{nullable => false}).
+ #{required => true}).
backend(Name) ->
hoconsc:mk(hoconsc:enum([Name]),
- #{nullable => false}).
+ #{required => true}).
diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl
index f8af51886..002723b75 100644
--- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl
+++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl
@@ -77,7 +77,7 @@ validations() ->
url(type) -> binary();
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
-url(nullable) -> false;
+url(required) -> true;
url(_) -> undefined.
headers(type) -> map();
diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl
index aabb39e82..683429908 100644
--- a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl
+++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl
@@ -76,11 +76,11 @@ password_hash_field(type) -> binary();
password_hash_field(_) -> undefined.
salt_field(type) -> binary();
-salt_field(nullable) -> true;
+salt_field(required) -> false;
salt_field(_) -> undefined.
is_superuser_field(type) -> binary();
-is_superuser_field(nullable) -> true;
+is_superuser_field(required) -> false;
is_superuser_field(_) -> undefined.
%%------------------------------------------------------------------------------
diff --git a/apps/emqx_authz/src/emqx_authz_api_schema.erl b/apps/emqx_authz/src/emqx_authz_api_schema.erl
index 9f21437d4..f74792f42 100644
--- a/apps/emqx_authz/src/emqx_authz_api_schema.erl
+++ b/apps/emqx_authz/src/emqx_authz_api_schema.erl
@@ -85,7 +85,7 @@ fields(position) ->
url(type) -> binary();
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
-url(nullable) -> false;
+url(required) -> true;
url(_) -> undefined.
headers(type) -> map();
diff --git a/apps/emqx_authz/src/emqx_authz_schema.erl b/apps/emqx_authz/src/emqx_authz_schema.erl
index 0d8e80039..a44361fad 100644
--- a/apps/emqx_authz/src/emqx_authz_schema.erl
+++ b/apps/emqx_authz/src/emqx_authz_schema.erl
@@ -145,7 +145,7 @@ fields(redis_cluster) ->
http_common_fields() ->
[ {url, fun url/1}
, {request_timeout, mk_duration("Request timeout", #{default => "30s"})}
- , {body, #{type => map(), nullable => true}}
+ , {body, #{type => map(), required => false}}
] ++ maps:to_list(maps:without([ base_url
, pool_type],
maps:from_list(connector_fields(http)))).
@@ -181,7 +181,7 @@ headers_no_content_type(_) -> undefined.
url(type) -> binary();
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
-url(nullable) -> false;
+url(required) -> true;
url(_) -> undefined.
%%--------------------------------------------------------------------
diff --git a/apps/emqx_bridge/src/emqx_bridge_http_schema.erl b/apps/emqx_bridge/src/emqx_bridge_http_schema.erl
index 5bbd8016f..ccf9c0939 100644
--- a/apps/emqx_bridge/src/emqx_bridge_http_schema.erl
+++ b/apps/emqx_bridge/src/emqx_bridge_http_schema.erl
@@ -13,7 +13,7 @@ roots() -> [].
fields("bridge") ->
basic_config() ++
[ {url, mk(binary(),
- #{ nullable => false
+ #{ required => true
, desc =>"""
The URL of the HTTP Bridge.
Template with variables is allowed in the path, but variables cannot be used in the scheme, host,
diff --git a/apps/emqx_bridge/src/emqx_bridge_schema.erl b/apps/emqx_bridge/src/emqx_bridge_schema.erl
index 19403e00c..88f3634b7 100644
--- a/apps/emqx_bridge/src/emqx_bridge_schema.erl
+++ b/apps/emqx_bridge/src/emqx_bridge_schema.erl
@@ -52,7 +52,7 @@ common_bridge_fields() ->
})}
, {connector,
mk(binary(),
- #{ nullable => false
+ #{ required => true
, example => <<"mqtt:my_mqtt_connector">>
, desc =>"""
The connector ID to be used for this bridge. Connector IDs must be of format:
@@ -75,7 +75,7 @@ metrics_status_fields() ->
direction_field(Dir, Desc) ->
{direction, mk(Dir,
- #{ nullable => false
+ #{ required => true
, default => egress
, desc => "The direction of the bridge. Can be one of 'ingress' or 'egress'.
"
++ Desc
diff --git a/apps/emqx_conf/src/emqx_conf.erl b/apps/emqx_conf/src/emqx_conf.erl
index 64b2a6a8b..e83ccfffd 100644
--- a/apps/emqx_conf/src/emqx_conf.erl
+++ b/apps/emqx_conf/src/emqx_conf.erl
@@ -162,7 +162,7 @@ check_cluster_rpc_result(Result) ->
%% Only gen hot_conf schema, not all configuration fields.
gen_hot_conf_schema(File) ->
{ApiSpec0, Components0} = emqx_dashboard_swagger:spec(emqx_mgmt_api_configs,
- #{schema_to_spec_func => fun hocon_schema_to_spec/2}),
+ #{schema_converter => fun hocon_schema_to_spec/2}),
ApiSpec = lists:foldl(fun({Path, Spec, _, _}, Acc) ->
NewSpec = maps:fold(fun(Method, #{responses := Responses}, SubAcc) ->
case Responses of
@@ -187,8 +187,6 @@ gen_hot_conf_schema(File) ->
-define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])).
-define(TO_COMPONENTS_SCHEMA(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>,
?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_)])).
--define(TO_COMPONENTS_PARAM(_M_, _F_), iolist_to_binary([<<"#/components/parameters/">>,
- ?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_)])).
hocon_schema_to_spec(?R_REF(Module, StructName), _LocalModule) ->
{#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(Module, StructName)},
@@ -224,8 +222,8 @@ typename_to_spec("term()", _Mod) -> #{type => string};
typename_to_spec("boolean()", _Mod) -> #{type => boolean};
typename_to_spec("binary()", _Mod) -> #{type => string};
typename_to_spec("float()", _Mod) -> #{type => number};
-typename_to_spec("integer()", _Mod) -> #{type => integer};
-typename_to_spec("non_neg_integer()", _Mod) -> #{type => integer, minimum => 1};
+typename_to_spec("integer()", _Mod) -> #{type => number};
+typename_to_spec("non_neg_integer()", _Mod) -> #{type => number, minimum => 1};
typename_to_spec("number()", _Mod) -> #{type => number};
typename_to_spec("string()", _Mod) -> #{type => string};
typename_to_spec("atom()", _Mod) -> #{type => string};
@@ -234,7 +232,7 @@ typename_to_spec("duration()", _Mod) -> #{type => duration};
typename_to_spec("duration_s()", _Mod) -> #{type => duration};
typename_to_spec("duration_ms()", _Mod) -> #{type => duration};
typename_to_spec("percent()", _Mod) -> #{type => percent};
-typename_to_spec("file()", _Mod) -> #{type => file};
+typename_to_spec("file()", _Mod) -> #{type => string};
typename_to_spec("ip_port()", _Mod) -> #{type => ip_port};
typename_to_spec("url()", _Mod) -> #{type => url};
typename_to_spec("bytesize()", _Mod) -> #{type => byteSize};
@@ -263,7 +261,7 @@ default_type(Type) -> Type.
range(Name) ->
case string:split(Name, "..") of
[MinStr, MaxStr] -> %% 1..10 1..inf -inf..10
- Schema = #{type => integer},
+ Schema = #{type => number},
Schema1 = add_integer_prop(Schema, minimum, MinStr),
add_integer_prop(Schema1, maximum, MaxStr);
_ -> nomatch
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index ee18200cf..32aa7667a 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -262,7 +262,7 @@ fields("node") ->
})}
, {"data_dir",
sc(string(),
- #{ nullable => false,
+ #{ required => true,
mapping => "emqx.data_dir",
desc => "Path to the persistent data directory. It must be unique per broker instance."
})}
diff --git a/apps/emqx_connector/src/emqx_connector_http.erl b/apps/emqx_connector/src/emqx_connector_http.erl
index ee59f75eb..a63ed78bb 100644
--- a/apps/emqx_connector/src/emqx_connector_http.erl
+++ b/apps/emqx_connector/src/emqx_connector_http.erl
@@ -61,7 +61,7 @@ roots() ->
fields(config) ->
[ {base_url,
sc(url(),
- #{ nullable => false
+ #{ required => true
, validator => fun(#{query := _Query}) ->
{error, "There must be no query in the base_url"};
(_) -> ok
@@ -106,7 +106,7 @@ For example: http://localhost:9901/
, {request, hoconsc:mk(
ref("request"),
#{ default => undefined
- , nullable => true
+ , required => false
, desc => """
If the request is provided, the caller can send HTTP requests via
emqx_resource:query(ResourceId, {send_message, BridgeId, Message})
@@ -115,13 +115,13 @@ If the request is provided, the caller can send HTTP requests via
] ++ emqx_connector_schema_lib:ssl_fields();
fields("request") ->
- [ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{nullable => true})}
- , {path, hoconsc:mk(binary(), #{nullable => true})}
- , {body, hoconsc:mk(binary(), #{nullable => true})}
- , {headers, hoconsc:mk(map(), #{nullable => true})}
+ [ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{required => false})}
+ , {path, hoconsc:mk(binary(), #{required => false})}
+ , {body, hoconsc:mk(binary(), #{required => false})}
+ , {headers, hoconsc:mk(map(), #{required => false})}
, {request_timeout,
sc(emqx_schema:duration_ms(),
- #{ nullable => true
+ #{ required => false
, desc => "The timeout when sending request to the HTTP server"
})}
].
diff --git a/apps/emqx_connector/src/emqx_connector_mongo.erl b/apps/emqx_connector/src/emqx_connector_mongo.erl
index 05f30c2ee..135ba3382 100644
--- a/apps/emqx_connector/src/emqx_connector_mongo.erl
+++ b/apps/emqx_connector/src/emqx_connector_mongo.erl
@@ -91,11 +91,9 @@ mongo_fields() ->
, {pool_size, fun emqx_connector_schema_lib:pool_size/1}
, {username, fun emqx_connector_schema_lib:username/1}
, {password, fun emqx_connector_schema_lib:password/1}
- , {auth_source, #{type => binary(),
- nullable => true}}
+ , {auth_source, #{type => binary(), required => false}}
, {database, fun emqx_connector_schema_lib:database/1}
- , {topology, #{type => hoconsc:ref(?MODULE, topology),
- nullable => true}}
+ , {topology, #{type => hoconsc:ref(?MODULE, topology), required => false}}
] ++
emqx_connector_schema_lib:ssl_fields().
@@ -289,14 +287,14 @@ init_worker_options([], Acc) -> Acc.
%% Schema funcs
server(type) -> emqx_schema:ip_port();
-server(nullable) -> false;
+server(required) -> true;
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
server(converter) -> fun to_server_raw/1;
server(desc) -> ?SERVER_DESC("MongoDB", integer_to_list(?MONGO_DEFAULT_PORT));
server(_) -> undefined.
servers(type) -> binary();
-servers(nullable) -> false;
+servers(required) -> true;
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
servers(converter) -> fun to_servers_raw/1;
servers(desc) -> ?SERVERS_DESC ++ server(desc);
@@ -311,11 +309,11 @@ r_mode(default) -> master;
r_mode(_) -> undefined.
duration(type) -> emqx_schema:duration_ms();
-duration(nullable) -> true;
+duration(required) -> false;
duration(_) -> undefined.
replica_set_name(type) -> binary();
-replica_set_name(nullable) -> true;
+replica_set_name(required) -> false;
replica_set_name(_) -> undefined.
srv_record(type) -> boolean();
diff --git a/apps/emqx_connector/src/emqx_connector_mysql.erl b/apps/emqx_connector/src/emqx_connector_mysql.erl
index 699027b4b..8fbed74fb 100644
--- a/apps/emqx_connector/src/emqx_connector_mysql.erl
+++ b/apps/emqx_connector/src/emqx_connector_mysql.erl
@@ -50,7 +50,7 @@ fields(config) ->
emqx_connector_schema_lib:ssl_fields().
server(type) -> emqx_schema:ip_port();
-server(nullable) -> false;
+server(required) -> true;
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
server(converter) -> fun to_server/1;
server(desc) -> ?SERVER_DESC("MySQL", integer_to_list(?MYSQL_DEFAULT_PORT));
diff --git a/apps/emqx_connector/src/emqx_connector_pgsql.erl b/apps/emqx_connector/src/emqx_connector_pgsql.erl
index 9e2c72e0b..77509b276 100644
--- a/apps/emqx_connector/src/emqx_connector_pgsql.erl
+++ b/apps/emqx_connector/src/emqx_connector_pgsql.erl
@@ -56,11 +56,11 @@ fields(config) ->
emqx_connector_schema_lib:ssl_fields().
named_queries(type) -> map();
-named_queries(nullable) -> true;
+named_queries(required) -> false;
named_queries(_) -> undefined.
server(type) -> emqx_schema:ip_port();
-server(nullable) -> false;
+server(required) -> true;
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
server(converter) -> fun to_server/1;
server(desc) -> ?SERVER_DESC("PostgreSQL", integer_to_list(?PGSQL_DEFAULT_PORT));
diff --git a/apps/emqx_connector/src/emqx_connector_redis.erl b/apps/emqx_connector/src/emqx_connector_redis.erl
index f25ef4331..b3f09e0f6 100644
--- a/apps/emqx_connector/src/emqx_connector_redis.erl
+++ b/apps/emqx_connector/src/emqx_connector_redis.erl
@@ -76,14 +76,14 @@ fields(sentinel) ->
emqx_connector_schema_lib:ssl_fields().
server(type) -> emqx_schema:ip_port();
-server(nullable) -> false;
+server(required) -> true;
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
server(converter) -> fun to_server_raw/1;
server(desc) -> ?SERVER_DESC("Redis", integer_to_list(?REDIS_DEFAULT_PORT));
server(_) -> undefined.
servers(type) -> list();
-servers(nullable) -> false;
+servers(required) -> true;
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
servers(converter) -> fun to_servers_raw/1;
servers(desc) -> ?SERVERS_DESC ++ server(desc);
diff --git a/apps/emqx_connector/src/emqx_connector_schema_lib.erl b/apps/emqx_connector/src/emqx_connector_schema_lib.erl
index a43cab0d4..32ddcd518 100644
--- a/apps/emqx_connector/src/emqx_connector_schema_lib.erl
+++ b/apps/emqx_connector/src/emqx_connector_schema_lib.erl
@@ -66,7 +66,7 @@ relational_db_fields() ->
].
database(type) -> binary();
-database(nullable) -> false;
+database(required) -> true;
database(validator) -> [?NOT_EMPTY("the value of the field 'database' cannot be empty")];
database(_) -> undefined.
@@ -76,11 +76,11 @@ pool_size(validator) -> [?MIN(1)];
pool_size(_) -> undefined.
username(type) -> binary();
-username(nullable) -> true;
+username(required) -> false;
username(_) -> undefined.
password(type) -> binary();
-password(nullable) -> true;
+password(required) -> false;
password(_) -> undefined.
auto_reconnect(type) -> boolean();
diff --git a/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl b/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl
index d01f0110a..ddf3b8bc2 100644
--- a/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl
+++ b/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl
@@ -57,7 +57,7 @@ topic filters for 'remote_topic' of ingress connections.
})}
, {name,
sc(binary(),
- #{ nullable => true
+ #{ required => false
, desc => "Connector name, used as a human-readable description of the connector."
})}
, {server,
@@ -105,7 +105,7 @@ fields("ingress") ->
%% the message maybe subscribed by rules, in this case 'local_topic' is not necessary
[ {remote_topic,
sc(binary(),
- #{ nullable => false
+ #{ required => true
, desc => "Receive messages from which topic of the remote broker"
})}
, {remote_qos,
diff --git a/apps/emqx_connector/test/emqx_connector_test_helpers.erl b/apps/emqx_connector/test/emqx_connector_test_helpers.erl
index 7bb0086fe..6fd526884 100644
--- a/apps/emqx_connector/test/emqx_connector_test_helpers.erl
+++ b/apps/emqx_connector/test/emqx_connector_test_helpers.erl
@@ -29,8 +29,8 @@ check_fields({FieldName, FieldValue}) ->
if
is_map(FieldValue) ->
?assert(
- maps:is_key(type, FieldValue) and maps:is_key(default, FieldValue) or
- (maps:is_key(nullable, FieldValue) and maps:get(nullable, FieldValue, false) =:= true)
+ (maps:is_key(type, FieldValue) andalso maps:is_key(default, FieldValue)) orelse
+ ((maps:is_key(required, FieldValue) andalso maps:get(required, FieldValue)))
);
true ->
?assert(is_function(FieldValue))
diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
index eb1d79f45..f112fc852 100644
--- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
+++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
@@ -48,7 +48,7 @@ fields("http") ->
[ {"protocol", sc(
hoconsc:enum([http, https]),
#{ desc => "HTTP/HTTPS protocol."
- , nullable => false
+ , required => true
, default => http})}
, {"bind", fun bind/1}
, {"num_acceptors", sc(
@@ -74,18 +74,18 @@ fields("https") ->
bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]);
bind(default) -> 18083;
-bind(nullable) -> false;
+bind(required) -> true;
bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083).";
bind(_) -> undefined.
default_username(type) -> string();
default_username(default) -> "admin";
-default_username(nullable) -> false;
+default_username(required) -> true;
default_username(_) -> undefined.
default_password(type) -> string();
default_password(default) -> "public";
-default_password(nullable) -> false;
+default_password(required) -> true;
default_password(sensitive) -> true;
default_password(desc) -> """
The initial default password for dashboard 'admin' user.
@@ -94,7 +94,7 @@ default_password(_) -> undefined.
cors(type) -> boolean();
cors(default) -> false;
-cors(nullable) -> true;
+cors(required) -> false;
cors(desc) ->
"""Support Cross-Origin Resource Sharing (CORS).
Allows a server to indicate any origins (domain, scheme, or port) other than
diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl
index f0b67dab8..89b6795a9 100644
--- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl
+++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl
@@ -56,7 +56,10 @@
-type(filter_result() :: {ok, request()} | {400, 'BAD_REQUEST', binary()}).
-type(filter() :: fun((request(), request_meta()) -> filter_result())).
--type(spec_opts() :: #{check_schema => boolean() | filter(), translate_body => boolean()}).
+-type(spec_opts() :: #{check_schema => boolean() | filter(),
+ translate_body => boolean(),
+ schema_converter => fun((hocon_schema:schema(), Module::atom()) -> map())
+ }).
-type(route_path() :: string() | binary()).
-type(route_methods() :: map()).
@@ -217,7 +220,7 @@ check_request_body(#{body := Body}, Schema, Module, CheckFun, true) ->
_ -> Type0
end,
NewSchema = ?INIT_SCHEMA#{roots => [{root, Type}]},
- Option = #{nullable => true},
+ Option = #{required => false},
#{<<"root">> := NewBody} = CheckFun(NewSchema, #{<<"root">> => Body}, Option),
NewBody;
%% TODO not support nest object check yet, please use ref!
@@ -265,30 +268,22 @@ parameters(Params, Module) ->
In = hocon_schema:field_schema(Type, in),
In =:= undefined andalso
throw({error, <<"missing in:path/query field in parameters">>}),
- Nullable = hocon_schema:field_schema(Type, nullable),
+ Required = hocon_schema:field_schema(Type, required),
Default = hocon_schema:field_schema(Type, default),
HoconType = hocon_schema:field_schema(Type, type),
- Meta = init_meta(Nullable, Default),
+ Meta = init_meta(Default),
{ParamType, Refs} = hocon_schema_to_spec(HoconType, Module),
Spec0 = init_prop([required | ?DEFAULT_FIELDS],
#{schema => maps:merge(ParamType, Meta), name => Name, in => In}, Type),
- Spec1 = trans_required(Spec0, Nullable, In),
+ Spec1 = trans_required(Spec0, Required, In),
Spec2 = trans_desc(Spec1, Type),
{[Spec2 | Acc], Refs ++ RefsAcc}
end
end, {[], []}, Params),
{lists:reverse(SpecList), AllRefs}.
-init_meta(Nullable, Default) ->
- Init =
- case Nullable of
- true -> #{nullable => true};
- _ -> #{}
- end,
- case Default =:= undefined of
- true -> Init;
- false -> Init#{default => Default}
- end.
+init_meta(undefined) -> #{};
+init_meta(Default) -> #{default => Default}.
init_prop(Keys, Init, Type) ->
lists:foldl(fun(Key, Acc) ->
@@ -298,7 +293,7 @@ init_prop(Keys, Init, Type) ->
end
end, Init, Keys).
-trans_required(Spec, false, _) -> Spec#{required => true};
+trans_required(Spec, true, _) -> Spec#{required => true};
trans_required(Spec, _, path) -> Spec#{required => true};
trans_required(Spec, _, _) -> Spec.
@@ -335,7 +330,7 @@ response(Status, #{content := _} = Content, {Acc, RefsAcc, Module, Options}) ->
response(Status, ?REF(StructName), {Acc, RefsAcc, Module, Options}) ->
response(Status, ?R_REF(Module, StructName), {Acc, RefsAcc, Module, Options});
response(Status, ?R_REF(_Mod, _Name) = RRef, {Acc, RefsAcc, Module, Options}) ->
- SchemaToSpec = schema_to_spec_func(Options),
+ SchemaToSpec = schema_converter(Options),
{Spec, Refs} = SchemaToSpec(RRef, Module),
Content = content(Spec),
{Acc#{integer_to_binary(Status) => #{<<"content">> => Content}}, Refs ++ RefsAcc, Module, Options};
@@ -557,7 +552,7 @@ parse_object(PropList = [_ | _], Module, Options) when is_list(PropList) ->
HoconType = hocon_schema:field_schema(Hocon, type),
Init0 = init_prop([default | ?DEFAULT_FIELDS], #{}, Hocon),
Init = trans_desc(Init0, Hocon),
- SchemaToSpec = schema_to_spec_func(Options),
+ SchemaToSpec = schema_converter(Options),
{Prop, Refs1} = SchemaToSpec(HoconType, Module),
NewRequiredAcc =
case is_required(Hocon) of
@@ -581,8 +576,7 @@ parse_object(Other, Module, Options) ->
args => Other, module => Module, options => Options}}).
is_required(Hocon) ->
- hocon_schema:field_schema(Hocon, required) =:= true orelse
- hocon_schema:field_schema(Hocon, nullable) =:= false.
+ hocon_schema:field_schema(Hocon, required) =:= true.
content(ApiSpec) ->
content(ApiSpec, undefined).
@@ -596,5 +590,5 @@ to_ref(Mod, StructName, Acc, RefsAcc) ->
Ref = #{<<"$ref">> => ?TO_COMPONENTS_PARAM(Mod, StructName)},
{[Ref | Acc], [{Mod, StructName, parameter} | RefsAcc]}.
-schema_to_spec_func(Options) ->
- maps:get(schema_to_spec_func, Options, fun hocon_schema_to_spec/2).
+schema_converter(Options) ->
+ maps:get(schema_converter, Options, fun hocon_schema_to_spec/2).
diff --git a/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl
index 1ae2e2e1f..4cf53ef38 100644
--- a/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl
+++ b/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl
@@ -124,8 +124,7 @@ t_nullable(_Config) ->
NullableFalse = [#{in => query,name => userid, required => true,
schema => #{example => <<"binary-example">>, type => string}}],
NullableTrue = [#{in => query,name => userid,
- schema => #{example => <<"binary-example">>, type => string,
- nullable => true}}],
+ schema => #{example => <<"binary-example">>, type => string}, required => false}],
validate("/nullable/false", NullableFalse),
validate("/nullable/true", NullableTrue),
ok.
@@ -358,9 +357,9 @@ schema("/test/without/in") ->
schema("/required/false") ->
to_schema([{'userid', mk(binary(), #{in => query, required => false})}]);
schema("/nullable/false") ->
- to_schema([{'userid', mk(binary(), #{in => query, nullable => false})}]);
+ to_schema([{'userid', mk(binary(), #{in => query, required => true})}]);
schema("/nullable/true") ->
- to_schema([{'userid', mk(binary(), #{in => query, nullable => true})}]);
+ to_schema([{'userid', mk(binary(), #{in => query, required => false})}]);
schema("/method/ok") ->
Response = #{responses => #{200 => <<"ok">>}},
lists:foldl(fun(Method, Acc) -> Acc#{Method => Response} end,
diff --git a/apps/emqx_dashboard/test/emqx_swagger_remote_schema.erl b/apps/emqx_dashboard/test/emqx_swagger_remote_schema.erl
index 110f08ebe..d2a47e59e 100644
--- a/apps/emqx_dashboard/test/emqx_swagger_remote_schema.erl
+++ b/apps/emqx_dashboard/test/emqx_swagger_remote_schema.erl
@@ -50,10 +50,10 @@ fields("ref3") ->
default_username(type) -> string();
default_username(default) -> "admin";
-default_username(nullable) -> false;
+default_username(required) -> true;
default_username(_) -> undefined.
default_password(type) -> string();
default_password(default) -> "public";
-default_password(nullable) -> false;
+default_password(required) -> true;
default_password(_) -> undefined.
diff --git a/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl
index 1c155fde9..bf48046c2 100644
--- a/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl
+++ b/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl
@@ -499,16 +499,16 @@ paths() ->
schema("/object") ->
to_schema([
- {per_page, mk(range(1, 100), #{nullable => false, desc => <<"good per page desc">>})},
+ {per_page, mk(range(1, 100), #{required => true, desc => <<"good per page desc">>})},
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
- #{default => 5, nullable => false})},
+ #{default => 5, required => true})},
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
]);
schema("/nest/object") ->
to_schema([
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
- #{default => 5, nullable => false})},
+ #{default => 5, required => true})},
{nest_object, [
{good_nest_1, mk(integer(), #{})},
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
@@ -572,5 +572,5 @@ enable(_) -> undefined.
init_file(type) -> binary();
init_file(desc) -> <<"test test desc">>;
-init_file(nullable) -> true;
+init_file(required) -> false;
init_file(_) -> undefined.
diff --git a/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl
index ca6ea97cc..3b68c8eff 100644
--- a/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl
+++ b/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl
@@ -299,9 +299,9 @@ schema("/simple/bin") ->
to_schema(<<"binary ok">>);
schema("/object") ->
Object = [
- {per_page, mk(range(1, 100), #{nullable => false, desc => <<"good per page desc">>})},
+ {per_page, mk(range(1, 100), #{required => true, desc => <<"good per page desc">>})},
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
- #{default => 5, nullable => false})},
+ #{default => 5, required => true})},
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
],
to_schema(Object);
@@ -309,7 +309,7 @@ schema("/nest/object") ->
Response = [
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
- #{default => 5, nullable => false})},
+ #{default => 5, required => true})},
{nest_object, [
{good_nest_1, mk(integer(), #{})},
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
@@ -425,5 +425,5 @@ enable(_) -> undefined.
init_file(type) -> binary();
init_file(desc) -> <<"test test desc">>;
-init_file(nullable) -> true;
+init_file(required) -> false;
init_file(_) -> undefined.
diff --git a/apps/emqx_gateway/src/emqx_gateway_api.erl b/apps/emqx_gateway/src/emqx_gateway_api.erl
index 610971a8c..b3cbcb5b4 100644
--- a/apps/emqx_gateway/src/emqx_gateway_api.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_api.erl
@@ -219,7 +219,7 @@ params_gateway_status_in_qs() ->
[{status,
mk(binary(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Gateway Status">>
, example => <<"">>
})}
@@ -245,11 +245,11 @@ fields(gateway_overview) ->
#{desc => <<"The Gateway created datetime">>})}
, {started_at,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"The Gateway started datetime">>})}
, {stopped_at,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"The Gateway stopped datetime">>})}
, {max_connections,
mk(integer(),
@@ -260,7 +260,7 @@ fields(gateway_overview) ->
})}
, {listeners,
mk(hoconsc:array(ref(gateway_listener_overview)),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The Gateway listeners overview">>})}
];
fields(gateway_listener_overview) ->
@@ -295,7 +295,7 @@ fields(Listener) when Listener == tcp_listener;
Listener == dtls_listener ->
[ {id,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener ID">>})}
, {type,
mk(hoconsc:union([tcp, ssl, udp, dtls]),
@@ -305,7 +305,7 @@ fields(Listener) when Listener == tcp_listener;
#{ desc => <<"Listener Name">>})}
, {running,
mk(boolean(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener running status">>})}
] ++ emqx_gateway_schema:fields(Listener);
@@ -334,7 +334,7 @@ convert_listener_struct(Schema) ->
{value, {listeners,
#{type := Type}}, Schema1} = lists:keytake(listeners, 1, Schema),
ListenerSchema = hoconsc:mk(listeners_schema(Type),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The gateway listeners">>
}),
lists:keystore(listeners, 1, Schema1, {listeners, ListenerSchema}).
diff --git a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl
index 5d48c9ac3..30ea7b050 100644
--- a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl
@@ -287,13 +287,13 @@ params_userid_in_path() ->
params_paging_in_qs() ->
[{page, mk(integer(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Page Index">>
, example => 1
})},
{limit, mk(integer(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Page Limit">>
, example => 100
})}
diff --git a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl
index 22c3dee37..e9c0fa879 100644
--- a/apps/emqx_gateway/src/emqx_gateway_api_clients.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_api_clients.erl
@@ -468,7 +468,7 @@ params_client_insta() ->
++ params_gateway_name_in_path().
params_client_searching_in_qs() ->
- M = #{in => query, nullable => true, example => <<"">>},
+ M = #{in => query, required => false, example => <<"">>},
[ {node,
mk(binary(),
M#{desc => <<"Match the client's node name">>})}
@@ -532,7 +532,7 @@ params_paging() ->
[ {page,
mk(integer(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Page Index">>
, example => 1
})}
@@ -540,7 +540,7 @@ params_paging() ->
mk(integer(),
#{ in => query
, desc => <<"Page Limit">>
- , nullable => true
+ , required => false
, example => 100
})}
].
diff --git a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl
index 95910cddd..8b8ab6fd2 100644
--- a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl
@@ -434,13 +434,13 @@ params_userid_in_path() ->
params_paging_in_qs() ->
[{page, mk(integer(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Page Index">>
, example => 1
})},
{limit, mk(integer(),
#{ in => query
- , nullable => true
+ , required => false
, desc => <<"Page Limit">>
, example => 100
})}
@@ -457,22 +457,22 @@ fields(listener) ->
common_listener_opts() ++
[ {tcp,
mk(ref(tcp_listener_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The tcp socket options for tcp or ssl listener">>
})}
, {ssl,
mk(ref(ssl_listener_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The ssl socket options for ssl listener">>
})}
, {udp,
mk(ref(udp_listener_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The udp socket options for udp or dtls listener">>
})}
, {dtls,
mk(ref(dtls_listener_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The dtls socket options for dtls listener">>
})}
];
@@ -529,47 +529,47 @@ lists_key_without([K | Ks], N, L) ->
common_listener_opts() ->
[ {enable,
mk(boolean(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Whether to enable this listener">>})}
, {id,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener Id">>})}
, {name,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener name">>})}
, {type,
mk(hoconsc:enum([tcp, ssl, udp, dtls]),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener type. Enum: tcp, udp, ssl, dtls">>})}
, {running,
mk(boolean(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener running status">>})}
, {bind,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener bind address or port">>})}
, {acceptors,
mk(integer(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener acceptors number">>})}
, {access_rules,
mk(hoconsc:array(binary()),
- #{ nullable => true
+ #{ required => false
, desc => <<"Listener Access rules for client">>})}
, {max_conn_rate,
mk(integer(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Max connection rate for the listener">>})}
, {max_connections,
mk(integer(),
- #{ nullable => true
+ #{ required => false
, desc => <<"Max connections for the listener">>})}
, {mountpoint,
mk(binary(),
- #{ nullable => true
+ #{ required => false
, desc =>
<<"The Mounpoint for clients of the listener. "
"The gateway-level mountpoint configuration can be overloaded "
@@ -577,7 +577,7 @@ common_listener_opts() ->
%% FIXME:
, {authentication,
mk(emqx_authn_schema:authenticator_type(),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => <<"The authenticatior for this listener">>
})}
] ++ emqx_gateway_schema:proxy_protocol_opts().
diff --git a/apps/emqx_gateway/src/emqx_gateway_schema.erl b/apps/emqx_gateway/src/emqx_gateway_schema.erl
index df46ace25..822118e2a 100644
--- a/apps/emqx_gateway/src/emqx_gateway_schema.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_schema.erl
@@ -59,21 +59,21 @@ roots() -> [gateway].
fields(gateway) ->
[{stomp,
sc(ref(stomp),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc =>
"The Stomp Gateway configuration.
This gateway supports v1.2/1.1/1.0"
})},
{mqttsn,
sc(ref(mqttsn),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc =>
"The MQTT-SN Gateway configuration.
This gateway only supports the v1.2 protocol"
})},
{coap,
sc(ref(coap),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc =>
"The CoAP Gateway configuration.
This gateway is implemented based on RFC-7252 and
@@ -81,14 +81,14 @@ https://core-wg.github.io/coap-pubsub/draft-ietf-core-pubsub.html"
})},
{lwm2m,
sc(ref(lwm2m),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc =>
"The LwM2M Gateway configuration.
This gateway only supports the v1.0.1 protocol"
})},
{exproto,
sc(ref(exproto),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc => "The Extension Protocol configuration"
})}
];
@@ -120,7 +120,7 @@ fields(mqttsn) ->
[ {gateway_id,
sc(integer(),
#{ default => 1
- , nullable => false
+ , required => true
, desc =>
"MQTT-SN Gateway ID.
When the broadcast
option is enabled,
@@ -145,7 +145,7 @@ The client just sends its 'PUBLISH' messages to a GW"
, {predefined,
sc(hoconsc:array(ref(mqttsn_predefined)),
#{ default => []
- , nullable => {true, recursively}
+ , required => {false, recursively}
, desc =>
<<"The pre-defined topic IDs and topic names.
A 'pre-defined' topic ID is a topic ID whose mapping to a topic name
@@ -221,7 +221,7 @@ fields(lwm2m) ->
[ {xml_dir,
sc(binary(),
#{ default =>"etc/lwm2m_xml"
- , nullable => false
+ , required => true
, desc => "The Directory for LwM2M Resource definition"
})}
, {lifetime_min,
@@ -261,7 +261,7 @@ beyond this time window are temporarily stored in memory."
})}
, {translators,
sc(ref(lwm2m_translators),
- #{ nullable => false
+ #{ required => true
, desc => "Topic configuration for LwM2M's gateway publishing and subscription"
})}
, {listeners, sc(ref(udp_listeners))}
@@ -270,12 +270,12 @@ beyond this time window are temporarily stored in memory."
fields(exproto) ->
[ {server,
sc(ref(exproto_grpc_server),
- #{ nullable => false
+ #{ required => true
, desc => "Configurations for starting the ConnectionAdapter
service"
})}
, {handler,
sc(ref(exproto_grpc_handler),
- #{ nullable => false
+ #{ required => true
, desc => "Configurations for request to ConnectionHandler
service"
})}
, {listeners, sc(ref(udp_tcp_listeners))}
@@ -284,18 +284,18 @@ fields(exproto) ->
fields(exproto_grpc_server) ->
[ {bind,
sc(hoconsc:union([ip_port(), integer()]),
- #{nullable => false})}
+ #{required => true})}
, {ssl,
sc(ref(ssl_server_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
})}
];
fields(exproto_grpc_handler) ->
- [ {address, sc(binary(), #{nullable => false})}
+ [ {address, sc(binary(), #{required => true})}
, {ssl,
sc(ref(ssl_client_opts),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
})}
];
@@ -324,13 +324,13 @@ fields(lwm2m_translators) ->
For each new LwM2M client that succeeds in going online, the gateway creates
a subscription relationship to receive downstream commands and send it to
the LwM2M client"
- , nullable => false
+ , required => true
})}
, {response,
sc(ref(translator),
#{ desc =>
"The topic for gateway to publish the acknowledge events from LwM2M client"
- , nullable => false
+ , required => true
})}
, {notify,
sc(ref(translator),
@@ -338,24 +338,24 @@ the LwM2M client"
"The topic for gateway to publish the notify events from LwM2M client.
After succeed observe a resource of LwM2M client, Gateway will send the
notify events via this topic, if the client reports any resource changes"
- , nullable => false
+ , required => true
})}
, {register,
sc(ref(translator),
#{ desc =>
"The topic for gateway to publish the register events from LwM2M client.
"
- , nullable => false
+ , required => true
})}
, {update,
sc(ref(translator),
#{ desc =>
"The topic for gateway to publish the update events from LwM2M client.
"
- , nullable => false
+ , required => true
})}
];
fields(translator) ->
- [ {topic, sc(binary(), #{nullable => false})}
+ [ {topic, sc(binary(), #{required => true})}
, {qos, sc(emqx_schema:qos(), #{default => 0})}
];
@@ -423,7 +423,7 @@ fields(dtls_opts) ->
authentication_schema() ->
sc(emqx_authn_schema:authenticator_type(),
- #{ nullable => {true, recursively}
+ #{ required => {false, recursively}
, desc =>
"""Default authentication configs for all the gateway listeners.
For per-listener overrides see authentication
diff --git a/apps/emqx_management/src/emqx_mgmt_api_alarms.erl b/apps/emqx_management/src/emqx_mgmt_api_alarms.erl
index e5cfca44d..86e9e6905 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_alarms.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_alarms.erl
@@ -44,7 +44,7 @@ schema("/alarms") ->
hoconsc:ref(emqx_dashboard_swagger, limit),
{activated, hoconsc:mk(boolean(), #{in => query,
desc => <<"All alarms, if not specified">>,
- nullable => true})}
+ required => false})}
],
responses => #{
200 => [
diff --git a/apps/emqx_management/src/emqx_mgmt_api_app.erl b/apps/emqx_management/src/emqx_mgmt_api_app.erl
index 51bd92bc0..fb43629ff 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_app.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_app.erl
@@ -94,7 +94,7 @@ fields(app) ->
{expired_at, hoconsc:mk(hoconsc:union([undefined, emqx_datetime:epoch_second()]),
#{desc => "No longer valid datetime",
example => <<"2021-12-05T02:01:34.186Z">>,
- nullable => true,
+ required => false,
default => undefined
})},
{created_at, hoconsc:mk(emqx_datetime:epoch_second(),
@@ -102,8 +102,8 @@ fields(app) ->
example => <<"2021-12-01T00:00:00.000Z">>
})},
{desc, hoconsc:mk(binary(),
- #{example => <<"Note">>, nullable => true})},
- {enable, hoconsc:mk(boolean(), #{desc => "Enable/Disable", nullable => true})}
+ #{example => <<"Note">>, required => false})},
+ {enable, hoconsc:mk(boolean(), #{desc => "Enable/Disable", required => false})}
];
fields(name) ->
[{name, hoconsc:mk(binary(),
diff --git a/apps/emqx_management/src/emqx_mgmt_api_banned.erl b/apps/emqx_management/src/emqx_mgmt_api_banned.erl
index 8633ccfc2..265fb2a9b 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_banned.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_banned.erl
@@ -101,27 +101,27 @@ fields(ban) ->
[
{as, hoconsc:mk(hoconsc:enum(?BANNED_TYPES), #{
desc => <<"Banned type clientid, username, peerhost">>,
- nullable => false,
+ required => true,
example => username})},
{who, hoconsc:mk(binary(), #{
desc => <<"Client info as banned type">>,
- nullable => false,
+ required => true,
example => <<"Banned name"/utf8>>})},
{by, hoconsc:mk(binary(), #{
desc => <<"Commander">>,
- nullable => true,
+ required => false,
example => <<"mgmt_api">>})},
{reason, hoconsc:mk(binary(), #{
desc => <<"Banned reason">>,
- nullable => true,
+ required => false,
example => <<"Too many requests">>})},
{at, hoconsc:mk(emqx_datetime:epoch_second(), #{
desc => <<"Create banned time, rfc3339, now if not specified">>,
- nullable => true,
+ required => false,
example => <<"2021-10-25T21:48:47+08:00">>})},
{until, hoconsc:mk(emqx_datetime:epoch_second(), #{
desc => <<"Cancel banned time, rfc3339, now + 5 minute if not specified">>,
- nullable => true,
+ required => false,
example => <<"2021-10-25T21:53:47+08:00">>})
}
];
diff --git a/apps/emqx_management/src/emqx_mgmt_api_clients.erl b/apps/emqx_management/src/emqx_mgmt_api_clients.erl
index 3218d707e..86d24434c 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_clients.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_clients.erl
@@ -93,65 +93,65 @@ schema("/clients") ->
hoconsc:ref(emqx_dashboard_swagger, limit),
{node, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Node name">>,
example => atom_to_list(node())})},
{username, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"User name">>})},
{zone, hoconsc:mk(binary(), #{
in => query,
- nullable => true})},
+ required => false})},
{ip_address, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Client's IP address">>,
example => <<"127.0.0.1">>})},
{conn_state, hoconsc:mk(hoconsc:enum([connected, idle, disconnected]), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"The current connection status of the client, ",
"the possible values are connected,idle,disconnected">>})},
{clean_start, hoconsc:mk(boolean(), #{
in => query,
- nullable => true,
+ required => false,
description => <<"Whether the client uses a new session">>})},
{proto_name, hoconsc:mk(hoconsc:enum(['MQTT', 'CoAP', 'LwM2M', 'MQTT-SN']), #{
in => query,
- nullable => true,
+ required => false,
description => <<"Client protocol name, ",
"the possible values are MQTT,CoAP,LwM2M,MQTT-SN">>})},
{proto_ver, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Client protocol version">>})},
{like_clientid, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Fuzzy search of client identifier by substring method">>})},
{like_username, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Client user name, fuzzy search by substring">>})},
{gte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Search client session creation time by greater",
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
{lte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Search client session creation time by less",
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
{gte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Search client connection creation time by greater"
" than or equal method, rfc3339 or timestamp(epoch millisecond)">>})},
{lte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Search client connection creation time by less"
" than or equal method, rfc3339 or timestamp(millisecond)">>})}
],
diff --git a/apps/emqx_management/src/emqx_mgmt_api_configs.erl b/apps/emqx_management/src/emqx_mgmt_api_configs.erl
index 827f6e913..8f9797843 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_configs.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_configs.erl
@@ -67,7 +67,7 @@ schema("/configs") ->
desc =>
<<"Node's name: If you do not fill in the fields, this node will be used by default.">>})}],
responses => #{
- 200 => config_list([])
+ 200 => config_list(?EXCLUDES)
}
}
};
diff --git a/apps/emqx_management/src/emqx_mgmt_api_metrics.erl b/apps/emqx_management/src/emqx_mgmt_api_metrics.erl
index 5ebc01c21..ee087efa9 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_metrics.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_metrics.erl
@@ -71,7 +71,7 @@ schema("/metrics") ->
[{ aggregate
, mk( boolean()
, #{ in => query
- , nullable => true
+ , required => false
, desc => <<"Whether to aggregate all nodes Metrics">>})
}]
, responses =>
diff --git a/apps/emqx_management/src/emqx_mgmt_api_nodes.erl b/apps/emqx_management/src/emqx_mgmt_api_nodes.erl
index 79c40a2e6..5eb16ad08 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_nodes.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_nodes.erl
@@ -140,7 +140,7 @@ fields(node_info) ->
, mk( emqx_schema:bytesize()
, #{desc => <<"Used memory">>, example => "256.00M"})}
, { node_status
- , mk( enum(["Running", "Stopped"])
+ , mk( enum(['Running', 'Stopped'])
, #{desc => <<"Node status">>, example => "Running"})}
, { otp_release
, mk( string()
@@ -164,7 +164,7 @@ fields(node_info) ->
, mk( string()
, #{desc => <<"Path to log files">>, example => "path/to/log | not found"})}
, { role
- , mk( enum(["core", "replicant"])
+ , mk( enum([core, replicant])
, #{desc => <<"Node role">>, example => "core"})}
].
diff --git a/apps/emqx_management/src/emqx_mgmt_api_stats.erl b/apps/emqx_management/src/emqx_mgmt_api_stats.erl
index d97a46623..ee28e8f73 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_stats.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_stats.erl
@@ -59,7 +59,7 @@ fields(aggregate) ->
, mk( boolean()
, #{ desc => <<"Calculation aggregate for all nodes">>
, in => query
- , nullable => true
+ , required => false
, example => false})}
];
fields(node_stats_data) ->
diff --git a/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl b/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl
index 40e3948a7..b33db0cd1 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_subscriptions.erl
@@ -75,38 +75,38 @@ parameters() ->
{
node, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Node name">>,
example => atom_to_list(node())})
},
{
clientid, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Client ID">>})
},
{
qos, hoconsc:mk(emqx_schema:qos(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"QoS">>})
},
{
topic, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Topic, url encoding">>})
},
{
match_topic, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Match topic string, url encoding">>})
},
{
share_group, hoconsc:mk(binary(), #{
in => query,
- nullable => true,
+ required => false,
desc => <<"Shared subscription group name">>})
}
].
diff --git a/apps/emqx_management/src/emqx_mgmt_api_trace.erl b/apps/emqx_management/src/emqx_mgmt_api_trace.erl
index 232d523c2..b9aaec95e 100644
--- a/apps/emqx_management/src/emqx_mgmt_api_trace.erl
+++ b/apps/emqx_management/src/emqx_mgmt_api_trace.erl
@@ -144,45 +144,45 @@ fields(trace) ->
{name, hoconsc:mk(binary(),
#{desc => "Unique and format by [a-zA-Z0-9-_]",
validator => fun ?MODULE:validate_name/1,
- nullable => false,
+ required => true,
example => <<"EMQX-TRACE-1">>})},
{type, hoconsc:mk(hoconsc:enum([clientid, topic, ip_address]),
#{desc => """Filter type""",
- nullable => false,
+ required => true,
example => <<"clientid">>})},
{topic, hoconsc:mk(binary(),
#{desc => """support mqtt wildcard topic.""",
- nullable => true,
+ required => false,
example => <<"/dev/#">>})},
{clientid, hoconsc:mk(binary(),
#{desc => """mqtt clientid.""",
- nullable => true,
+ required => false,
example => <<"dev-001">>})},
%% TODO add ip_address type in emqx_schema.erl
{ip_address, hoconsc:mk(binary(),
#{desc => "client ip address",
- nullable => true,
+ required => false,
example => <<"127.0.0.1">>
})},
{status, hoconsc:mk(hoconsc:enum([running, stopped, waiting]),
#{desc => "trace status",
- nullable => true,
+ required => false,
example => running
})},
{start_at, hoconsc:mk(emqx_datetime:epoch_second(),
#{desc => "rfc3339 timestamp or epoch second",
- nullable => true,
+ required => false,
example => <<"2021-11-04T18:17:38+08:00">>
})},
{end_at, hoconsc:mk(emqx_datetime:epoch_second(),
#{desc => "rfc3339 timestamp or epoch second",
- nullable => true,
+ required => false,
example => <<"2021-11-05T18:17:38+08:00">>
})},
{log_size, hoconsc:mk(hoconsc:array(map()),
#{desc => "trace log size",
example => [#{<<"node">> => <<"emqx@127.0.0.1">>, <<"size">> => 1024}],
- nullable => true})}
+ required => false})}
];
fields(name) ->
[{name, hoconsc:mk(binary(),
@@ -198,14 +198,14 @@ fields(node) ->
#{
desc => "Node name",
in => query,
- nullable => true
+ required => false
})}];
fields(bytes) ->
[{bytes, hoconsc:mk(integer(),
#{
desc => "Maximum number of bytes to store in request",
in => query,
- nullable => true,
+ required => false,
default => 1000
})}];
fields(position) ->
@@ -213,7 +213,7 @@ fields(position) ->
#{
desc => "Offset from the current trace position.",
in => query,
- nullable => true,
+ required => false,
default => 0
})}].
diff --git a/apps/emqx_management/test/emqx_mgmt_api_trace_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_api_trace_SUITE.erl
index bbd68948a..409fe9104 100644
--- a/apps/emqx_management/test/emqx_mgmt_api_trace_SUITE.erl
+++ b/apps/emqx_management/test/emqx_mgmt_api_trace_SUITE.erl
@@ -58,7 +58,7 @@ t_http_test(_Config) ->
?assertEqual(
#{
<<"code">> => <<"BAD_REQUEST">>,
- <<"message">> => <<"name : not_nullable">>
+ <<"message">> => <<"name : mandatory_required_field">>
}, json(Body)),
Name = <<"test-name">>,
diff --git a/apps/emqx_modules/src/emqx_topic_metrics_api.erl b/apps/emqx_modules/src/emqx_topic_metrics_api.erl
index 889268a4a..ddd7ffe88 100644
--- a/apps/emqx_modules/src/emqx_topic_metrics_api.erl
+++ b/apps/emqx_modules/src/emqx_topic_metrics_api.erl
@@ -121,12 +121,12 @@ fields(reset) ->
<<"Topic Name. If this parameter is not present,"
" all created topic metrics will be reset">>
, example => <<"testtopic/1">>
- , nullable => true})}
+ , required => false})}
, {action
, mk( string()
, #{ desc => <<"Action Name. Only as a \"reset\"">>
, enum => [reset]
- , nullable => false
+ , required => true
, example => <<"reset">>})}
];
@@ -135,21 +135,21 @@ fields(topic_metrics) ->
, mk( binary()
, #{ desc => <<"Topic Name">>
, example => <<"testtopic/1">>
- , nullable => false})},
+ , required => true})},
{ create_time
, mk( emqx_datetime:epoch_second()
, #{ desc => <<"Topic Metrics created date time, in rfc3339">>
- , nullable => false
+ , required => true
, example => <<"2022-01-14T21:48:47+08:00">>})},
{ reset_time
, mk( emqx_datetime:epoch_second()
, #{ desc => <<"Topic Metrics reset date time, in rfc3339. Nullable if never reset">>
- , nullable => true
+ , required => false
, example => <<"2022-01-14T21:48:47+08:00">>})},
{ metrics
, mk( ref(metrics)
, #{ desc => <<"Topic Metrics fields">>
- , nullable => false})
+ , required => true})
}
];
diff --git a/apps/emqx_plugins/src/emqx_plugins_schema.erl b/apps/emqx_plugins/src/emqx_plugins_schema.erl
index b47a0b3c3..9dfb77589 100644
--- a/apps/emqx_plugins/src/emqx_plugins_schema.erl
+++ b/apps/emqx_plugins/src/emqx_plugins_schema.erl
@@ -54,12 +54,12 @@ state_fields() ->
"It should match the plugin application name-version as the "
"for the plugin release package name
"
"For example: my_plugin-0.1.0."
- , nullable => false
+ , required => true
})}
, {enable,
hoconsc:mk(boolean(),
#{ desc => "Set to 'true' to enable this plugin"
- , nullable => false
+ , required => true
})}
].
@@ -69,14 +69,14 @@ root_fields() ->
].
states(type) -> hoconsc:array(hoconsc:ref(state));
-states(nullable) -> true;
+states(required) -> false;
states(default) -> [];
states(desc) -> "An array of plugins in the desired states.
"
"The plugins are started in the defined order";
states(_) -> undefined.
install_dir(type) -> string();
-install_dir(nullable) -> true;
+install_dir(required) -> false;
install_dir(default) -> "plugins"; %% runner's root dir
install_dir(T) when T =/= desc -> undefined;
install_dir(desc) -> """
diff --git a/apps/emqx_prometheus/rebar.config b/apps/emqx_prometheus/rebar.config
index c8b94178a..96afa679a 100644
--- a/apps/emqx_prometheus/rebar.config
+++ b/apps/emqx_prometheus/rebar.config
@@ -4,7 +4,7 @@
[ {emqx, {path, "../emqx"}},
%% FIXME: tag this as v3.1.3
{prometheus, {git, "https://github.com/deadtrickster/prometheus.erl", {tag, "v4.8.1"}}},
- {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
+ {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
]}.
{edoc_opts, [{preprocess, true}]}.
diff --git a/apps/emqx_psk/src/emqx_psk_schema.erl b/apps/emqx_psk/src/emqx_psk_schema.erl
index e9a71e35b..a8a870ea1 100644
--- a/apps/emqx_psk/src/emqx_psk_schema.erl
+++ b/apps/emqx_psk/src/emqx_psk_schema.erl
@@ -60,7 +60,7 @@ init_file(desc) ->
"The file has to be structured line-by-line, each line must be in ",
"the format of PSKIdentity:SharedSecret
. For example: ",
"mydevice1:c2VjcmV0
">>;
-init_file(nullable) -> true;
+init_file(required) -> false;
init_file(_) -> undefined.
separator(type) -> binary();
diff --git a/apps/emqx_resource/test/emqx_test_resource.erl b/apps/emqx_resource/test/emqx_test_resource.erl
index 1849e329b..b68fba1c1 100644
--- a/apps/emqx_resource/test/emqx_test_resource.erl
+++ b/apps/emqx_resource/test/emqx_test_resource.erl
@@ -35,11 +35,11 @@ roots() -> [{name, fun name/1},
{register, fun register/1}].
name(type) -> atom();
-name(nullable) -> false;
+name(required) -> true;
name(_) -> undefined.
register(type) -> boolean();
-register(nullable) -> false;
+register(required) -> true;
register(default) -> false;
register(_) -> undefined.
diff --git a/apps/emqx_rule_engine/src/emqx_rule_api_schema.erl b/apps/emqx_rule_engine/src/emqx_rule_api_schema.erl
index b1dc1bba5..66064ac24 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_api_schema.erl
+++ b/apps/emqx_rule_engine/src/emqx_rule_api_schema.erl
@@ -55,7 +55,7 @@ fields("rule_info") ->
%% TODO: we can delete this API if the Dashboard not denpends on it
fields("rule_events") ->
ETopics = [binary_to_atom(emqx_rule_events:event_topic(E)) || E <- emqx_rule_events:event_names()],
- [ {"event", sc(hoconsc:enum(ETopics), #{desc => "The event topics", nullable => false})}
+ [ {"event", sc(hoconsc:enum(ETopics), #{desc => "The event topics", required => true})}
, {"title", sc(binary(), #{desc => "The title", example => "some title"})}
, {"description", sc(binary(), #{desc => "The description", example => "some desc"})}
, {"columns", sc(map(), #{desc => "The columns"})}
@@ -75,7 +75,7 @@ fields("rule_test") ->
]),
#{desc => "The context of the event for testing",
default => #{}})}
- , {"sql", sc(binary(), #{desc => "The SQL of the rule for testing", nullable => false})}
+ , {"sql", sc(binary(), #{desc => "The SQL of the rule for testing", required => true})}
];
fields("metrics") ->
@@ -121,7 +121,7 @@ fields("node_metrics") ->
] ++ fields("metrics");
fields("ctx_pub") ->
- [ {"event_type", sc(message_publish, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(message_publish, #{desc => "Event Type", required => true})}
, {"id", sc(binary(), #{desc => "Message ID"})}
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
, {"username", sc(binary(), #{desc => "The User Name"})}
@@ -133,7 +133,7 @@ fields("ctx_pub") ->
] ++ [qos()];
fields("ctx_sub") ->
- [ {"event_type", sc(session_subscribed, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(session_subscribed, #{desc => "Event Type", required => true})}
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
, {"username", sc(binary(), #{desc => "The User Name"})}
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
@@ -144,11 +144,11 @@ fields("ctx_sub") ->
] ++ [qos()];
fields("ctx_unsub") ->
- [{"event_type", sc(session_unsubscribed, #{desc => "Event Type", nullable => false})}] ++
+ [{"event_type", sc(session_unsubscribed, #{desc => "Event Type", required => true})}] ++
proplists:delete("event_type", fields("ctx_sub"));
fields("ctx_delivered") ->
- [ {"event_type", sc(message_delivered, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(message_delivered, #{desc => "Event Type", required => true})}
, {"id", sc(binary(), #{desc => "Message ID"})}
, {"from_clientid", sc(binary(), #{desc => "The Client ID"})}
, {"from_username", sc(binary(), #{desc => "The User Name"})}
@@ -162,11 +162,11 @@ fields("ctx_delivered") ->
] ++ [qos()];
fields("ctx_acked") ->
- [{"event_type", sc(message_acked, #{desc => "Event Type", nullable => false})}] ++
+ [{"event_type", sc(message_acked, #{desc => "Event Type", required => true})}] ++
proplists:delete("event_type", fields("ctx_delivered"));
fields("ctx_dropped") ->
- [ {"event_type", sc(message_dropped, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(message_dropped, #{desc => "Event Type", required => true})}
, {"id", sc(binary(), #{desc => "Message ID"})}
, {"reason", sc(binary(), #{desc => "The Reason for Dropping"})}
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
@@ -179,7 +179,7 @@ fields("ctx_dropped") ->
] ++ [qos()];
fields("ctx_connected") ->
- [ {"event_type", sc(client_connected, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(client_connected, #{desc => "Event Type", required => true})}
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
, {"username", sc(binary(), #{desc => "The User Name"})}
, {"mountpoint", sc(binary(), #{desc => "The Mountpoint"})}
@@ -196,7 +196,7 @@ fields("ctx_connected") ->
];
fields("ctx_disconnected") ->
- [ {"event_type", sc(client_disconnected, #{desc => "Event Type", nullable => false})}
+ [ {"event_type", sc(client_disconnected, #{desc => "Event Type", required => true})}
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
, {"username", sc(binary(), #{desc => "The User Name"})}
, {"reason", sc(binary(), #{desc => "The Reason for Disconnect"})}
@@ -211,7 +211,7 @@ qos() ->
rule_id() ->
{"id", sc(binary(),
- #{ desc => "The ID of the rule", nullable => false
+ #{ desc => "The ID of the rule", required => true
, example => "293fb66f"
})}.
diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl
index 0946ed755..de04ee736 100644
--- a/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl
+++ b/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl
@@ -46,7 +46,7 @@ SQL query to transform the messages.
Example: SELECT * FROM \"test/topic\" WHERE payload.x = 1
"""
, example => "SELECT * FROM \"test/topic\" WHERE payload.x = 1"
- , nullable => false
+ , required => true
, validator => fun ?MODULE:validate_sql/1
})}
, {"outputs", sc(hoconsc:array(hoconsc:union(outputs())),
@@ -143,7 +143,7 @@ fields("republish_args") ->
The target topic of message to be re-published.
Template with variables is allowed, see description of the 'republish_args'.
"""
- , nullable => false
+ , required => true
, example => <<"a/1">>
})}
, {qos, sc(qos(),
@@ -182,7 +182,7 @@ rule_name() ->
{"name", sc(binary(),
#{ desc => "The name of the rule"
, default => ""
- , nullable => false
+ , required => true
, example => "foo"
})}.
diff --git a/apps/emqx_statsd/src/emqx_statsd_schema.erl b/apps/emqx_statsd/src/emqx_statsd_schema.erl
index 76725226a..09522870d 100644
--- a/apps/emqx_statsd/src/emqx_statsd_schema.erl
+++ b/apps/emqx_statsd/src/emqx_statsd_schema.erl
@@ -33,19 +33,19 @@ namespace() -> "statsd".
roots() -> ["statsd"].
fields("statsd") ->
- [ {enable, hoconsc:mk(boolean(), #{default => false, nullable => false})}
+ [ {enable, hoconsc:mk(boolean(), #{default => false, required => true})}
, {server, fun server/1}
, {sample_time_interval, fun duration_ms/1}
, {flush_time_interval, fun duration_ms/1}
].
server(type) -> emqx_schema:ip_port();
-server(nullable) -> false;
+server(required) -> true;
server(default) -> "127.0.0.1:8125";
server(_) -> undefined.
duration_ms(type) -> emqx_schema:duration_ms();
-duration_ms(nullable) -> false;
+duration_ms(required) -> true;
duration_ms(default) -> "10s";
duration_ms(_) -> undefined.
diff --git a/mix.exs b/mix.exs
index 5614aa654..d48abb0ce 100644
--- a/mix.exs
+++ b/mix.exs
@@ -68,7 +68,7 @@ defmodule EMQXUmbrella.MixProject do
# in conflict by emqtt and hocon
{:getopt, "1.0.2", override: true},
{:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.18.0", override: true},
- {:hocon, github: "emqx/hocon", tag: "0.24.0", override: true},
+ {:hocon, github: "emqx/hocon", tag: "0.25.0", override: true},
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.4.1", override: true},
{:esasl, github: "emqx/esasl", tag: "0.2.0"},
{:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},
diff --git a/rebar.config b/rebar.config
index 66f667bb5..31552346b 100644
--- a/rebar.config
+++ b/rebar.config
@@ -66,7 +66,7 @@
, {system_monitor, {git, "https://github.com/ieQu1/system_monitor", {tag, "3.0.2"}}}
, {getopt, "1.0.2"}
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
- , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
+ , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
, {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.4.1"}}}
, {esasl, {git, "https://github.com/emqx/esasl", {tag, "0.2.0"}}}
, {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.2"}}}
diff --git a/schema_v1.json b/schema_v1.json
new file mode 100644
index 000000000..948d69332
--- /dev/null
+++ b/schema_v1.json
@@ -0,0 +1,5392 @@
+{
+ "components": {
+ "schemas": {
+ "limiter.bucket": {
+ "properties": {
+ "zone": {
+ "description": "The bucket's zone",
+ "type": "string"
+ },
+ "aggregated": {
+ "$ref": "#/components/schemas/limiter.bucket_aggregated"
+ },
+ "per_client": {
+ "$ref": "#/components/schemas/limiter.client_bucket"
+ }
+ },
+ "type": "object"
+ },
+ "modules.rewrite": {
+ "properties": {
+ "action": {
+ "description": "Action",
+ "example": "publish",
+ "symbols": [
+ "subscribe",
+ "publish",
+ "all"
+ ],
+ "type": "enum"
+ },
+ "source_topic": {
+ "description": "Origin Topic",
+ "example": "x/#",
+ "type": "string"
+ },
+ "dest_topic": {
+ "description": "Destination Topic",
+ "example": "z/y/$1",
+ "type": "string"
+ },
+ "re": {
+ "description": "Regular expressions",
+ "example": "^x/y/(.+)$",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "dashboard.http": {
+ "required": [
+ "bind",
+ "protocol"
+ ],
+ "properties": {
+ "protocol": {
+ "default": "http",
+ "description": "HTTP/HTTPS protocol.",
+ "symbols": [
+ "http",
+ "https"
+ ],
+ "type": "enum"
+ },
+ "bind": {
+ "default": 18083,
+ "description": "Port without IP(18083) or port with specified IP(127.0.0.1:18083).",
+ "oneOf": [
+ {
+ "type": "ip_port"
+ },
+ {
+ "minimum": 1,
+ "type": "number"
+ }
+ ]
+ },
+ "num_acceptors": {
+ "default": 4,
+ "description": "Socket acceptor pool for TCP protocols.",
+ "type": "number"
+ },
+ "max_connections": {
+ "default": 512,
+ "type": "number"
+ },
+ "backlog": {
+ "default": 1024,
+ "description": "Defines the maximum length that the queue of pending connections can grow to.",
+ "type": "number"
+ },
+ "send_timeout": {
+ "default": "5s",
+ "type": "duration"
+ },
+ "inet6": {
+ "default": false,
+ "type": "boolean"
+ },
+ "ipv6_v6only": {
+ "default": false,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "authn-mysql.authentication": {
+ "required": [
+ "database",
+ "server",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "mysql"
+ ],
+ "type": "enum"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "query": {
+ "type": "string"
+ },
+ "query_timeout": {
+ "default": "5s",
+ "type": "duration"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "server": {
+ "description": "\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe MySQL default port 3306 is used if '[:Port]' isn't present",
+ "type": "ip_port"
+ },
+ "database": {
+ "type": "string"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "auto_reconnect": {
+ "default": true,
+ "type": "boolean"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "configuration.node": {
+ "required": [
+ "data_dir"
+ ],
+ "properties": {
+ "name": {
+ "default": "emqx@127.0.0.1",
+ "description": "Unique name of the EMQX node. It must follow %name%@FQDN
or\n %name%@IP
format.",
+ "type": "string"
+ },
+ "cookie": {
+ "default": "emqxsecretcookie",
+ "description": "Secret cookie is a random string that should be the same on all nodes in\n the given EMQX cluster, but unique per EMQX cluster. It is used to prevent EMQX nodes that\n belong to different clusters from accidentally connecting to each other.",
+ "type": "string"
+ },
+ "data_dir": {
+ "description": "Path to the persistent data directory. It must be unique per broker instance.",
+ "type": "string"
+ },
+ "config_files": {
+ "description": "List of configuration files that are read during startup. The order is\n significant: later configuration files override the previous ones.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "global_gc_interval": {
+ "default": "15m",
+ "description": "Periodic garbage collection interval.",
+ "type": "duration"
+ },
+ "crash_dump_file": {
+ "description": "Location of the crash dump file",
+ "type": "string"
+ },
+ "crash_dump_seconds": {
+ "default": "30s",
+ "description": "The number of seconds that the broker is allowed to spend writing\na crash dump",
+ "type": "duration"
+ },
+ "crash_dump_bytes": {
+ "default": "100MB",
+ "description": "The maximum size of a crash dump file in bytes.",
+ "type": "byteSize"
+ },
+ "dist_net_ticktime": {
+ "default": "2m",
+ "description": "This is the approximate time an EMQX node may be unresponsive until it is considered down and thereby disconnected.",
+ "type": "duration"
+ },
+ "dist_listen_min": {
+ "default": 6369,
+ "description": "Lower bound for the port range where EMQX broker listens for peer connections.",
+ "maximum": 65535,
+ "minimum": 1024,
+ "type": "number"
+ },
+ "dist_listen_max": {
+ "default": 6369,
+ "description": "Upper bound for the port range where EMQX broker listens for peer connections.",
+ "maximum": 65535,
+ "minimum": 1024,
+ "type": "number"
+ },
+ "backtrace_depth": {
+ "default": 23,
+ "description": "Maximum depth of the call stack printed in error messages and\n process_info
.",
+ "type": "number"
+ },
+ "applications": {
+ "default": "",
+ "description": "List of Erlang applications that shall be rebooted when the EMQX broker joins\n the cluster.",
+ "type": "comma_separated_string"
+ },
+ "etc_dir": {
+ "description": "etc
dir for the node",
+ "type": "string"
+ },
+ "cluster_call": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_call"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.force_shutdown": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "max_message_queue_len": {
+ "default": 1000,
+ "minimum": 0,
+ "type": "number"
+ },
+ "max_heap_size": {
+ "default": "32MB",
+ "type": "byteSize"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.ssl_client_opts": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "cacertfile": {
+ "description": "Trusted PEM format CA certificates bundle file.
\nThe certificates in this file are used to verify the TLS peer's certificates.\nAppend new certificates to the file if new CAs are to be trusted.\nThere is no need to restart EMQX to have the updated file loaded, because\nthe system regularly checks if file has been updated (and reload).
\nNOTE: invalidating (deleting) a certificate from the file will not affect\nalready established connections.\n",
+ "type": "string"
+ },
+ "certfile": {
+ "description": "PEM format certificates chain file.
\nThe certificates in this file should be in reversed order of the certificate\nissue chain. That is, the host's certificate should be placed in the beginning\nof the file, followed by the immediate issuer certificate and so on.\nAlthough the root CA certificate is optional, it should be placed at the end of\nthe file if it is to be added.\n",
+ "type": "string"
+ },
+ "keyfile": {
+ "description": "PEM format private key file.
\n",
+ "type": "string"
+ },
+ "verify": {
+ "default": "verify_none",
+ "symbols": [
+ "verify_peer",
+ "verify_none"
+ ],
+ "type": "enum"
+ },
+ "reuse_sessions": {
+ "default": true,
+ "type": "boolean"
+ },
+ "depth": {
+ "default": 10,
+ "type": "number"
+ },
+ "password": {
+ "description": "String containing the user's password. Only used if the private\nkey file is password-protected.",
+ "type": "string"
+ },
+ "versions": {
+ "default": [
+ "tlsv1.3",
+ "tlsv1.2",
+ "tlsv1.1",
+ "tlsv1"
+ ],
+ "description": "All TLS/DTLS versions to be supported.
\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIn case PSK cipher suites are intended, make sure to configured\n['tlsv1.2', 'tlsv1.1']
here.\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "ciphers": {
+ "default": [
+ "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",
+ "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",
+ "ECDHE-ECDSA-AES128-SHA",
+ "ECDHE-RSA-AES128-SHA",
+ "DHE-DSS-AES128-SHA",
+ "ECDH-ECDSA-AES128-SHA",
+ "ECDH-RSA-AES128-SHA",
+ "RSA-PSK-AES256-GCM-SHA384",
+ "RSA-PSK-AES256-CBC-SHA384",
+ "RSA-PSK-AES128-GCM-SHA256",
+ "RSA-PSK-AES128-CBC-SHA256",
+ "RSA-PSK-AES256-CBC-SHA",
+ "RSA-PSK-AES128-CBC-SHA"
+ ],
+ "description": "This config holds TLS cipher suite names separated by comma,\nor as an array of strings. e.g.\n\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n[\"TLS_AES_256_GCM_SHA384\",\"TLS_AES_128_GCM_SHA256\"]
.\n
\nCiphers (and their ordering) define the way in which the\nclient and server encrypts information over the network connection.\nSelecting a good cipher suite is critical for the\napplication's data security, confidentiality and performance.\n\nThe names should be in OpenSSL string format (not RFC format).\nAll default values and examples provided by EMQX config\ndocumentation are all in OpenSSL format.
\n\nNOTE: Certain cipher suites are only compatible with\nspecific TLS versions
('tlsv1.1', 'tlsv1.2' or 'tlsv1.3')\nincompatible cipher suites will be silently dropped.\nFor instance, if only 'tlsv1.3' is given in the versions
,\nconfiguring cipher suites for other versions will have no effect.\n
\n\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIf PSK cipher suites are intended, 'tlsv1.3' should be disabled from versions
.
\nPSK cipher suites: \"RSA-PSK-AES256-GCM-SHA384,RSA-PSK-AES256-CBC-SHA384,\nRSA-PSK-AES128-GCM-SHA256,RSA-PSK-AES128-CBC-SHA256,\nRSA-PSK-AES256-CBC-SHA,RSA-PSK-AES128-CBC-SHA,\nRSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "user_lookup_fun": {
+ "default": "emqx_tls_psk:lookup",
+ "type": "string"
+ },
+ "secure_renegotiate": {
+ "default": true,
+ "description": "\nSSL parameter renegotiation is a feature that allows a client and a server\nto renegotiate the parameters of the SSL connection on the fly.\nRFC 5746 defines a more secure way of doing this. By enabling secure renegotiation,\nyou drop support for the insecure renegotiation, prone to MitM attacks.\n",
+ "type": "boolean"
+ },
+ "server_name_indication": {
+ "description": "Specify the host name to be used in TLS Server Name Indication extension.
\nFor instance, when connecting to \"server.example.net\", the genuine server\nwhich accepts the connection and performs TLS handshake may differ from the\nhost the TLS client initially connects to, e.g. when connecting to an IP address\nor when the host has multiple resolvable DNS records
\nIf not specified, it will default to the host name string which is used\nto establish the connection, unless it is IP addressed used.
\nThe host name is then also used in the host name verification of the peer\ncertificate.
The special value 'disable' prevents the Server Name\nIndication extension from being sent and disables the hostname\nverification check.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "symbols": [
+ "disable"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_etcd": {
+ "properties": {
+ "server": {
+ "type": "comma_separated_string"
+ },
+ "prefix": {
+ "default": "emqxcl",
+ "type": "string"
+ },
+ "node_ttl": {
+ "default": "1m",
+ "type": "duration"
+ },
+ "ssl": {
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.flapping_detect": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "max_count": {
+ "default": 15,
+ "type": "number"
+ },
+ "window_time": {
+ "default": "1m",
+ "type": "duration"
+ },
+ "ban_time": {
+ "default": "5m",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.tcp_opts": {
+ "properties": {
+ "active_n": {
+ "default": 100,
+ "type": "number"
+ },
+ "backlog": {
+ "default": 1024,
+ "type": "number"
+ },
+ "send_timeout": {
+ "default": "15s",
+ "type": "duration"
+ },
+ "send_timeout_close": {
+ "default": true,
+ "type": "boolean"
+ },
+ "recbuf": {
+ "type": "byteSize"
+ },
+ "sndbuf": {
+ "type": "byteSize"
+ },
+ "buffer": {
+ "type": "byteSize"
+ },
+ "high_watermark": {
+ "default": "1MB",
+ "type": "byteSize"
+ },
+ "nodelay": {
+ "default": false,
+ "type": "boolean"
+ },
+ "reuseaddr": {
+ "default": true,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt_wss_listener": {
+ "required": [
+ "bind"
+ ],
+ "properties": {
+ "tcp": {
+ "$ref": "#/components/schemas/emqx_schema.tcp_opts"
+ },
+ "ssl": {
+ "$ref": "#/components/schemas/emqx_schema.listener_wss_opts"
+ },
+ "websocket": {
+ "$ref": "#/components/schemas/emqx_schema.ws_opts"
+ },
+ "bind": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "ip_port"
+ }
+ ]
+ },
+ "acceptors": {
+ "default": 16,
+ "type": "number"
+ },
+ "max_connections": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "mountpoint": {
+ "default": "",
+ "type": "string"
+ },
+ "zone": {
+ "default": "default",
+ "type": "string"
+ },
+ "limiter": {
+ "default": {},
+ "properties": {
+ "$ratelimit bucket's name": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "access_rules": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "proxy_protocol": {
+ "default": false,
+ "type": "boolean"
+ },
+ "proxy_protocol_timeout": {
+ "type": "duration"
+ },
+ "authentication": {
+ "description": "Per-listener authentication override\nAuthentication can be one single authenticator instance or a chain of authenticators as an array.\nWhen authenticating a login (username, client ID, etc.) the authenticators are checked\nin the configured order.
\n",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-scram-builtin_db.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.jwks"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.public-key"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.hmac-based"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.post"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.get"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.sentinel"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.sharded-cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.replica-set"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-postgresql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mysql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-builtin_db.authentication"
+ }
+ ]
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.persistent_session_store": {
+ "properties": {
+ "enabled": {
+ "default": false,
+ "type": "boolean"
+ },
+ "storage_type": {
+ "default": "disc",
+ "oneOf": [
+ {
+ "symbols": [
+ "disc"
+ ],
+ "type": "enum"
+ },
+ {
+ "symbols": [
+ "ram"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "max_retain_undelivered": {
+ "default": "1h",
+ "type": "duration"
+ },
+ "message_gc_interval": {
+ "default": "1h",
+ "type": "duration"
+ },
+ "session_message_gc_interval": {
+ "default": "1m",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "auto_subscribe.auto_subscribe": {
+ "properties": {
+ "topics": {
+ "items": {
+ "$ref": "#/components/schemas/auto_subscribe.topic"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "connector-http.request": {
+ "properties": {
+ "method": {
+ "symbols": [
+ "post",
+ "put",
+ "get",
+ "delete"
+ ],
+ "type": "enum"
+ },
+ "path": {
+ "type": "string"
+ },
+ "body": {
+ "type": "string"
+ },
+ "headers": {
+ "type": "string"
+ },
+ "request_timeout": {
+ "description": "The timeout when sending request to the HTTP server",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.overload_protection": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "description": "React on system overload or not",
+ "type": "boolean"
+ },
+ "backoff_delay": {
+ "default": 1,
+ "description": "Some unimportant tasks could be delayed for execution, here set the delays in ms",
+ "minimum": 0,
+ "type": "number"
+ },
+ "backoff_gc": {
+ "default": false,
+ "description": "Skip forceful GC if necessary",
+ "type": "boolean"
+ },
+ "backoff_hibernation": {
+ "default": true,
+ "description": "Skip process hibernation if necessary",
+ "type": "boolean"
+ },
+ "backoff_new_conn": {
+ "default": true,
+ "description": "Close new incoming connections if necessary",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.zone": {
+ "properties": {
+ "mqtt": {
+ "$ref": "#/components/schemas/zone.mqtt"
+ },
+ "stats": {
+ "$ref": "#/components/schemas/zone.stats"
+ },
+ "flapping_detect": {
+ "$ref": "#/components/schemas/zone.flapping_detect"
+ },
+ "force_shutdown": {
+ "$ref": "#/components/schemas/zone.force_shutdown"
+ },
+ "conn_congestion": {
+ "$ref": "#/components/schemas/zone.conn_congestion"
+ },
+ "rate_limit": {
+ "$ref": "#/components/schemas/zone.rate_limit"
+ },
+ "quota": {
+ "$ref": "#/components/schemas/zone.quota"
+ },
+ "force_gc": {
+ "$ref": "#/components/schemas/zone.force_gc"
+ },
+ "overload_protection": {
+ "$ref": "#/components/schemas/zone.overload_protection"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.listener_ssl_opts": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "cacertfile": {
+ "description": "Trusted PEM format CA certificates bundle file.
\nThe certificates in this file are used to verify the TLS peer's certificates.\nAppend new certificates to the file if new CAs are to be trusted.\nThere is no need to restart EMQX to have the updated file loaded, because\nthe system regularly checks if file has been updated (and reload).
\nNOTE: invalidating (deleting) a certificate from the file will not affect\nalready established connections.\n",
+ "type": "string"
+ },
+ "certfile": {
+ "description": "PEM format certificates chain file.
\nThe certificates in this file should be in reversed order of the certificate\nissue chain. That is, the host's certificate should be placed in the beginning\nof the file, followed by the immediate issuer certificate and so on.\nAlthough the root CA certificate is optional, it should be placed at the end of\nthe file if it is to be added.\n",
+ "type": "string"
+ },
+ "keyfile": {
+ "description": "PEM format private key file.
\n",
+ "type": "string"
+ },
+ "verify": {
+ "default": "verify_none",
+ "symbols": [
+ "verify_peer",
+ "verify_none"
+ ],
+ "type": "enum"
+ },
+ "reuse_sessions": {
+ "default": true,
+ "type": "boolean"
+ },
+ "depth": {
+ "default": 10,
+ "type": "number"
+ },
+ "password": {
+ "description": "String containing the user's password. Only used if the private\nkey file is password-protected.",
+ "type": "string"
+ },
+ "versions": {
+ "default": [
+ "tlsv1.3",
+ "tlsv1.2",
+ "tlsv1.1",
+ "tlsv1"
+ ],
+ "description": "All TLS/DTLS versions to be supported.
\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIn case PSK cipher suites are intended, make sure to configured\n['tlsv1.2', 'tlsv1.1']
here.\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "ciphers": {
+ "default": [
+ "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",
+ "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",
+ "ECDHE-ECDSA-AES128-SHA",
+ "ECDHE-RSA-AES128-SHA",
+ "DHE-DSS-AES128-SHA",
+ "ECDH-ECDSA-AES128-SHA",
+ "ECDH-RSA-AES128-SHA",
+ "RSA-PSK-AES256-GCM-SHA384",
+ "RSA-PSK-AES256-CBC-SHA384",
+ "RSA-PSK-AES128-GCM-SHA256",
+ "RSA-PSK-AES128-CBC-SHA256",
+ "RSA-PSK-AES256-CBC-SHA",
+ "RSA-PSK-AES128-CBC-SHA"
+ ],
+ "description": "This config holds TLS cipher suite names separated by comma,\nor as an array of strings. e.g.\n\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n[\"TLS_AES_256_GCM_SHA384\",\"TLS_AES_128_GCM_SHA256\"]
.\n
\nCiphers (and their ordering) define the way in which the\nclient and server encrypts information over the network connection.\nSelecting a good cipher suite is critical for the\napplication's data security, confidentiality and performance.\n\nThe names should be in OpenSSL string format (not RFC format).\nAll default values and examples provided by EMQX config\ndocumentation are all in OpenSSL format.
\n\nNOTE: Certain cipher suites are only compatible with\nspecific TLS versions
('tlsv1.1', 'tlsv1.2' or 'tlsv1.3')\nincompatible cipher suites will be silently dropped.\nFor instance, if only 'tlsv1.3' is given in the versions
,\nconfiguring cipher suites for other versions will have no effect.\n
\n\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIf PSK cipher suites are intended, 'tlsv1.3' should be disabled from versions
.
\nPSK cipher suites: \"RSA-PSK-AES256-GCM-SHA384,RSA-PSK-AES256-CBC-SHA384,\nRSA-PSK-AES128-GCM-SHA256,RSA-PSK-AES128-CBC-SHA256,\nRSA-PSK-AES256-CBC-SHA,RSA-PSK-AES128-CBC-SHA,\nRSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "user_lookup_fun": {
+ "default": "emqx_tls_psk:lookup",
+ "type": "string"
+ },
+ "secure_renegotiate": {
+ "default": true,
+ "description": "\nSSL parameter renegotiation is a feature that allows a client and a server\nto renegotiate the parameters of the SSL connection on the fly.\nRFC 5746 defines a more secure way of doing this. By enabling secure renegotiation,\nyou drop support for the insecure renegotiation, prone to MitM attacks.\n",
+ "type": "boolean"
+ },
+ "dhfile": {
+ "description": "Path to a file containing PEM-encoded Diffie Hellman parameters\nto be used by the server if a cipher suite using Diffie Hellman\nkey exchange is negotiated. If not specified, default parameters\nare used.
\nNOTE: The dhfile
option is not supported by TLS 1.3.",
+ "type": "string"
+ },
+ "fail_if_no_peer_cert": {
+ "default": false,
+ "description": "\nUsed together with {verify, verify_peer} by an TLS/DTLS server.\nIf set to true, the server fails if the client does not have a\ncertificate to send, that is, sends an empty certificate.\nIf set to false, it fails only if the client sends an invalid\ncertificate (an empty certificate is considered valid).\n",
+ "type": "boolean"
+ },
+ "honor_cipher_order": {
+ "default": true,
+ "type": "boolean"
+ },
+ "client_renegotiation": {
+ "default": true,
+ "description": "\nIn protocols that support client-initiated renegotiation,\nthe cost of resources of such an operation is higher for the server than the client.\nThis can act as a vector for denial of service attacks.\nThe SSL application already takes measures to counter-act such attempts,\nbut client-initiated renegotiation can be strictly disabled by setting this option to false.\nThe default value is true. Note that disabling renegotiation can result in\nlong-lived connections becoming unusable due to limits on\nthe number of messages the underlying cipher suite can encipher.\n",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.trace": {
+ "properties": {
+ "payload_encode": {
+ "default": "text",
+ "description": "\nDetermine the format of the payload format in the trace file.
\n`text`: Text-based protocol or plain text protocol. It is recommended when payload is JSON encoded.
\n`hex`: Binary hexadecimal encode. It is recommended when payload is a custom binary protocol.
\n`hidden`: payload is obfuscated as `******`\n ",
+ "symbols": [
+ "hex",
+ "text",
+ "hidden"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.deflate_opts": {
+ "properties": {
+ "level": {
+ "symbols": [
+ "none",
+ "default",
+ "best_compression",
+ "best_speed"
+ ],
+ "type": "enum"
+ },
+ "mem_level": {
+ "default": 8,
+ "maximum": 9,
+ "minimum": 1,
+ "type": "number"
+ },
+ "strategy": {
+ "symbols": [
+ "default",
+ "filtered",
+ "huffman_only",
+ "rle"
+ ],
+ "type": "enum"
+ },
+ "server_context_takeover": {
+ "symbols": [
+ "takeover",
+ "no_takeover"
+ ],
+ "type": "enum"
+ },
+ "client_context_takeover": {
+ "symbols": [
+ "takeover",
+ "no_takeover"
+ ],
+ "type": "enum"
+ },
+ "server_max_window_bits": {
+ "default": 15,
+ "maximum": 15,
+ "minimum": 8,
+ "type": "number"
+ },
+ "client_max_window_bits": {
+ "default": 15,
+ "maximum": 15,
+ "minimum": 8,
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.log_burst_limit": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "max_count": {
+ "default": 10000,
+ "type": "number"
+ },
+ "window_time": {
+ "default": "1s",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "zone.rate_limit": {
+ "properties": {
+ "max_conn_rate": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "conn_messages_in": {
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "conn_bytes_in": {
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.sysmon_os": {
+ "properties": {
+ "cpu_check_interval": {
+ "default": "60s",
+ "type": "duration"
+ },
+ "cpu_high_watermark": {
+ "default": "80%",
+ "type": "percent"
+ },
+ "cpu_low_watermark": {
+ "default": "60%",
+ "type": "percent"
+ },
+ "mem_check_interval": {
+ "default": "60s",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "sysmem_high_watermark": {
+ "default": "70%",
+ "type": "percent"
+ },
+ "procmem_high_watermark": {
+ "default": "5%",
+ "type": "percent"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_k8s": {
+ "properties": {
+ "apiserver": {
+ "type": "string"
+ },
+ "service_name": {
+ "default": "emqx",
+ "type": "string"
+ },
+ "address_type": {
+ "symbols": [
+ "ip",
+ "dns",
+ "hostname"
+ ],
+ "type": "enum"
+ },
+ "app_name": {
+ "default": "emqx",
+ "type": "string"
+ },
+ "namespace": {
+ "default": "default",
+ "type": "string"
+ },
+ "suffix": {
+ "default": "pod.local",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "statsd.statsd": {
+ "required": [
+ "flush_time_interval",
+ "sample_time_interval",
+ "server",
+ "enable"
+ ],
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "server": {
+ "default": "127.0.0.1:8125",
+ "type": "ip_port"
+ },
+ "sample_time_interval": {
+ "default": "10s",
+ "type": "duration"
+ },
+ "flush_time_interval": {
+ "default": "10s",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt_ssl_listener": {
+ "required": [
+ "bind"
+ ],
+ "properties": {
+ "tcp": {
+ "$ref": "#/components/schemas/emqx_schema.tcp_opts"
+ },
+ "ssl": {
+ "$ref": "#/components/schemas/emqx_schema.listener_ssl_opts"
+ },
+ "bind": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "ip_port"
+ }
+ ]
+ },
+ "acceptors": {
+ "default": 16,
+ "type": "number"
+ },
+ "max_connections": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "mountpoint": {
+ "default": "",
+ "type": "string"
+ },
+ "zone": {
+ "default": "default",
+ "type": "string"
+ },
+ "limiter": {
+ "default": {},
+ "properties": {
+ "$ratelimit bucket's name": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "access_rules": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "proxy_protocol": {
+ "default": false,
+ "type": "boolean"
+ },
+ "proxy_protocol_timeout": {
+ "type": "duration"
+ },
+ "authentication": {
+ "description": "Per-listener authentication override\nAuthentication can be one single authenticator instance or a chain of authenticators as an array.\nWhen authenticating a login (username, client ID, etc.) the authenticators are checked\nin the configured order.
\n",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-scram-builtin_db.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.jwks"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.public-key"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.hmac-based"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.post"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.get"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.sentinel"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.sharded-cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.replica-set"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-postgresql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mysql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-builtin_db.authentication"
+ }
+ ]
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "retainer.mnesia_config": {
+ "properties": {
+ "type": {
+ "oneOf": [
+ {
+ "symbols": [
+ "built_in_database"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "storage_type": {
+ "default": "ram",
+ "oneOf": [
+ {
+ "symbols": [
+ "disc"
+ ],
+ "type": "enum"
+ },
+ {
+ "symbols": [
+ "ram"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "max_retained_messages": {
+ "default": 0,
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "zone.quota": {
+ "properties": {
+ "conn_messages_routing": {
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "overall_messages_routing": {
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.console_handler": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "level": {
+ "default": "warning",
+ "description": "Global log level. This includes the primary log level and all log handlers.",
+ "symbols": [
+ "debug",
+ "info",
+ "notice",
+ "warning",
+ "error",
+ "critical",
+ "alert",
+ "emergency",
+ "all"
+ ],
+ "type": "enum"
+ },
+ "time_offset": {
+ "default": "system",
+ "type": "string"
+ },
+ "chars_limit": {
+ "default": "unlimited",
+ "description": "Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.",
+ "oneOf": [
+ {
+ "minimum": 1,
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "unlimited"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "formatter": {
+ "default": "text",
+ "description": "Choose log format. text
for free text, and json
for structured logging.",
+ "symbols": [
+ "text",
+ "json"
+ ],
+ "type": "enum"
+ },
+ "single_line": {
+ "default": true,
+ "description": "Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.",
+ "type": "boolean"
+ },
+ "sync_mode_qlen": {
+ "default": 100,
+ "type": "number"
+ },
+ "drop_mode_qlen": {
+ "default": 3000,
+ "type": "number"
+ },
+ "flush_qlen": {
+ "default": 8000,
+ "type": "number"
+ },
+ "overload_kill": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_overload_kill"
+ },
+ "burst_limit": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_burst_limit"
+ },
+ "supervisor_reports": {
+ "default": "error",
+ "symbols": [
+ "error",
+ "progress"
+ ],
+ "type": "enum"
+ },
+ "max_depth": {
+ "default": 100,
+ "description": "Maximum depth for Erlang term log formatting and Erlang process message queue inspection.",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "unlimited"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt": {
+ "properties": {
+ "idle_timeout": {
+ "default": "15s",
+ "description": "Close TCP connections from the clients that have not sent MQTT CONNECT\nmessage within this interval.",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "max_packet_size": {
+ "default": "1MB",
+ "description": "Maximum MQTT packet size allowed.",
+ "type": "byteSize"
+ },
+ "max_clientid_len": {
+ "default": 65535,
+ "description": "Maximum allowed length of MQTT clientId.",
+ "maximum": 65535,
+ "minimum": 23,
+ "type": "number"
+ },
+ "max_topic_levels": {
+ "default": 65535,
+ "description": "Maximum topic levels allowed.",
+ "maximum": 65535,
+ "minimum": 1,
+ "type": "number"
+ },
+ "max_qos_allowed": {
+ "default": 2,
+ "description": "Maximum QoS allowed.",
+ "symbols": [
+ 0,
+ 1,
+ 2
+ ],
+ "type": "enum"
+ },
+ "max_topic_alias": {
+ "default": 65535,
+ "description": "Maximum Topic Alias, 0 means no topic alias supported.",
+ "maximum": 65535,
+ "minimum": 0,
+ "type": "number"
+ },
+ "retain_available": {
+ "default": true,
+ "description": "Support MQTT retained messages.",
+ "type": "boolean"
+ },
+ "wildcard_subscription": {
+ "default": true,
+ "description": "Support MQTT Wildcard Subscriptions.",
+ "type": "boolean"
+ },
+ "shared_subscription": {
+ "default": true,
+ "description": "Support MQTT Shared Subscriptions.",
+ "type": "boolean"
+ },
+ "ignore_loop_deliver": {
+ "default": false,
+ "description": "Ignore loop delivery of messages for MQTT v3.1.1.",
+ "type": "boolean"
+ },
+ "strict_mode": {
+ "default": false,
+ "description": "Parse the MQTT frame in strict mode.",
+ "type": "boolean"
+ },
+ "response_information": {
+ "default": "",
+ "description": "Specify the response information returned to the client\nThis feature is disabled if is set to \"\".",
+ "type": "string"
+ },
+ "server_keepalive": {
+ "default": "disabled",
+ "description": "'Server Keep Alive' of MQTT 5.0.\nIf the server returns a 'Server Keep Alive' in the CONNACK packet,\nthe client MUST use that value instead of the value it sent as the 'Keep Alive'.",
+ "oneOf": [
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "keepalive_backoff": {
+ "default": 0.75,
+ "description": "The backoff for MQTT keepalive timeout. The broker will close the connection\nafter idling for 'Keepalive * backoff * 2'.",
+ "type": "number"
+ },
+ "max_subscriptions": {
+ "default": "infinity",
+ "description": "Maximum number of subscriptions allowed.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "minimum": 1,
+ "type": "number"
+ }
+ ]
+ },
+ "upgrade_qos": {
+ "default": false,
+ "description": "Force upgrade of QoS level according to subscription.",
+ "type": "boolean"
+ },
+ "max_inflight": {
+ "default": 32,
+ "description": "Maximum size of the Inflight Window storing QoS1/2 messages delivered but un-acked.",
+ "maximum": 65535,
+ "minimum": 1,
+ "type": "number"
+ },
+ "retry_interval": {
+ "default": "30s",
+ "description": "Retry interval for QoS1/2 message delivering.",
+ "type": "duration"
+ },
+ "max_awaiting_rel": {
+ "default": 100,
+ "description": "Maximum QoS2 packets (Client -> Broker) awaiting PUBREL.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "await_rel_timeout": {
+ "default": "300s",
+ "description": "The QoS2 messages (Client -> Broker) will be dropped if awaiting PUBREL timeout.",
+ "type": "duration"
+ },
+ "session_expiry_interval": {
+ "default": "2h",
+ "description": "Default session expiry interval for MQTT V3.1.1 connections.",
+ "type": "duration"
+ },
+ "max_mqueue_len": {
+ "default": 1000,
+ "description": "Maximum queue length. Enqueued messages when persistent client disconnected,\nor inflight window is full.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "minimum": 0,
+ "type": "number"
+ }
+ ]
+ },
+ "mqueue_priorities": {
+ "default": "disabled",
+ "description": "Topic priorities.
\nThere's no priority table by default, hence all messages are treated equal.
\nPriority number [1-255]
\n\n**NOTE**: Comma and equal signs are not allowed for priority topic names.
\n**NOTE**: Messages for topics not in the priority table are treated as\neither highest or lowest priority depending on the configured value for\nmqtt.mqueue_default_priority
.\n
\n**Examples**:\nTo configure \"topic/1\" > \"topic/2\"
:
\nmqueue_priorities: {\"topic/1\": 10, \"topic/2\": 8}
",
+ "oneOf": [
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "mqueue_default_priority": {
+ "default": "lowest",
+ "description": "Default to the highest priority for topics not matching priority table.",
+ "symbols": [
+ "highest",
+ "lowest"
+ ],
+ "type": "enum"
+ },
+ "mqueue_store_qos0": {
+ "default": true,
+ "description": "Support enqueue QoS0 messages.",
+ "type": "boolean"
+ },
+ "use_username_as_clientid": {
+ "default": false,
+ "description": "Replace client ID with the username.",
+ "type": "boolean"
+ },
+ "peer_cert_as_username": {
+ "default": "disabled",
+ "description": "Use the CN, DN or CRT field from the client certificate as a username.\nOnly works for the TLS connection.",
+ "symbols": [
+ "disabled",
+ "cn",
+ "dn",
+ "crt",
+ "pem",
+ "md5"
+ ],
+ "type": "enum"
+ },
+ "peer_cert_as_clientid": {
+ "default": "disabled",
+ "description": "Use the CN, DN or CRT field from the client certificate as a clientid.\nOnly works for the TLS connection.",
+ "symbols": [
+ "disabled",
+ "cn",
+ "dn",
+ "crt",
+ "pem",
+ "md5"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "limiter.rate_burst": {
+ "properties": {
+ "rate": {
+ "type": "string"
+ },
+ "burst": {
+ "default": "0/0s",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "authn-hash.bcrypt_rw": {
+ "properties": {
+ "name": {
+ "symbols": [
+ "bcrypt"
+ ],
+ "type": "enum"
+ },
+ "salt_rounds": {
+ "default": 10,
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "authn-http.post": {
+ "required": [
+ "url",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "method": {
+ "default": "post",
+ "symbols": [
+ "post"
+ ],
+ "type": "enum"
+ },
+ "headers": {
+ "default": {
+ "accept": "application/json",
+ "cache-control": "no-cache",
+ "connection": "keep-alive",
+ "content-type": "application/json",
+ "keep-alive": "timeout=30, max=1000"
+ },
+ "type": "string"
+ },
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "http"
+ ],
+ "type": "enum"
+ },
+ "url": {
+ "type": "string"
+ },
+ "body": {
+ "type": "string"
+ },
+ "request_timeout": {
+ "default": "5s",
+ "type": "duration"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "connect_timeout": {
+ "default": "15s",
+ "description": "The timeout when connecting to the HTTP server",
+ "type": "duration"
+ },
+ "enable_pipelining": {
+ "default": true,
+ "description": "Enable the HTTP pipeline",
+ "type": "boolean"
+ },
+ "max_retries": {
+ "default": 5,
+ "description": "Max retry times if error on sending request",
+ "minimum": 1,
+ "type": "number"
+ },
+ "pool_size": {
+ "default": 8,
+ "description": "The pool size",
+ "minimum": 1,
+ "type": "number"
+ },
+ "request": {
+ "description": "\nIf the request is provided, the caller can send HTTP requests via\nemqx_resource:query(ResourceId, {send_message, BridgeId, Message})
\n",
+ "$ref": "#/components/schemas/connector-http.request"
+ },
+ "retry_interval": {
+ "default": "1s",
+ "description": "Interval before next retry if error on sending request",
+ "type": "duration"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.sysmon_vm": {
+ "properties": {
+ "process_check_interval": {
+ "default": "30s",
+ "type": "duration"
+ },
+ "process_high_watermark": {
+ "default": "80%",
+ "type": "percent"
+ },
+ "process_low_watermark": {
+ "default": "60%",
+ "type": "percent"
+ },
+ "long_gc": {
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "long_schedule": {
+ "default": "240ms",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "large_heap": {
+ "default": "32MB",
+ "oneOf": [
+ {
+ "type": "byteSize"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "busy_dist_port": {
+ "default": true,
+ "type": "boolean"
+ },
+ "busy_port": {
+ "default": true,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "zone.force_gc": {
+ "properties": {
+ "enable": {
+ "type": "boolean"
+ },
+ "count": {
+ "description": "GC the process after this many received messages.",
+ "minimum": 0,
+ "type": "number"
+ },
+ "bytes": {
+ "description": "GC the process after specified number of bytes have passed through.",
+ "type": "byteSize"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_dns": {
+ "properties": {
+ "name": {
+ "default": "localhost",
+ "type": "string"
+ },
+ "app": {
+ "default": "emqx",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "modules.delayed": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "max_delayed_messages": {
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_connector_mongo.topology": {
+ "properties": {
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "max_overflow": {
+ "default": 8,
+ "type": "number"
+ },
+ "overflow_ttl": {
+ "type": "duration"
+ },
+ "overflow_check_period": {
+ "type": "duration"
+ },
+ "local_threshold_ms": {
+ "type": "duration"
+ },
+ "connect_timeout_ms": {
+ "type": "duration"
+ },
+ "socket_timeout_ms": {
+ "type": "duration"
+ },
+ "server_selection_timeout_ms": {
+ "type": "duration"
+ },
+ "wait_queue_timeout_ms": {
+ "type": "duration"
+ },
+ "heartbeat_frequency_ms": {
+ "type": "duration"
+ },
+ "min_heartbeat_frequency_ms": {
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "retainer.flow_control": {
+ "properties": {
+ "max_read_number": {
+ "default": 0,
+ "type": "number"
+ },
+ "msg_deliver_quota": {
+ "default": 0,
+ "type": "number"
+ },
+ "quota_release_interval": {
+ "default": "0ms",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "authn-redis.cluster": {
+ "required": [
+ "servers",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "redis"
+ ],
+ "type": "enum"
+ },
+ "cmd": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "servers": {
+ "description": "A Node list for Cluster to connect to. The nodes should be split with ',', such as: 'Node[,Node]'
\nFor each Node should be:
\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe Redis default port 6379 is used if '[:Port]' isn't present",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "redis_type": {
+ "default": "cluster",
+ "symbols": [
+ "cluster"
+ ],
+ "type": "enum"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "password": {
+ "type": "string"
+ },
+ "database": {
+ "default": 0,
+ "type": "number"
+ },
+ "auto_reconnect": {
+ "default": true,
+ "type": "boolean"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.ws_opts": {
+ "properties": {
+ "mqtt_path": {
+ "default": "/mqtt",
+ "type": "string"
+ },
+ "mqtt_piggyback": {
+ "default": "multiple",
+ "symbols": [
+ "single",
+ "multiple"
+ ],
+ "type": "enum"
+ },
+ "compress": {
+ "default": false,
+ "type": "boolean"
+ },
+ "idle_timeout": {
+ "default": "15s",
+ "type": "duration"
+ },
+ "max_frame_size": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "fail_if_no_subprotocol": {
+ "default": true,
+ "type": "boolean"
+ },
+ "supported_subprotocols": {
+ "default": "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5",
+ "type": "comma_separated_string"
+ },
+ "check_origin_enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "allow_origin_absence": {
+ "default": true,
+ "type": "boolean"
+ },
+ "check_origins": {
+ "default": "",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "proxy_address_header": {
+ "default": "x-forwarded-for",
+ "type": "string"
+ },
+ "proxy_port_header": {
+ "default": "x-forwarded-port",
+ "type": "string"
+ },
+ "deflate_opts": {
+ "$ref": "#/components/schemas/emqx_schema.deflate_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.log_file_handler": {
+ "properties": {
+ "file": {
+ "type": "string"
+ },
+ "rotation": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_rotation"
+ },
+ "max_size": {
+ "default": "10MB",
+ "oneOf": [
+ {
+ "type": "byteSize"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "level": {
+ "default": "warning",
+ "description": "Global log level. This includes the primary log level and all log handlers.",
+ "symbols": [
+ "debug",
+ "info",
+ "notice",
+ "warning",
+ "error",
+ "critical",
+ "alert",
+ "emergency",
+ "all"
+ ],
+ "type": "enum"
+ },
+ "time_offset": {
+ "default": "system",
+ "type": "string"
+ },
+ "chars_limit": {
+ "default": "unlimited",
+ "description": "Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.",
+ "oneOf": [
+ {
+ "minimum": 1,
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "unlimited"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "formatter": {
+ "default": "text",
+ "description": "Choose log format. text
for free text, and json
for structured logging.",
+ "symbols": [
+ "text",
+ "json"
+ ],
+ "type": "enum"
+ },
+ "single_line": {
+ "default": true,
+ "description": "Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.",
+ "type": "boolean"
+ },
+ "sync_mode_qlen": {
+ "default": 100,
+ "type": "number"
+ },
+ "drop_mode_qlen": {
+ "default": 3000,
+ "type": "number"
+ },
+ "flush_qlen": {
+ "default": 8000,
+ "type": "number"
+ },
+ "overload_kill": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_overload_kill"
+ },
+ "burst_limit": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_burst_limit"
+ },
+ "supervisor_reports": {
+ "default": "error",
+ "symbols": [
+ "error",
+ "progress"
+ ],
+ "type": "enum"
+ },
+ "max_depth": {
+ "default": 100,
+ "description": "Maximum depth for Erlang term log formatting and Erlang process message queue inspection.",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "unlimited"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "retainer.retainer": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "msg_expiry_interval": {
+ "default": "0s",
+ "type": "duration"
+ },
+ "msg_clear_interval": {
+ "default": "0s",
+ "type": "duration"
+ },
+ "flow_control": {
+ "$ref": "#/components/schemas/retainer.flow_control"
+ },
+ "max_payload_size": {
+ "default": "1MB",
+ "type": "byteSize"
+ },
+ "stop_publish_clear_msg": {
+ "default": false,
+ "type": "boolean"
+ },
+ "config": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/retainer.mnesia_config"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "authn-jwt.hmac-based": {
+ "required": [
+ "mechanism"
+ ],
+ "properties": {
+ "use_jwks": {
+ "symbols": [
+ false
+ ],
+ "type": "enum"
+ },
+ "algorithm": {
+ "symbols": [
+ "hmac-based"
+ ],
+ "type": "enum"
+ },
+ "secret": {
+ "type": "string"
+ },
+ "secret_base64_encoded": {
+ "default": false,
+ "type": "boolean"
+ },
+ "mechanism": {
+ "symbols": [
+ "jwt"
+ ],
+ "type": "enum"
+ },
+ "verify_claims": {
+ "default": {},
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "zone.flapping_detect": {
+ "properties": {
+ "enable": {
+ "type": "boolean"
+ },
+ "max_count": {
+ "type": "number"
+ },
+ "window_time": {
+ "type": "duration"
+ },
+ "ban_time": {
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "zone.stats": {
+ "properties": {
+ "enable": {
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "authn-mongodb.replica-set": {
+ "required": [
+ "database",
+ "servers",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "mongodb"
+ ],
+ "type": "enum"
+ },
+ "collection": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "password_hash_field": {
+ "type": "string"
+ },
+ "salt_field": {
+ "type": "string"
+ },
+ "is_superuser_field": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "mongo_type": {
+ "default": "rs",
+ "symbols": [
+ "rs"
+ ],
+ "type": "enum"
+ },
+ "servers": {
+ "description": "A Node list for Cluster to connect to. The nodes should be split with ',', such as: 'Node[,Node]'
\nFor each Node should be:
\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe MongoDB default port 27017 is used if '[:Port]' isn't present",
+ "type": "string"
+ },
+ "w_mode": {
+ "default": "unsafe",
+ "symbols": [
+ "unsafe",
+ "safe"
+ ],
+ "type": "enum"
+ },
+ "r_mode": {
+ "default": "master",
+ "symbols": [
+ "master",
+ "slave_ok"
+ ],
+ "type": "enum"
+ },
+ "replica_set_name": {
+ "type": "string"
+ },
+ "srv_record": {
+ "default": false,
+ "type": "boolean"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "auth_source": {
+ "type": "string"
+ },
+ "database": {
+ "type": "string"
+ },
+ "topology": {
+ "$ref": "#/components/schemas/emqx_connector_mongo.topology"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.stats": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.log_overload_kill": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "mem_size": {
+ "default": "30MB",
+ "type": "byteSize"
+ },
+ "qlen": {
+ "default": 20000,
+ "type": "number"
+ },
+ "restart_after": {
+ "default": "5s",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "duration"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.rate_limit": {
+ "properties": {
+ "max_conn_rate": {
+ "default": 1000,
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "conn_messages_in": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "conn_bytes_in": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.sysmon_top": {
+ "properties": {
+ "num_items": {
+ "default": 10,
+ "description": "The number of top processes per monitoring group",
+ "minimum": 1,
+ "type": "number"
+ },
+ "sample_interval": {
+ "default": "2s",
+ "description": "Specifies how often process top should be collected",
+ "type": "duration"
+ },
+ "max_procs": {
+ "default": 1000000,
+ "description": "Stop collecting data when the number of processes\nin the VM exceeds this value",
+ "minimum": 1,
+ "type": "number"
+ },
+ "db_hostname": {
+ "default": "",
+ "description": "Hostname of the PostgreSQL database that collects the data points",
+ "type": "string"
+ },
+ "db_port": {
+ "default": 5432,
+ "description": "Port of the PostgreSQL database that collects the data points",
+ "type": "number"
+ },
+ "db_username": {
+ "default": "system_monitor",
+ "description": "EMQX username in the PostgreSQL database",
+ "type": "string"
+ },
+ "db_password": {
+ "default": "system_monitor_password",
+ "description": "EMQX user password in the PostgreSQL database",
+ "type": "string"
+ },
+ "db_name": {
+ "default": "postgres",
+ "description": "PostgreSQL database name",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "authn-redis.standalone": {
+ "required": [
+ "server",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "redis"
+ ],
+ "type": "enum"
+ },
+ "cmd": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "server": {
+ "description": "\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe Redis default port 6379 is used if '[:Port]' isn't present",
+ "type": "ip_port"
+ },
+ "redis_type": {
+ "default": "single",
+ "symbols": [
+ "single"
+ ],
+ "type": "enum"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "password": {
+ "type": "string"
+ },
+ "database": {
+ "default": 0,
+ "type": "number"
+ },
+ "auto_reconnect": {
+ "default": true,
+ "type": "boolean"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "authn-jwt.public-key": {
+ "required": [
+ "mechanism"
+ ],
+ "properties": {
+ "use_jwks": {
+ "symbols": [
+ false
+ ],
+ "type": "enum"
+ },
+ "algorithm": {
+ "symbols": [
+ "public-key"
+ ],
+ "type": "enum"
+ },
+ "certificate": {
+ "type": "string"
+ },
+ "mechanism": {
+ "symbols": [
+ "jwt"
+ ],
+ "type": "enum"
+ },
+ "verify_claims": {
+ "default": {},
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_static": {
+ "properties": {
+ "seeds": {
+ "default": "",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "authn-redis.sentinel": {
+ "required": [
+ "servers",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "redis"
+ ],
+ "type": "enum"
+ },
+ "cmd": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "servers": {
+ "description": "A Node list for Cluster to connect to. The nodes should be split with ',', such as: 'Node[,Node]'
\nFor each Node should be:
\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe Redis default port 6379 is used if '[:Port]' isn't present",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "redis_type": {
+ "default": "sentinel",
+ "symbols": [
+ "sentinel"
+ ],
+ "type": "enum"
+ },
+ "sentinel": {
+ "type": "string"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "password": {
+ "type": "string"
+ },
+ "database": {
+ "default": 0,
+ "type": "number"
+ },
+ "auto_reconnect": {
+ "default": true,
+ "type": "boolean"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_call": {
+ "properties": {
+ "retry_interval": {
+ "default": "1s",
+ "description": "Time interval to retry after a failed call.",
+ "type": "duration"
+ },
+ "max_history": {
+ "default": 100,
+ "description": "Retain the maximum number of completed transactions (for queries).",
+ "maximum": 500,
+ "minimum": 1,
+ "type": "number"
+ },
+ "cleanup_interval": {
+ "default": "5m",
+ "description": "Time interval to clear completed but stale transactions.\nEnsure that the number of completed transactions is less than the max_history.",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "zone.overload_protection": {
+ "properties": {
+ "enable": {
+ "description": "React on system overload or not",
+ "type": "boolean"
+ },
+ "backoff_delay": {
+ "description": "Some unimportant tasks could be delayed for execution, here set the delays in ms",
+ "minimum": 0,
+ "type": "number"
+ },
+ "backoff_gc": {
+ "description": "Skip forceful GC if necessary",
+ "type": "boolean"
+ },
+ "backoff_hibernation": {
+ "description": "Skip process hibernation if necessary",
+ "type": "boolean"
+ },
+ "backoff_new_conn": {
+ "description": "Close new incoming connections if necessary",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "configuration.cluster": {
+ "properties": {
+ "name": {
+ "default": "emqxcl",
+ "type": "string"
+ },
+ "discovery_strategy": {
+ "default": "manual",
+ "symbols": [
+ "manual",
+ "static",
+ "mcast",
+ "dns",
+ "etcd",
+ "k8s"
+ ],
+ "type": "enum"
+ },
+ "autoclean": {
+ "default": "5m",
+ "type": "duration"
+ },
+ "autoheal": {
+ "default": true,
+ "type": "boolean"
+ },
+ "static": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_static"
+ },
+ "mcast": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_mcast"
+ },
+ "proto_dist": {
+ "default": "inet_tcp",
+ "symbols": [
+ "inet_tcp",
+ "inet6_tcp",
+ "inet_tls"
+ ],
+ "type": "enum"
+ },
+ "dns": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_dns"
+ },
+ "etcd": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_etcd"
+ },
+ "k8s": {
+ "$ref": "#/components/schemas/emqx_conf_schema.cluster_k8s"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.force_gc": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "count": {
+ "default": 16000,
+ "description": "GC the process after this many received messages.",
+ "minimum": 0,
+ "type": "number"
+ },
+ "bytes": {
+ "default": "16MB",
+ "description": "GC the process after specified number of bytes have passed through.",
+ "type": "byteSize"
+ }
+ },
+ "type": "object"
+ },
+ "authn-hash.other_algorithms": {
+ "properties": {
+ "name": {
+ "symbols": [
+ "plain",
+ "md5",
+ "sha",
+ "sha256",
+ "sha512"
+ ],
+ "type": "enum"
+ },
+ "salt_position": {
+ "default": "prefix",
+ "symbols": [
+ "prefix",
+ "suffix"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "modules.topic_metrics": {
+ "properties": {
+ "topic": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "authn-http.get": {
+ "required": [
+ "url",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "method": {
+ "default": "post",
+ "symbols": [
+ "get"
+ ],
+ "type": "enum"
+ },
+ "headers": {
+ "default": {
+ "accept": "application/json",
+ "cache-control": "no-cache",
+ "connection": "keep-alive",
+ "keep-alive": "timeout=30, max=1000"
+ },
+ "type": "string"
+ },
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "http"
+ ],
+ "type": "enum"
+ },
+ "url": {
+ "type": "string"
+ },
+ "body": {
+ "type": "string"
+ },
+ "request_timeout": {
+ "default": "5s",
+ "type": "duration"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "connect_timeout": {
+ "default": "15s",
+ "description": "The timeout when connecting to the HTTP server",
+ "type": "duration"
+ },
+ "enable_pipelining": {
+ "default": true,
+ "description": "Enable the HTTP pipeline",
+ "type": "boolean"
+ },
+ "max_retries": {
+ "default": 5,
+ "description": "Max retry times if error on sending request",
+ "minimum": 1,
+ "type": "number"
+ },
+ "pool_size": {
+ "default": 8,
+ "description": "The pool size",
+ "minimum": 1,
+ "type": "number"
+ },
+ "request": {
+ "description": "\nIf the request is provided, the caller can send HTTP requests via\nemqx_resource:query(ResourceId, {send_message, BridgeId, Message})
\n",
+ "$ref": "#/components/schemas/connector-http.request"
+ },
+ "retry_interval": {
+ "default": "1s",
+ "description": "Interval before next retry if error on sending request",
+ "type": "duration"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "limiter.client_bucket": {
+ "properties": {
+ "rate": {
+ "type": "string"
+ },
+ "initial": {
+ "default": "0",
+ "type": "string"
+ },
+ "low_water_mark": {
+ "default": "0",
+ "description": "If the remaining tokens are lower than this value,\nthe check/consume will succeed, but it will be forced to wait for a short period of time.",
+ "type": "string"
+ },
+ "capacity": {
+ "description": "The capacity of the token bucket.",
+ "type": "string"
+ },
+ "divisible": {
+ "default": false,
+ "description": "Is it possible to split the number of requested tokens?",
+ "type": "boolean"
+ },
+ "max_retry_time": {
+ "default": "5s",
+ "description": "The maximum retry time when acquire failed.",
+ "type": "duration"
+ },
+ "failure_strategy": {
+ "default": "force",
+ "description": "The strategy when all the retries failed.",
+ "symbols": [
+ "force",
+ "drop",
+ "throw"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "authn-postgresql.authentication": {
+ "required": [
+ "database",
+ "server",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "postgresql"
+ ],
+ "type": "enum"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "query": {
+ "type": "string"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "server": {
+ "description": "\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe PostgreSQL default port 5432 is used if '[:Port]' isn't present",
+ "type": "ip_port"
+ },
+ "database": {
+ "type": "string"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "auto_reconnect": {
+ "default": true,
+ "type": "boolean"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.alarm": {
+ "properties": {
+ "actions": {
+ "default": [
+ "log",
+ "publish"
+ ],
+ "description": "The actions triggered when the alarm is activated.
\nCurrently, the following actions are supported: log
and publish
.\nlog
is to write the alarm to log (console or file).\npublish
is to publish the alarm as an MQTT message to the system topics:\n$SYS/brokers/emqx@xx.xx.xx.x/alarms/activate
and\n$SYS/brokers/emqx@xx.xx.xx.x/alarms/deactivate
",
+ "example": [
+ "log",
+ "publish"
+ ],
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "size_limit": {
+ "default": 1000,
+ "description": "The maximum total number of deactivated alarms to keep as history.
\nWhen this limit is exceeded, the oldest deactivated alarms are deleted to cap the total number.\n",
+ "example": 1000,
+ "maximum": 3000,
+ "minimum": 1,
+ "type": "number"
+ },
+ "validity_period": {
+ "default": "24h",
+ "description": "Retention time of deactivated alarms. Alarms are not deleted immediately\nwhen deactivated, but after the retention time.\n",
+ "example": "24h",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "authn-jwt.jwks": {
+ "required": [
+ "mechanism"
+ ],
+ "properties": {
+ "use_jwks": {
+ "symbols": [
+ true
+ ],
+ "type": "enum"
+ },
+ "endpoint": {
+ "type": "string"
+ },
+ "refresh_interval": {
+ "default": 300,
+ "type": "number"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-jwt.ssl_disable"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.ssl_enable"
+ }
+ ]
+ },
+ "mechanism": {
+ "symbols": [
+ "jwt"
+ ],
+ "type": "enum"
+ },
+ "verify_claims": {
+ "default": {},
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.sysmon": {
+ "properties": {
+ "vm": {
+ "description": "This part of the configuration is responsible for collecting\n BEAM VM events, such as long garbage collection, traffic congestion in the inter-broker\n communication, etc.",
+ "$ref": "#/components/schemas/emqx_schema.sysmon_vm"
+ },
+ "os": {
+ "description": "This part of the configuration is responsible for monitoring\n the host OS health, such as free memory, disk space, CPU load, etc.",
+ "$ref": "#/components/schemas/emqx_schema.sysmon_os"
+ },
+ "top": {
+ "description": "This part of the configuration is responsible for monitoring\n the Erlang processes in the VM. This information can be sent to an external\n PostgreSQL database. This feature is inactive unless the PostgreSQL sink is configured.",
+ "$ref": "#/components/schemas/emqx_schema.sysmon_top"
+ }
+ },
+ "type": "object"
+ },
+ "authn-mongodb.standalone": {
+ "required": [
+ "database",
+ "server",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "mongodb"
+ ],
+ "type": "enum"
+ },
+ "collection": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "password_hash_field": {
+ "type": "string"
+ },
+ "salt_field": {
+ "type": "string"
+ },
+ "is_superuser_field": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "mongo_type": {
+ "default": "single",
+ "symbols": [
+ "single"
+ ],
+ "type": "enum"
+ },
+ "server": {
+ "description": "\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe MongoDB default port 27017 is used if '[:Port]' isn't present",
+ "type": "ip_port"
+ },
+ "w_mode": {
+ "default": "unsafe",
+ "symbols": [
+ "unsafe",
+ "safe"
+ ],
+ "type": "enum"
+ },
+ "srv_record": {
+ "default": false,
+ "type": "boolean"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "auth_source": {
+ "type": "string"
+ },
+ "database": {
+ "type": "string"
+ },
+ "topology": {
+ "$ref": "#/components/schemas/emqx_connector_mongo.topology"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "configuration.log": {
+ "properties": {
+ "console_handler": {
+ "$ref": "#/components/schemas/emqx_conf_schema.console_handler"
+ },
+ "file_handlers": {
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_conf_schema.log_file_handler"
+ }
+ },
+ "type": "object"
+ },
+ "error_logger": {
+ "default": "silent",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "prometheus.prometheus": {
+ "properties": {
+ "push_gateway_server": {
+ "default": "http://127.0.0.1:9091",
+ "type": "string"
+ },
+ "interval": {
+ "default": "15s",
+ "type": "duration"
+ },
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "authn-hash.bcrypt": {
+ "properties": {
+ "name": {
+ "symbols": [
+ "bcrypt"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.quota": {
+ "properties": {
+ "conn_messages_routing": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "overall_messages_routing": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "comma_separated_string"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.conn_congestion": {
+ "properties": {
+ "enable_alarm": {
+ "default": false,
+ "type": "boolean"
+ },
+ "min_alarm_sustain_duration": {
+ "default": "1m",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "authn-jwt.ssl_disable": {
+ "properties": {
+ "enable": {
+ "symbols": [
+ false
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.listener_wss_opts": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "cacertfile": {
+ "description": "Trusted PEM format CA certificates bundle file.
\nThe certificates in this file are used to verify the TLS peer's certificates.\nAppend new certificates to the file if new CAs are to be trusted.\nThere is no need to restart EMQX to have the updated file loaded, because\nthe system regularly checks if file has been updated (and reload).
\nNOTE: invalidating (deleting) a certificate from the file will not affect\nalready established connections.\n",
+ "type": "string"
+ },
+ "certfile": {
+ "description": "PEM format certificates chain file.
\nThe certificates in this file should be in reversed order of the certificate\nissue chain. That is, the host's certificate should be placed in the beginning\nof the file, followed by the immediate issuer certificate and so on.\nAlthough the root CA certificate is optional, it should be placed at the end of\nthe file if it is to be added.\n",
+ "type": "string"
+ },
+ "keyfile": {
+ "description": "PEM format private key file.
\n",
+ "type": "string"
+ },
+ "verify": {
+ "default": "verify_none",
+ "symbols": [
+ "verify_peer",
+ "verify_none"
+ ],
+ "type": "enum"
+ },
+ "reuse_sessions": {
+ "default": true,
+ "type": "boolean"
+ },
+ "depth": {
+ "default": 10,
+ "type": "number"
+ },
+ "password": {
+ "description": "String containing the user's password. Only used if the private\nkey file is password-protected.",
+ "type": "string"
+ },
+ "versions": {
+ "default": [
+ "tlsv1.3",
+ "tlsv1.2",
+ "tlsv1.1",
+ "tlsv1"
+ ],
+ "description": "All TLS/DTLS versions to be supported.
\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIn case PSK cipher suites are intended, make sure to configured\n['tlsv1.2', 'tlsv1.1']
here.\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "ciphers": {
+ "default": [
+ "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",
+ "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",
+ "ECDHE-ECDSA-AES128-SHA",
+ "ECDHE-RSA-AES128-SHA",
+ "DHE-DSS-AES128-SHA",
+ "ECDH-ECDSA-AES128-SHA",
+ "ECDH-RSA-AES128-SHA",
+ "RSA-PSK-AES256-GCM-SHA384",
+ "RSA-PSK-AES256-CBC-SHA384",
+ "RSA-PSK-AES128-GCM-SHA256",
+ "RSA-PSK-AES128-CBC-SHA256",
+ "RSA-PSK-AES256-CBC-SHA",
+ "RSA-PSK-AES128-CBC-SHA"
+ ],
+ "description": "This config holds TLS cipher suite names separated by comma,\nor as an array of strings. e.g.\n\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n[\"TLS_AES_256_GCM_SHA384\",\"TLS_AES_128_GCM_SHA256\"]
.\n
\nCiphers (and their ordering) define the way in which the\nclient and server encrypts information over the network connection.\nSelecting a good cipher suite is critical for the\napplication's data security, confidentiality and performance.\n\nThe names should be in OpenSSL string format (not RFC format).\nAll default values and examples provided by EMQX config\ndocumentation are all in OpenSSL format.
\n\nNOTE: Certain cipher suites are only compatible with\nspecific TLS versions
('tlsv1.1', 'tlsv1.2' or 'tlsv1.3')\nincompatible cipher suites will be silently dropped.\nFor instance, if only 'tlsv1.3' is given in the versions
,\nconfiguring cipher suites for other versions will have no effect.\n
\n\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIf PSK cipher suites are intended, 'tlsv1.3' should be disabled from versions
.
\nPSK cipher suites: \"RSA-PSK-AES256-GCM-SHA384,RSA-PSK-AES256-CBC-SHA384,\nRSA-PSK-AES128-GCM-SHA256,RSA-PSK-AES128-CBC-SHA256,\nRSA-PSK-AES256-CBC-SHA,RSA-PSK-AES128-CBC-SHA,\nRSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "user_lookup_fun": {
+ "default": "emqx_tls_psk:lookup",
+ "type": "string"
+ },
+ "secure_renegotiate": {
+ "default": true,
+ "description": "\nSSL parameter renegotiation is a feature that allows a client and a server\nto renegotiate the parameters of the SSL connection on the fly.\nRFC 5746 defines a more secure way of doing this. By enabling secure renegotiation,\nyou drop support for the insecure renegotiation, prone to MitM attacks.\n",
+ "type": "boolean"
+ },
+ "dhfile": {
+ "description": "Path to a file containing PEM-encoded Diffie Hellman parameters\nto be used by the server if a cipher suite using Diffie Hellman\nkey exchange is negotiated. If not specified, default parameters\nare used.
\nNOTE: The dhfile
option is not supported by TLS 1.3.",
+ "type": "string"
+ },
+ "fail_if_no_peer_cert": {
+ "default": false,
+ "description": "\nUsed together with {verify, verify_peer} by an TLS/DTLS server.\nIf set to true, the server fails if the client does not have a\ncertificate to send, that is, sends an empty certificate.\nIf set to false, it fails only if the client sends an invalid\ncertificate (an empty certificate is considered valid).\n",
+ "type": "boolean"
+ },
+ "honor_cipher_order": {
+ "default": true,
+ "type": "boolean"
+ },
+ "client_renegotiation": {
+ "default": true,
+ "description": "\nIn protocols that support client-initiated renegotiation,\nthe cost of resources of such an operation is higher for the server than the client.\nThis can act as a vector for denial of service attacks.\nThe SSL application already takes measures to counter-act such attempts,\nbut client-initiated renegotiation can be strictly disabled by setting this option to false.\nThe default value is true. Note that disabling renegotiation can result in\nlong-lived connections becoming unusable due to limits on\nthe number of messages the underlying cipher suite can encipher.\n",
+ "type": "boolean"
+ },
+ "handshake_timeout": {
+ "default": "15s",
+ "description": "Maximum time duration allowed for the handshake to complete",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "modules.telemetry": {
+ "properties": {
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt_tcp_listener": {
+ "required": [
+ "bind"
+ ],
+ "properties": {
+ "tcp": {
+ "description": "TCP listener options",
+ "$ref": "#/components/schemas/emqx_schema.tcp_opts"
+ },
+ "bind": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "ip_port"
+ }
+ ]
+ },
+ "acceptors": {
+ "default": 16,
+ "type": "number"
+ },
+ "max_connections": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "mountpoint": {
+ "default": "",
+ "type": "string"
+ },
+ "zone": {
+ "default": "default",
+ "type": "string"
+ },
+ "limiter": {
+ "default": {},
+ "properties": {
+ "$ratelimit bucket's name": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "access_rules": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "proxy_protocol": {
+ "default": false,
+ "type": "boolean"
+ },
+ "proxy_protocol_timeout": {
+ "type": "duration"
+ },
+ "authentication": {
+ "description": "Per-listener authentication override\nAuthentication can be one single authenticator instance or a chain of authenticators as an array.\nWhen authenticating a login (username, client ID, etc.) the authenticators are checked\nin the configured order.
\n",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-scram-builtin_db.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.jwks"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.public-key"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.hmac-based"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.post"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.get"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.sentinel"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.sharded-cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.replica-set"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-postgresql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mysql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-builtin_db.authentication"
+ }
+ ]
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.broker": {
+ "properties": {
+ "sys_msg_interval": {
+ "default": "1m",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "sys_heartbeat_interval": {
+ "default": "30s",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "enable_session_registry": {
+ "default": true,
+ "type": "boolean"
+ },
+ "session_locking_strategy": {
+ "default": "quorum",
+ "symbols": [
+ "local",
+ "leader",
+ "quorum",
+ "all"
+ ],
+ "type": "enum"
+ },
+ "shared_subscription_strategy": {
+ "default": "round_robin",
+ "symbols": [
+ "random",
+ "round_robin",
+ "sticky",
+ "hash_topic",
+ "hash_clientid"
+ ],
+ "type": "enum"
+ },
+ "shared_dispatch_ack_enabled": {
+ "default": false,
+ "type": "boolean"
+ },
+ "route_batch_clean": {
+ "default": true,
+ "type": "boolean"
+ },
+ "perf": {
+ "description": "Broker performance tuning parameters",
+ "$ref": "#/components/schemas/emqx_schema.broker_perf"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.cluster_mcast": {
+ "properties": {
+ "addr": {
+ "default": "239.192.0.1",
+ "type": "string"
+ },
+ "ports": {
+ "default": [
+ 4369,
+ 4370
+ ],
+ "items": {
+ "type": "number"
+ },
+ "type": "array"
+ },
+ "iface": {
+ "default": "0.0.0.0",
+ "type": "string"
+ },
+ "ttl": {
+ "default": 255,
+ "maximum": 255,
+ "minimum": 0,
+ "type": "number"
+ },
+ "loop": {
+ "default": true,
+ "type": "boolean"
+ },
+ "sndbuf": {
+ "default": "16KB",
+ "type": "byteSize"
+ },
+ "recbuf": {
+ "default": "16KB",
+ "type": "byteSize"
+ },
+ "buffer": {
+ "default": "32KB",
+ "type": "byteSize"
+ }
+ },
+ "type": "object"
+ },
+ "zone.mqtt": {
+ "properties": {
+ "idle_timeout": {
+ "description": "Close TCP connections from the clients that have not sent MQTT CONNECT\nmessage within this interval.",
+ "oneOf": [
+ {
+ "type": "duration"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "max_packet_size": {
+ "description": "Maximum MQTT packet size allowed.",
+ "type": "byteSize"
+ },
+ "max_clientid_len": {
+ "description": "Maximum allowed length of MQTT clientId.",
+ "maximum": 65535,
+ "minimum": 23,
+ "type": "number"
+ },
+ "max_topic_levels": {
+ "description": "Maximum topic levels allowed.",
+ "maximum": 65535,
+ "minimum": 1,
+ "type": "number"
+ },
+ "max_qos_allowed": {
+ "description": "Maximum QoS allowed.",
+ "symbols": [
+ 0,
+ 1,
+ 2
+ ],
+ "type": "enum"
+ },
+ "max_topic_alias": {
+ "description": "Maximum Topic Alias, 0 means no topic alias supported.",
+ "maximum": 65535,
+ "minimum": 0,
+ "type": "number"
+ },
+ "retain_available": {
+ "description": "Support MQTT retained messages.",
+ "type": "boolean"
+ },
+ "wildcard_subscription": {
+ "description": "Support MQTT Wildcard Subscriptions.",
+ "type": "boolean"
+ },
+ "shared_subscription": {
+ "description": "Support MQTT Shared Subscriptions.",
+ "type": "boolean"
+ },
+ "ignore_loop_deliver": {
+ "description": "Ignore loop delivery of messages for MQTT v3.1.1.",
+ "type": "boolean"
+ },
+ "strict_mode": {
+ "description": "Parse the MQTT frame in strict mode.",
+ "type": "boolean"
+ },
+ "response_information": {
+ "description": "Specify the response information returned to the client\nThis feature is disabled if is set to \"\".",
+ "type": "string"
+ },
+ "server_keepalive": {
+ "description": "'Server Keep Alive' of MQTT 5.0.\nIf the server returns a 'Server Keep Alive' in the CONNACK packet,\nthe client MUST use that value instead of the value it sent as the 'Keep Alive'.",
+ "oneOf": [
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "keepalive_backoff": {
+ "description": "The backoff for MQTT keepalive timeout. The broker will close the connection\nafter idling for 'Keepalive * backoff * 2'.",
+ "type": "number"
+ },
+ "max_subscriptions": {
+ "description": "Maximum number of subscriptions allowed.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "minimum": 1,
+ "type": "number"
+ }
+ ]
+ },
+ "upgrade_qos": {
+ "description": "Force upgrade of QoS level according to subscription.",
+ "type": "boolean"
+ },
+ "max_inflight": {
+ "description": "Maximum size of the Inflight Window storing QoS1/2 messages delivered but un-acked.",
+ "maximum": 65535,
+ "minimum": 1,
+ "type": "number"
+ },
+ "retry_interval": {
+ "description": "Retry interval for QoS1/2 message delivering.",
+ "type": "duration"
+ },
+ "max_awaiting_rel": {
+ "description": "Maximum QoS2 packets (Client -> Broker) awaiting PUBREL.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "number"
+ }
+ ]
+ },
+ "await_rel_timeout": {
+ "description": "The QoS2 messages (Client -> Broker) will be dropped if awaiting PUBREL timeout.",
+ "type": "duration"
+ },
+ "session_expiry_interval": {
+ "description": "Default session expiry interval for MQTT V3.1.1 connections.",
+ "type": "duration"
+ },
+ "max_mqueue_len": {
+ "description": "Maximum queue length. Enqueued messages when persistent client disconnected,\nor inflight window is full.",
+ "oneOf": [
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ },
+ {
+ "minimum": 0,
+ "type": "number"
+ }
+ ]
+ },
+ "mqueue_priorities": {
+ "description": "Topic priorities.
\nThere's no priority table by default, hence all messages are treated equal.
\nPriority number [1-255]
\n\n**NOTE**: Comma and equal signs are not allowed for priority topic names.
\n**NOTE**: Messages for topics not in the priority table are treated as\neither highest or lowest priority depending on the configured value for\nmqtt.mqueue_default_priority
.\n
\n**Examples**:\nTo configure \"topic/1\" > \"topic/2\"
:
\nmqueue_priorities: {\"topic/1\": 10, \"topic/2\": 8}
",
+ "oneOf": [
+ {
+ "symbols": [
+ "disabled"
+ ],
+ "type": "enum"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "mqueue_default_priority": {
+ "description": "Default to the highest priority for topics not matching priority table.",
+ "symbols": [
+ "highest",
+ "lowest"
+ ],
+ "type": "enum"
+ },
+ "mqueue_store_qos0": {
+ "description": "Support enqueue QoS0 messages.",
+ "type": "boolean"
+ },
+ "use_username_as_clientid": {
+ "description": "Replace client ID with the username.",
+ "type": "boolean"
+ },
+ "peer_cert_as_username": {
+ "description": "Use the CN, DN or CRT field from the client certificate as a username.\nOnly works for the TLS connection.",
+ "symbols": [
+ "disabled",
+ "cn",
+ "dn",
+ "crt",
+ "pem",
+ "md5"
+ ],
+ "type": "enum"
+ },
+ "peer_cert_as_clientid": {
+ "description": "Use the CN, DN or CRT field from the client certificate as a clientid.\nOnly works for the TLS connection.",
+ "symbols": [
+ "disabled",
+ "cn",
+ "dn",
+ "crt",
+ "pem",
+ "md5"
+ ],
+ "type": "enum"
+ }
+ },
+ "type": "object"
+ },
+ "authn-scram-builtin_db.authentication": {
+ "required": [
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "scram"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "built-in-database"
+ ],
+ "type": "enum"
+ },
+ "algorithm": {
+ "default": "sha256",
+ "symbols": [
+ "sha256",
+ "sha512"
+ ],
+ "type": "enum"
+ },
+ "iteration_count": {
+ "default": 4096,
+ "minimum": 1,
+ "type": "number"
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "zone.conn_congestion": {
+ "properties": {
+ "enable_alarm": {
+ "type": "boolean"
+ },
+ "min_alarm_sustain_duration": {
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "limiter.limiter": {
+ "properties": {
+ "bytes_in": {
+ "$ref": "#/components/schemas/limiter.limiter_opts"
+ },
+ "message_in": {
+ "$ref": "#/components/schemas/limiter.limiter_opts"
+ },
+ "connection": {
+ "$ref": "#/components/schemas/limiter.limiter_opts"
+ },
+ "message_routing": {
+ "$ref": "#/components/schemas/limiter.limiter_opts"
+ }
+ },
+ "type": "object"
+ },
+ "dashboard.https": {
+ "required": [
+ "bind",
+ "protocol"
+ ],
+ "properties": {
+ "protocol": {
+ "default": "http",
+ "description": "HTTP/HTTPS protocol.",
+ "symbols": [
+ "http",
+ "https"
+ ],
+ "type": "enum"
+ },
+ "bind": {
+ "default": 18083,
+ "description": "Port without IP(18083) or port with specified IP(127.0.0.1:18083).",
+ "oneOf": [
+ {
+ "type": "ip_port"
+ },
+ {
+ "minimum": 1,
+ "type": "number"
+ }
+ ]
+ },
+ "num_acceptors": {
+ "default": 4,
+ "description": "Socket acceptor pool for TCP protocols.",
+ "type": "number"
+ },
+ "max_connections": {
+ "default": 512,
+ "type": "number"
+ },
+ "backlog": {
+ "default": 1024,
+ "description": "Defines the maximum length that the queue of pending connections can grow to.",
+ "type": "number"
+ },
+ "send_timeout": {
+ "default": "5s",
+ "type": "duration"
+ },
+ "inet6": {
+ "default": false,
+ "type": "boolean"
+ },
+ "ipv6_v6only": {
+ "default": false,
+ "type": "boolean"
+ },
+ "enable": {
+ "default": false,
+ "type": "boolean"
+ },
+ "cacertfile": {
+ "description": "Trusted PEM format CA certificates bundle file.
\nThe certificates in this file are used to verify the TLS peer's certificates.\nAppend new certificates to the file if new CAs are to be trusted.\nThere is no need to restart EMQX to have the updated file loaded, because\nthe system regularly checks if file has been updated (and reload).
\nNOTE: invalidating (deleting) a certificate from the file will not affect\nalready established connections.\n",
+ "type": "string"
+ },
+ "certfile": {
+ "description": "PEM format certificates chain file.
\nThe certificates in this file should be in reversed order of the certificate\nissue chain. That is, the host's certificate should be placed in the beginning\nof the file, followed by the immediate issuer certificate and so on.\nAlthough the root CA certificate is optional, it should be placed at the end of\nthe file if it is to be added.\n",
+ "type": "string"
+ },
+ "keyfile": {
+ "description": "PEM format private key file.
\n",
+ "type": "string"
+ },
+ "verify": {
+ "default": "verify_none",
+ "symbols": [
+ "verify_peer",
+ "verify_none"
+ ],
+ "type": "enum"
+ },
+ "reuse_sessions": {
+ "default": true,
+ "type": "boolean"
+ },
+ "depth": {
+ "default": 10,
+ "type": "number"
+ },
+ "password": {
+ "description": "String containing the user's password. Only used if the private\nkey file is password-protected.",
+ "type": "string"
+ },
+ "versions": {
+ "default": [
+ "tlsv1.3",
+ "tlsv1.2",
+ "tlsv1.1",
+ "tlsv1"
+ ],
+ "description": "All TLS/DTLS versions to be supported.
\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIn case PSK cipher suites are intended, make sure to configured\n['tlsv1.2', 'tlsv1.1']
here.\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "ciphers": {
+ "default": [
+ "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",
+ "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",
+ "ECDHE-ECDSA-AES128-SHA",
+ "ECDHE-RSA-AES128-SHA",
+ "DHE-DSS-AES128-SHA",
+ "ECDH-ECDSA-AES128-SHA",
+ "ECDH-RSA-AES128-SHA",
+ "RSA-PSK-AES256-GCM-SHA384",
+ "RSA-PSK-AES256-CBC-SHA384",
+ "RSA-PSK-AES128-GCM-SHA256",
+ "RSA-PSK-AES128-CBC-SHA256",
+ "RSA-PSK-AES256-CBC-SHA",
+ "RSA-PSK-AES128-CBC-SHA"
+ ],
+ "description": "This config holds TLS cipher suite names separated by comma,\nor as an array of strings. e.g.\n\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n[\"TLS_AES_256_GCM_SHA384\",\"TLS_AES_128_GCM_SHA256\"]
.\n
\nCiphers (and their ordering) define the way in which the\nclient and server encrypts information over the network connection.\nSelecting a good cipher suite is critical for the\napplication's data security, confidentiality and performance.\n\nThe names should be in OpenSSL string format (not RFC format).\nAll default values and examples provided by EMQX config\ndocumentation are all in OpenSSL format.
\n\nNOTE: Certain cipher suites are only compatible with\nspecific TLS versions
('tlsv1.1', 'tlsv1.2' or 'tlsv1.3')\nincompatible cipher suites will be silently dropped.\nFor instance, if only 'tlsv1.3' is given in the versions
,\nconfiguring cipher suites for other versions will have no effect.\n
\n\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIf PSK cipher suites are intended, 'tlsv1.3' should be disabled from versions
.
\nPSK cipher suites: \"RSA-PSK-AES256-GCM-SHA384,RSA-PSK-AES256-CBC-SHA384,\nRSA-PSK-AES128-GCM-SHA256,RSA-PSK-AES128-CBC-SHA256,\nRSA-PSK-AES256-CBC-SHA,RSA-PSK-AES128-CBC-SHA,\nRSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
\n",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "user_lookup_fun": {
+ "default": "emqx_tls_psk:lookup",
+ "type": "string"
+ },
+ "secure_renegotiate": {
+ "default": true,
+ "description": "\nSSL parameter renegotiation is a feature that allows a client and a server\nto renegotiate the parameters of the SSL connection on the fly.\nRFC 5746 defines a more secure way of doing this. By enabling secure renegotiation,\nyou drop support for the insecure renegotiation, prone to MitM attacks.\n",
+ "type": "boolean"
+ },
+ "dhfile": {
+ "description": "Path to a file containing PEM-encoded Diffie Hellman parameters\nto be used by the server if a cipher suite using Diffie Hellman\nkey exchange is negotiated. If not specified, default parameters\nare used.
\nNOTE: The dhfile
option is not supported by TLS 1.3.",
+ "type": "string"
+ },
+ "honor_cipher_order": {
+ "default": true,
+ "type": "boolean"
+ },
+ "client_renegotiation": {
+ "default": true,
+ "description": "\nIn protocols that support client-initiated renegotiation,\nthe cost of resources of such an operation is higher for the server than the client.\nThis can act as a vector for denial of service attacks.\nThe SSL application already takes measures to counter-act such attempts,\nbut client-initiated renegotiation can be strictly disabled by setting this option to false.\nThe default value is true. Note that disabling renegotiation can result in\nlong-lived connections becoming unusable due to limits on\nthe number of messages the underlying cipher suite can encipher.\n",
+ "type": "boolean"
+ },
+ "handshake_timeout": {
+ "default": "15s",
+ "description": "Maximum time duration allowed for the handshake to complete",
+ "type": "duration"
+ }
+ },
+ "type": "object"
+ },
+ "modules.event_message": {
+ "properties": {
+ "client_connected": {
+ "default": false,
+ "description": "Enable/disable client_connected event messages",
+ "type": "boolean"
+ },
+ "client_disconnected": {
+ "default": false,
+ "description": "Enable/disable client_disconnected event messages",
+ "type": "boolean"
+ },
+ "client_subscribed": {
+ "default": false,
+ "description": "Enable/disable client_subscribed event messages",
+ "type": "boolean"
+ },
+ "client_unsubscribed": {
+ "default": false,
+ "description": "Enable/disable client_unsubscribed event messages",
+ "type": "boolean"
+ },
+ "message_delivered": {
+ "default": false,
+ "description": "Enable/disable message_delivered event messages",
+ "type": "boolean"
+ },
+ "message_acked": {
+ "default": false,
+ "description": "Enable/disable message_acked event messages",
+ "type": "boolean"
+ },
+ "message_dropped": {
+ "default": false,
+ "description": "Enable/disable message_dropped event messages",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "limiter.limiter_opts": {
+ "properties": {
+ "global": {
+ "$ref": "#/components/schemas/limiter.rate_burst"
+ },
+ "zone": {
+ "properties": {
+ "$zone name": {
+ "$ref": "#/components/schemas/limiter.rate_burst"
+ }
+ },
+ "type": "object"
+ },
+ "bucket": {
+ "description": "Token bucket",
+ "properties": {
+ "$bucket_id": {
+ "$ref": "#/components/schemas/limiter.bucket"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_conf_schema.log_rotation": {
+ "properties": {
+ "enable": {
+ "default": true,
+ "type": "boolean"
+ },
+ "count": {
+ "default": 10,
+ "maximum": 2048,
+ "minimum": 1,
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "authn-builtin_db.authentication": {
+ "required": [
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "built-in-database"
+ ],
+ "type": "enum"
+ },
+ "user_id_type": {
+ "default": "username",
+ "symbols": [
+ "clientid",
+ "username"
+ ],
+ "type": "enum"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt_rw"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "authn-jwt.ssl_enable": {
+ "properties": {
+ "enable": {
+ "symbols": [
+ true
+ ],
+ "type": "enum"
+ },
+ "cacertfile": {
+ "type": "string"
+ },
+ "certfile": {
+ "type": "string"
+ },
+ "keyfile": {
+ "type": "string"
+ },
+ "verify": {
+ "default": "verify_none",
+ "symbols": [
+ "verify_peer",
+ "verify_none"
+ ],
+ "type": "enum"
+ },
+ "server_name_indication": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.broker_perf": {
+ "properties": {
+ "route_lock_type": {
+ "default": "key",
+ "symbols": [
+ "key",
+ "tab",
+ "global"
+ ],
+ "type": "enum"
+ },
+ "trie_compaction": {
+ "default": true,
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "auto_subscribe.topic": {
+ "properties": {
+ "topic": {
+ "example": "/clientid/${clientid}/username/${username}/host/${host}/port/${port}",
+ "type": "string"
+ },
+ "qos": {
+ "default": 0,
+ "symbols": [
+ 0,
+ 1,
+ 2
+ ],
+ "type": "enum"
+ },
+ "rh": {
+ "default": 0,
+ "maximum": 2,
+ "minimum": 0,
+ "type": "number"
+ },
+ "rap": {
+ "default": 0,
+ "maximum": 1,
+ "minimum": 0,
+ "type": "number"
+ },
+ "nl": {
+ "default": 0,
+ "maximum": 1,
+ "minimum": 0,
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt_quic_listener": {
+ "required": [
+ "bind"
+ ],
+ "properties": {
+ "enabled": {
+ "default": true,
+ "type": "boolean"
+ },
+ "certfile": {
+ "type": "string"
+ },
+ "keyfile": {
+ "type": "string"
+ },
+ "ciphers": {
+ "default": [
+ "TLS_AES_256_GCM_SHA384",
+ "TLS_AES_128_GCM_SHA256",
+ "TLS_CHACHA20_POLY1305_SHA256"
+ ],
+ "description": "This config holds TLS cipher suite names separated by comma,\nor as an array of strings. e.g.\n\"TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256\"
or\n[\"TLS_AES_256_GCM_SHA384\",\"TLS_AES_128_GCM_SHA256\"]
.\n
\nCiphers (and their ordering) define the way in which the\nclient and server encrypts information over the network connection.\nSelecting a good cipher suite is critical for the\napplication's data security, confidentiality and performance.\n\nThe names should be in OpenSSL string format (not RFC format).\nAll default values and examples provided by EMQX config\ndocumentation are all in OpenSSL format.
\n\nNOTE: Certain cipher suites are only compatible with\nspecific TLS versions
('tlsv1.1', 'tlsv1.2' or 'tlsv1.3')\nincompatible cipher suites will be silently dropped.\nFor instance, if only 'tlsv1.3' is given in the versions
,\nconfiguring cipher suites for other versions will have no effect.\n
\n\nNOTE: PSK ciphers are suppressed by 'tlsv1.3' version config
\nIf PSK cipher suites are intended, 'tlsv1.3' should be disabled from versions
.
\nPSK cipher suites: \"RSA-PSK-AES256-GCM-SHA384,RSA-PSK-AES256-CBC-SHA384,\nRSA-PSK-AES128-GCM-SHA256,RSA-PSK-AES128-CBC-SHA256,\nRSA-PSK-AES256-CBC-SHA,RSA-PSK-AES128-CBC-SHA,\nRSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
\nNOTE: QUIC listener supports only 'tlsv1.3' ciphers
",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "idle_timeout": {
+ "default": "15s",
+ "type": "duration"
+ },
+ "bind": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "ip_port"
+ }
+ ]
+ },
+ "acceptors": {
+ "default": 16,
+ "type": "number"
+ },
+ "max_connections": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "mountpoint": {
+ "default": "",
+ "type": "string"
+ },
+ "zone": {
+ "default": "default",
+ "type": "string"
+ },
+ "limiter": {
+ "default": {},
+ "properties": {
+ "$ratelimit bucket's name": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.listeners": {
+ "properties": {
+ "tcp": {
+ "description": "TCP listeners",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt_tcp_listener"
+ }
+ },
+ "type": "object"
+ },
+ "ssl": {
+ "description": "SSL listeners",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt_ssl_listener"
+ }
+ },
+ "type": "object"
+ },
+ "ws": {
+ "description": "HTTP websocket listeners",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt_ws_listener"
+ }
+ },
+ "type": "object"
+ },
+ "wss": {
+ "description": "HTTPS websocket listeners",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt_wss_listener"
+ }
+ },
+ "type": "object"
+ },
+ "quic": {
+ "description": "QUIC listeners",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt_quic_listener"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "authn-hash.pbkdf2": {
+ "required": [
+ "dk_length"
+ ],
+ "properties": {
+ "name": {
+ "symbols": [
+ "pbkdf2"
+ ],
+ "type": "enum"
+ },
+ "mac_fun": {
+ "symbols": [
+ "md4",
+ "md5",
+ "ripemd160",
+ "sha",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512"
+ ],
+ "type": "enum"
+ },
+ "iterations": {
+ "type": "number"
+ },
+ "dk_length": {
+ "type": "number"
+ }
+ },
+ "type": "object"
+ },
+ "authn-mongodb.sharded-cluster": {
+ "required": [
+ "database",
+ "servers",
+ "backend",
+ "mechanism"
+ ],
+ "properties": {
+ "mechanism": {
+ "symbols": [
+ "password-based"
+ ],
+ "type": "enum"
+ },
+ "backend": {
+ "symbols": [
+ "mongodb"
+ ],
+ "type": "enum"
+ },
+ "collection": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "password_hash_field": {
+ "type": "string"
+ },
+ "salt_field": {
+ "type": "string"
+ },
+ "is_superuser_field": {
+ "type": "string"
+ },
+ "password_hash_algorithm": {
+ "default": {
+ "name": "sha256",
+ "salt_position": "prefix"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-hash.other_algorithms"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.pbkdf2"
+ },
+ {
+ "$ref": "#/components/schemas/authn-hash.bcrypt"
+ }
+ ]
+ },
+ "enable": {
+ "default": true,
+ "description": "Set to false
to disable this auth provider",
+ "type": "boolean"
+ },
+ "mongo_type": {
+ "default": "sharded",
+ "symbols": [
+ "sharded"
+ ],
+ "type": "enum"
+ },
+ "servers": {
+ "description": "A Node list for Cluster to connect to. The nodes should be split with ',', such as: 'Node[,Node]'
\nFor each Node should be:
\nThe IPv4 or IPv6 address or host name to connect to.
\nA host entry has the following form: 'Host[:Port]'
\nThe MongoDB default port 27017 is used if '[:Port]' isn't present",
+ "type": "string"
+ },
+ "w_mode": {
+ "default": "unsafe",
+ "symbols": [
+ "unsafe",
+ "safe"
+ ],
+ "type": "enum"
+ },
+ "srv_record": {
+ "default": false,
+ "type": "boolean"
+ },
+ "pool_size": {
+ "default": 8,
+ "type": "number"
+ },
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "auth_source": {
+ "type": "string"
+ },
+ "database": {
+ "type": "string"
+ },
+ "topology": {
+ "$ref": "#/components/schemas/emqx_connector_mongo.topology"
+ },
+ "ssl": {
+ "default": {
+ "enable": false
+ },
+ "$ref": "#/components/schemas/emqx_schema.ssl_client_opts"
+ }
+ },
+ "type": "object"
+ },
+ "limiter.bucket_aggregated": {
+ "properties": {
+ "rate": {
+ "type": "string"
+ },
+ "initial": {
+ "default": "0",
+ "type": "string"
+ },
+ "capacity": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "dashboard.dashboard": {
+ "required": [
+ "default_password",
+ "default_username"
+ ],
+ "properties": {
+ "listeners": {
+ "description": "HTTP(s) listeners are identified by their protocol type and are\nused to serve dashboard UI and restful HTTP API.
\nListeners must have a unique combination of port number and IP address.
\nFor example, an HTTP listener can listen on all configured IP addresses\non a given port for a machine by specifying the IP address 0.0.0.0.
\nAlternatively, the HTTP listener can specify a unique IP address for each listener,\nbut use the same port.\n",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/dashboard.https"
+ },
+ {
+ "$ref": "#/components/schemas/dashboard.http"
+ }
+ ]
+ },
+ "type": "array"
+ },
+ "default_username": {
+ "default": "admin",
+ "type": "string"
+ },
+ "default_password": {
+ "default": "public",
+ "description": "\nThe initial default password for dashboard 'admin' user.\nFor safety, it should be changed as soon as possible.",
+ "type": "string"
+ },
+ "sample_interval": {
+ "default": "10s",
+ "type": "duration"
+ },
+ "token_expired_time": {
+ "default": "30m",
+ "type": "duration"
+ },
+ "cors": {
+ "default": false,
+ "description": "Support Cross-Origin Resource Sharing (CORS).\nAllows a server to indicate any origins (domain, scheme, or port) other than\nits own from which a browser should permit loading resources.",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "emqx_schema.mqtt_ws_listener": {
+ "required": [
+ "bind"
+ ],
+ "properties": {
+ "tcp": {
+ "$ref": "#/components/schemas/emqx_schema.tcp_opts"
+ },
+ "websocket": {
+ "$ref": "#/components/schemas/emqx_schema.ws_opts"
+ },
+ "bind": {
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "type": "ip_port"
+ }
+ ]
+ },
+ "acceptors": {
+ "default": 16,
+ "type": "number"
+ },
+ "max_connections": {
+ "default": "infinity",
+ "oneOf": [
+ {
+ "type": "number"
+ },
+ {
+ "symbols": [
+ "infinity"
+ ],
+ "type": "enum"
+ }
+ ]
+ },
+ "mountpoint": {
+ "default": "",
+ "type": "string"
+ },
+ "zone": {
+ "default": "default",
+ "type": "string"
+ },
+ "limiter": {
+ "default": {},
+ "properties": {
+ "$ratelimit bucket's name": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "access_rules": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "proxy_protocol": {
+ "default": false,
+ "type": "boolean"
+ },
+ "proxy_protocol_timeout": {
+ "type": "duration"
+ },
+ "authentication": {
+ "description": "Per-listener authentication override\nAuthentication can be one single authenticator instance or a chain of authenticators as an array.\nWhen authenticating a login (username, client ID, etc.) the authenticators are checked\nin the configured order.
\n",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/authn-scram-builtin_db.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.jwks"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.public-key"
+ },
+ {
+ "$ref": "#/components/schemas/authn-jwt.hmac-based"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.post"
+ },
+ {
+ "$ref": "#/components/schemas/authn-http.get"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.sentinel"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-redis.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.sharded-cluster"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.replica-set"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mongodb.standalone"
+ },
+ {
+ "$ref": "#/components/schemas/authn-postgresql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-mysql.authentication"
+ },
+ {
+ "$ref": "#/components/schemas/authn-builtin_db.authentication"
+ }
+ ]
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "zone.force_shutdown": {
+ "properties": {
+ "enable": {
+ "type": "boolean"
+ },
+ "max_message_queue_len": {
+ "minimum": 0,
+ "type": "number"
+ },
+ "max_heap_size": {
+ "type": "byteSize"
+ }
+ },
+ "type": "object"
+ }
+ }
+ },
+ "info": {
+ "title": "EMQX Hot Conf Schema",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/configs": {
+ "get": {
+ "properties": {
+ "listeners": {
+ "description": "MQTT listeners identified by their protocol type and assigned names",
+ "$ref": "#/components/schemas/emqx_schema.listeners"
+ },
+ "zones": {
+ "description": "A zone is a set of configs grouped by the zone name
.
\nFor flexible configuration mapping, the name
\ncan be set to a listener's zone
config.
\nNOTE: A built-in zone named default
is auto created\nand can not be deleted.",
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.zone"
+ }
+ },
+ "type": "object"
+ },
+ "mqtt": {
+ "description": "Global MQTT configuration.
\nThe configs here work as default values which can be overridden\nin zone
configs",
+ "$ref": "#/components/schemas/emqx_schema.mqtt"
+ },
+ "node": {
+ "description": "Node name, cookie, config & data directories and the Erlang virtual machine (BEAM) boot parameters.",
+ "$ref": "#/components/schemas/configuration.node"
+ },
+ "cluster": {
+ "description": "EMQX nodes can form a cluster to scale up the total capacity.
Here holds the configs to instruct how individual nodes can discover each other.",
+ "$ref": "#/components/schemas/configuration.cluster"
+ },
+ "log": {
+ "description": "Configure logging backends (to console or to file), and logging level for each logger backend.",
+ "$ref": "#/components/schemas/configuration.log"
+ },
+ "broker": {
+ "$ref": "#/components/schemas/emqx_schema.broker"
+ },
+ "rate_limit": {
+ "$ref": "#/components/schemas/emqx_schema.rate_limit"
+ },
+ "force_shutdown": {
+ "$ref": "#/components/schemas/emqx_schema.force_shutdown"
+ },
+ "overload_protection": {
+ "$ref": "#/components/schemas/emqx_schema.overload_protection"
+ },
+ "force_gc": {
+ "description": "Force the MQTT connection process garbage collection after\nthis number of messages or bytes have passed through.",
+ "$ref": "#/components/schemas/emqx_schema.force_gc"
+ },
+ "conn_congestion": {
+ "$ref": "#/components/schemas/emqx_schema.conn_congestion"
+ },
+ "quota": {
+ "$ref": "#/components/schemas/emqx_schema.quota"
+ },
+ "stats": {
+ "$ref": "#/components/schemas/emqx_schema.stats"
+ },
+ "sysmon": {
+ "$ref": "#/components/schemas/emqx_schema.sysmon"
+ },
+ "alarm": {
+ "$ref": "#/components/schemas/emqx_schema.alarm"
+ },
+ "flapping_detect": {
+ "$ref": "#/components/schemas/emqx_schema.flapping_detect"
+ },
+ "persistent_session_store": {
+ "$ref": "#/components/schemas/emqx_schema.persistent_session_store"
+ },
+ "trace": {
+ "description": "\nReal-time filtering logs for the ClientID or Topic or IP for debugging.\n",
+ "$ref": "#/components/schemas/emqx_schema.trace"
+ },
+ "retainer": {
+ "$ref": "#/components/schemas/retainer.retainer"
+ },
+ "statsd": {
+ "$ref": "#/components/schemas/statsd.statsd"
+ },
+ "auto_subscribe": {
+ "$ref": "#/components/schemas/auto_subscribe.auto_subscribe"
+ },
+ "delayed": {
+ "$ref": "#/components/schemas/modules.delayed"
+ },
+ "telemetry": {
+ "$ref": "#/components/schemas/modules.telemetry"
+ },
+ "event_message": {
+ "$ref": "#/components/schemas/modules.event_message"
+ },
+ "rewrite": {
+ "items": {
+ "$ref": "#/components/schemas/modules.rewrite"
+ },
+ "type": "array"
+ },
+ "topic_metrics": {
+ "items": {
+ "$ref": "#/components/schemas/modules.topic_metrics"
+ },
+ "type": "array"
+ },
+ "dashboard": {
+ "$ref": "#/components/schemas/dashboard.dashboard"
+ },
+ "prometheus": {
+ "$ref": "#/components/schemas/prometheus.prometheus"
+ },
+ "limiter": {
+ "$ref": "#/components/schemas/limiter.limiter"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "/configs/alarm": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.alarm"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.alarm"
+ }
+ },
+ "/configs/auto_subscribe": {
+ "get": {
+ "$ref": "#/components/schemas/auto_subscribe.auto_subscribe"
+ },
+ "put": {
+ "$ref": "#/components/schemas/auto_subscribe.auto_subscribe"
+ }
+ },
+ "/configs/broker": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.broker"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.broker"
+ }
+ },
+ "/configs/cluster": {
+ "get": {
+ "$ref": "#/components/schemas/configuration.cluster"
+ },
+ "put": {
+ "$ref": "#/components/schemas/configuration.cluster"
+ }
+ },
+ "/configs/conn_congestion": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.conn_congestion"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.conn_congestion"
+ }
+ },
+ "/configs/dashboard": {
+ "get": {
+ "$ref": "#/components/schemas/dashboard.dashboard"
+ },
+ "put": {
+ "$ref": "#/components/schemas/dashboard.dashboard"
+ }
+ },
+ "/configs/delayed": {
+ "get": {
+ "$ref": "#/components/schemas/modules.delayed"
+ },
+ "put": {
+ "$ref": "#/components/schemas/modules.delayed"
+ }
+ },
+ "/configs/event_message": {
+ "get": {
+ "$ref": "#/components/schemas/modules.event_message"
+ },
+ "put": {
+ "$ref": "#/components/schemas/modules.event_message"
+ }
+ },
+ "/configs/flapping_detect": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.flapping_detect"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.flapping_detect"
+ }
+ },
+ "/configs/force_gc": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.force_gc"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.force_gc"
+ }
+ },
+ "/configs/force_shutdown": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.force_shutdown"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.force_shutdown"
+ }
+ },
+ "/configs/limiter": {
+ "get": {
+ "$ref": "#/components/schemas/limiter.limiter"
+ },
+ "put": {
+ "$ref": "#/components/schemas/limiter.limiter"
+ }
+ },
+ "/configs/listeners": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.listeners"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.listeners"
+ }
+ },
+ "/configs/log": {
+ "get": {
+ "$ref": "#/components/schemas/configuration.log"
+ },
+ "put": {
+ "$ref": "#/components/schemas/configuration.log"
+ }
+ },
+ "/configs/mqtt": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.mqtt"
+ }
+ },
+ "/configs/node": {
+ "get": {
+ "$ref": "#/components/schemas/configuration.node"
+ },
+ "put": {
+ "$ref": "#/components/schemas/configuration.node"
+ }
+ },
+ "/configs/overload_protection": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.overload_protection"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.overload_protection"
+ }
+ },
+ "/configs/persistent_session_store": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.persistent_session_store"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.persistent_session_store"
+ }
+ },
+ "/configs/prometheus": {
+ "get": {
+ "$ref": "#/components/schemas/prometheus.prometheus"
+ },
+ "put": {
+ "$ref": "#/components/schemas/prometheus.prometheus"
+ }
+ },
+ "/configs/quota": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.quota"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.quota"
+ }
+ },
+ "/configs/rate_limit": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.rate_limit"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.rate_limit"
+ }
+ },
+ "/configs/retainer": {
+ "get": {
+ "$ref": "#/components/schemas/retainer.retainer"
+ },
+ "put": {
+ "$ref": "#/components/schemas/retainer.retainer"
+ }
+ },
+ "/configs/rewrite": {
+ "get": {
+ "items": {
+ "$ref": "#/components/schemas/modules.rewrite"
+ },
+ "type": "array"
+ },
+ "put": {
+ "items": {
+ "$ref": "#/components/schemas/modules.rewrite"
+ },
+ "type": "array"
+ }
+ },
+ "/configs/stats": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.stats"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.stats"
+ }
+ },
+ "/configs/statsd": {
+ "get": {
+ "$ref": "#/components/schemas/statsd.statsd"
+ },
+ "put": {
+ "$ref": "#/components/schemas/statsd.statsd"
+ }
+ },
+ "/configs/sysmon": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.sysmon"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.sysmon"
+ }
+ },
+ "/configs/telemetry": {
+ "get": {
+ "$ref": "#/components/schemas/modules.telemetry"
+ },
+ "put": {
+ "$ref": "#/components/schemas/modules.telemetry"
+ }
+ },
+ "/configs/topic_metrics": {
+ "get": {
+ "items": {
+ "$ref": "#/components/schemas/modules.topic_metrics"
+ },
+ "type": "array"
+ },
+ "put": {
+ "items": {
+ "$ref": "#/components/schemas/modules.topic_metrics"
+ },
+ "type": "array"
+ }
+ },
+ "/configs/trace": {
+ "get": {
+ "$ref": "#/components/schemas/emqx_schema.trace"
+ },
+ "put": {
+ "$ref": "#/components/schemas/emqx_schema.trace"
+ }
+ },
+ "/configs/zones": {
+ "get": {
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.zone"
+ }
+ },
+ "type": "object"
+ },
+ "put": {
+ "properties": {
+ "$name": {
+ "$ref": "#/components/schemas/emqx_schema.zone"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "/configs_reset/:rootname": {}
+ }
+}
\ No newline at end of file