diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml
index a8f65b926..85b38627f 100644
--- a/.github/workflows/run_test_cases.yaml
+++ b/.github/workflows/run_test_cases.yaml
@@ -88,6 +88,30 @@ jobs:
name: source-${{ matrix.profile }}-${{ matrix.otp }}
path: source.zip
+ check_examples:
+ needs:
+ - build-matrix
+ - prepare
+ runs-on: ${{ needs.build-matrix.outputs.runs-on }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include: ${{ fromJson(needs.build-matrix.outputs.prepare) }}
+ container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04"
+ steps:
+ - uses: AutoModality/action-clean@v1
+ - uses: actions/download-artifact@v3
+ with:
+ name: source-${{ matrix.profile }}-${{ matrix.otp }}
+ path: .
+ - name: unzip source code
+ run: unzip -o -q source.zip
+ - name: check example config files
+ env:
+ PROFILE: ${{ matrix.profile }}
+ working-directory: source
+ run: ./scripts/test/check-example-configs.sh
+
static_checks:
needs:
- build-matrix
diff --git a/apps/emqx/src/emqx_hocon.erl b/apps/emqx/src/emqx_hocon.erl
index e028ebb14..4423ad29d 100644
--- a/apps/emqx/src/emqx_hocon.erl
+++ b/apps/emqx/src/emqx_hocon.erl
@@ -24,7 +24,8 @@
compact_errors/2,
format_error/1,
format_error/2,
- make_schema/1
+ make_schema/1,
+ load_and_check/2
]).
%% @doc Format hocon config field path to dot-separated string in iolist format.
@@ -135,3 +136,28 @@ compact_errors(SchemaModule, Error, Stacktrace) ->
exception => Error,
stacktrace => Stacktrace
}}.
+
+%% @doc This is only used in static check scripts in the CI.
+-spec load_and_check(module(), filename:filename_all()) -> {ok, term()} | {error, any()}.
+load_and_check(SchemaModule, File) ->
+ try
+ do_load_and_check(SchemaModule, File)
+ catch
+ throw:Reason:Stacktrace ->
+ compact_errors(Reason, Stacktrace)
+ end.
+
+do_load_and_check(SchemaModule, File) ->
+ case hocon:load(File, #{format => map}) of
+ {ok, Conf} ->
+ Opts = #{atom_key => false, required => false},
+ %% here we check only the provided root keys
+ %% because the examples are all provided only with one (or maybe two) roots
+ %% and some roots have required fields.
+ RootKeys = maps:keys(Conf),
+ {ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts, RootKeys)};
+ {error, {parse_error, Reason}} ->
+ {error, Reason};
+ {error, Reason} ->
+ {error, Reason}
+ end.
diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index 9de6ef34a..6c0c511fb 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -3271,7 +3271,19 @@ tombstone() ->
tombstone_map(Name, Type) ->
%% marked_for_deletion must be the last member of the union
%% because we need to first union member to populate the default values
- map(Name, ?UNION([Type, ?TOMBSTONE_TYPE])).
+ map(
+ Name,
+ hoconsc:union(
+ fun
+ (all_union_members) ->
+ [Type, ?TOMBSTONE_TYPE];
+ ({value, V}) when is_map(V) ->
+ [Type];
+ ({value, _}) ->
+ [?TOMBSTONE_TYPE]
+ end
+ )
+ ).
%% inverse of mark_del_map
get_tombstone_map_value_type(Schema) ->
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index ce7bbb8b2..89fda6de8 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -154,6 +154,8 @@ fields("cluster") ->
sc(
node_array(),
#{
+ %% This config is nerver needed (since 5.0.0)
+ importance => ?IMPORTANCE_HIDDEN,
mapping => "mria.core_nodes",
default => [],
'readOnly' => true,
diff --git a/apps/emqx_conf/test/emqx_conf_schema_tests.erl b/apps/emqx_conf/test/emqx_conf_schema_tests.erl
index 76efd8ec4..855b8ff12 100644
--- a/apps/emqx_conf/test/emqx_conf_schema_tests.erl
+++ b/apps/emqx_conf/test/emqx_conf_schema_tests.erl
@@ -1,5 +1,17 @@
%%--------------------------------------------------------------------
-%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
+%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_conf_schema_tests).
@@ -488,3 +500,60 @@ check(Config) ->
atom_key => false, required => false, format => map
}),
emqx_utils_maps:unsafe_atom_key_map(Conf).
+
+with_file(Path, Content, F) ->
+ ok = file:write_file(Path, Content),
+ try
+ F()
+ after
+ file:delete(Path)
+ end.
+
+load_and_check_test_() ->
+ [
+ {"non-existing file", fun() ->
+ File = "/tmp/nonexistingfilename.hocon",
+ ?assertEqual(
+ {error, {enoent, File}},
+ emqx_hocon:load_and_check(emqx_conf_schema, File)
+ )
+ end},
+ {"bad syntax", fun() ->
+ %% use abs path to match error return
+ File = "/tmp/emqx-conf-bad-syntax-test.hocon",
+ with_file(
+ File,
+ "{",
+ fun() ->
+ ?assertMatch(
+ {error, #{file := File}},
+ emqx_hocon:load_and_check(emqx_conf_schema, File)
+ )
+ end
+ )
+ end},
+ {"type-check failure", fun() ->
+ File = "emqx-conf-type-check-failure.hocon",
+ %% typecheck fail because cookie is required field
+ with_file(
+ File,
+ "node {}",
+ fun() ->
+ ?assertMatch(
+ {error, #{
+ kind := validation_error,
+ path := "node.cookie",
+ reason := required_field
+ }},
+ emqx_hocon:load_and_check(emqx_conf_schema, File)
+ )
+ end
+ )
+ end},
+ {"ok load", fun() ->
+ File = "emqx-conf-test-tmp-file-load-ok.hocon",
+ with_file(File, "plugins: {}", fun() ->
+ ?assertMatch({ok, _}, emqx_hocon:load_and_check(emqx_conf_schema, File))
+ end)
+ end}
+ ].
diff --git a/apps/emqx_prometheus/src/emqx_prometheus.app.src b/apps/emqx_prometheus/src/emqx_prometheus.app.src
index 147dcc28f..7252e4436 100644
--- a/apps/emqx_prometheus/src/emqx_prometheus.app.src
+++ b/apps/emqx_prometheus/src/emqx_prometheus.app.src
@@ -2,7 +2,7 @@
{application, emqx_prometheus, [
{description, "Prometheus for EMQX"},
% strict semver, bump manually!
- {vsn, "5.0.12"},
+ {vsn, "5.0.13"},
{modules, []},
{registered, [emqx_prometheus_sup]},
{applications, [kernel, stdlib, prometheus, emqx, emqx_management]},
diff --git a/apps/emqx_prometheus/src/emqx_prometheus_schema.erl b/apps/emqx_prometheus/src/emqx_prometheus_schema.erl
index d657e0772..3300e8b28 100644
--- a/apps/emqx_prometheus/src/emqx_prometheus_schema.erl
+++ b/apps/emqx_prometheus/src/emqx_prometheus_schema.erl
@@ -86,61 +86,67 @@ fields("prometheus") ->
)},
{vm_dist_collector,
?HOCON(
- hoconsc:enum([enabled, disabled]),
+ hoconsc:enum([disabled, enabled]),
#{
- default => enabled,
+ default => disabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(vm_dist_collector)
}
)},
+ %% Mnesia metrics mainly using mnesia:system_info/1
{mnesia_collector,
?HOCON(
hoconsc:enum([enabled, disabled]),
#{
default => enabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(mnesia_collector)
}
)},
+ %% Collects Erlang VM metrics using erlang:statistics/1.
{vm_statistics_collector,
?HOCON(
hoconsc:enum([enabled, disabled]),
#{
default => enabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(vm_statistics_collector)
}
)},
+ %% Collects Erlang VM metrics using erlang:system_info/1.
{vm_system_info_collector,
?HOCON(
hoconsc:enum([enabled, disabled]),
#{
default => enabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(vm_system_info_collector)
}
)},
+ %% Collects information about memory dynamically allocated by the Erlang VM using erlang:memory/0,
+ %% it also provides basic (D)ETS statistics.
{vm_memory_collector,
?HOCON(
hoconsc:enum([enabled, disabled]),
#{
default => enabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(vm_memory_collector)
}
)},
+ %% Collects microstate accounting metrics using erlang:statistics(microstate_accounting).
{vm_msacc_collector,
?HOCON(
hoconsc:enum([enabled, disabled]),
#{
default => enabled,
required => true,
- importance => ?IMPORTANCE_HIDDEN,
+ importance => ?IMPORTANCE_LOW,
desc => ?DESC(vm_msacc_collector)
}
)}
diff --git a/examples/README.md b/examples/README.md
deleted file mode 100644
index 013939394..000000000
--- a/examples/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Examples
-
-Here are examples of how to configure features In EMQX, most of them can be used directly by copy-paste content into the `emqx.conf` file, others may need to be slightly modified to use, for example, you should change the listener port or HTTP URL to what you actually used.
-
-Although we have tried to show every configurable field in the example,
-you do not need to care about each one, since most of them already have default values and can be omitted in the configuration file.
-
-If you are confused about some fields, please refer to our documents, here are just some simple configuration examples with necessary descriptions.
-
-
-## Documentation
-
-The EMQX documentation is available at [www.emqx.io/docs/en/latest/](https://www.emqx.io/docs/en/latest/).
-
-The EMQX Enterprise documentation is available at [docs.emqx.com/en/](https://docs.emqx.com/en/).
-
diff --git a/examples/cluster-with-dns.conf.example b/examples/cluster-with-dns.conf.example
deleted file mode 100644
index ae617a808..000000000
--- a/examples/cluster-with-dns.conf.example
+++ /dev/null
@@ -1,30 +0,0 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery via DNS SRV records mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-cluster {
- ## Human-friendly name of the EMQX cluster.
- name = emqxcl
-
- ## Service discovery method for the cluster nodes
- discovery_strategy = dns
-
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
- ## If true, the node will try to heal network partitions automatically
- autoheal = true
-
- dns {
- ## The domain name from which to discover peer EMQX nodes' IP addresses
- name = localhost
-
- ## DNS record type
- ## Type: enum: a | srv
- record_type = a
- }
- }
diff --git a/examples/cluster-with-etcd-ssl.conf.example b/examples/cluster-with-etcd-ssl.conf.example
deleted file mode 100644
index d3a31c7d0..000000000
--- a/examples/cluster-with-etcd-ssl.conf.example
+++ /dev/null
@@ -1,81 +0,0 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery using 'etcd' service mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-cluster {
- ## Human-friendly name of the EMQX cluster.
- name = emqxcl
-
- ## Service discovery method for the cluster nodes
- discovery_strategy = etcd
-
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
- ## If true, the node will try to heal network partitions automatically
- autoheal = true
-
- etcd {
- ## List of endpoint URLs of the etcd cluster
- server = "http://ur1,http://ur2"
-
- ## Key prefix used for EMQX service discovery
- prefix = emqxcl
-
- ## Expiration time of the etcd key associated with the node.
- node_ttl = 1m
-
- ssl_options {
- ## Trusted PEM format CA certificates bundle file
- cacertfile = "data/certs/cacert.pem"
-
- ## PEM format certificates chain file
- certfile = "data/certs/cert.pem"
-
- ## PEM format private key file
- keyfile = "data/certs/key.pem"
-
- ## Enable or disable peer verification
- verify = verify_none ## use verify_peer to enable
-
- ## if `verify' is ebabled, whit true, the connection fails if the client does not have a certificate to send
- fail_if_no_peer_cert = false
-
- ## Enable TLS session reuse
- reuse_sessions = true
-
- ## Maximum number of non-self-issued intermediate certificates that can follow the peer certificate in a valid certification path
- depth = 10
-
- ## Which versions are to be supported
- versions = [tlsv1.3, tlsv1.2]
-
- ## TLS cipher suite names
- ## Note: By default, all available suites are supported, you do not need to set this
- ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
-
- ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
- secure_renegotiate = true
-
- ## Log level for SSL communication
- ## Type: emergency | alert | critical | error | warning | notice | info | debug | none | all
- log_level = notice
-
- ## Hibernate the SSL process after idling for amount of time reducing its memory footprint
- hibernate_after = 5s
-
- ## Forces the cipher to be set based on the server-specified order instead of the client-specified order
- honor_cipher_order = true
-
- ## Setting this to false to disable client-initiated renegotiation
- client_renegotiation = true
-
- ## Maximum time duration allowed for the handshake to complete
- handshake_timeout = 15s
- }
- }
-}
diff --git a/examples/cluster-with-manual.conf.example b/examples/cluster-with-manual.conf.example
deleted file mode 100644
index 7c031b44a..000000000
--- a/examples/cluster-with-manual.conf.example
+++ /dev/null
@@ -1,21 +0,0 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery via manual join mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-cluster {
- ## Human-friendly name of the EMQX cluster.
- name = emqxcl
-
- ## Service discovery method for the cluster nodes
- discovery_strategy = manual
-
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
- ## If true, the node will try to heal network partitions automatically
- autoheal = true
- }
diff --git a/examples/cluster-with-static.conf.example b/examples/cluster-with-static.conf.example
deleted file mode 100644
index e2263da15..000000000
--- a/examples/cluster-with-static.conf.example
+++ /dev/null
@@ -1,24 +0,0 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery via static nodes mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-cluster {
- ## Human-friendly name of the EMQX cluster.
- name = emqxcl
-
- ## Service discovery method for the cluster nodes
- discovery_strategy = static
-
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
- ## If true, the node will try to heal network partitions automatically
- autoheal = true
-
- ## List EMQX node names in the static cluster
- static.seeds = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
- }
diff --git a/examples/conn_congestion.conf.example b/examples/conn_congestion.conf.example
deleted file mode 100644
index e6f3597d1..000000000
--- a/examples/conn_congestion.conf.example
+++ /dev/null
@@ -1,15 +0,0 @@
-##--------------------------------------------------------------------
-## Connection Congestion
-##
-## Generating alarm when MQTT connection congested
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-conn_congestion {
- ## Enable or disable connection congestion alarm
- enable_alarm = true
-
- ## Minimal time before clearing the alarm
- min_alarm_sustain_duration = 1m
-}
diff --git a/examples/flapping_detect.conf.example b/examples/flapping_detect.conf.example
deleted file mode 100644
index b33a805ea..000000000
--- a/examples/flapping_detect.conf.example
+++ /dev/null
@@ -1,21 +0,0 @@
-##--------------------------------------------------------------------
-## Flapping Detect
-##
-## Ban the client when the times of connections exceed the limit in the time window
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-flapping_detect {
- ## use false to disabled
- enable = true
-
- ## Time window for flapping detection
- window_time = 1m
-
- ## Maximum number of connects allowed for a MQTT Client in window_time
- max_count = 15
-
- ## How long the flapping clientid will be banned
- ban_time = 5m
-}
diff --git a/examples/force_gc.conf.example b/examples/force_gc.conf.example
deleted file mode 100644
index e682d723d..000000000
--- a/examples/force_gc.conf.example
+++ /dev/null
@@ -1,18 +0,0 @@
-##--------------------------------------------------------------------
-## Force garbage collection
-##
-## Force garbage collection in MQTT connection process after they process certain number of messages or bytes of data
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-force_gc {
- ## set to false to disable this
- enable = true
-
- ## GC the process after this many received messages
- count = 16000
-
- ## GC the process after specified number of bytes have passed through
- bytes = 16MB
-}
diff --git a/examples/force_shutdown.conf.example b/examples/force_shutdown.conf.example
deleted file mode 100644
index b049691c6..000000000
--- a/examples/force_shutdown.conf.example
+++ /dev/null
@@ -1,19 +0,0 @@
-##--------------------------------------------------------------------
-## Force Shutdown
-##
-## Forced closing of the overloaded session
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-force_shutdown {
- ## false to disable this
- enable = true
-
- ## Maximum mailbox size for each Erlang process
- ## Note: Do not modify this unless you know what this is for
- max_mailbox_size = 1000
-
- ## Maximum heap size for each session process
- max_heap_size = 32MB
-}
diff --git a/examples/node.conf.example b/examples/node.conf.example
deleted file mode 100644
index 65c08b337..000000000
--- a/examples/node.conf.example
+++ /dev/null
@@ -1,43 +0,0 @@
-##--------------------------------------------------------------------
-## Node
-##
-## configuring for current EMQX node
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-## Note: all fields in this section are immutable after EMQX started, and most of the time you only need to modify the value for the name and cookie.
-node {
- ## The actions triggered when the alarm is activated
- ## Type: Formatted String
- ## Format: any_name@any_domain or an_name@any_ip
- ## Note: Make sure the IP resolve from the domain is deterministic and unique and never change
- name = "emqx@127.0.0.1"
-
- ## Secret cookie is a random string that should be the same on all nodes in the given EMQX cluster, but unique per EMQX cluster
- cookie = "Yzc0NGExM2RjYzYxYzM0YzQ5MWQ0NmI1NWM0MWRhMzY4NzgxYmFkMmI2MWJjZWQ5NTQzYTMxNjE1ODVmYmJmMyAgLQo="
-
- ## Select a node role
- ## Type:
- ## - core :: nodes provide durability of the data, and take care of writes
- ## - replicant :: nodes are ephemeral worker nodes
- role = core
-
- ## Maximum number of simultaneously existing processes for this Erlang system
- ## Type: Range from 1024 to 134217727
- process_limit = 2097152
-
- ## Maximum number of simultaneously existing ports for this Erlang system
- ## Type: Range from 1024 to 134217727
- max_ports = 1048576
-
- ## Erlang's distribution buffer busy limit in kilobytes
- ## Type: Range from 1 to 2097152
- dist_buffer_size = 8192
-
- ## Path to the persistent data directory
- data_dir = "var/emqx/data"
-
- ## Type: Periodic garbage collection interval
- global_gc_interval = 15m
-}
diff --git a/examples/prometheus.conf.example b/examples/prometheus.conf.example
deleted file mode 100644
index 645e10364..000000000
--- a/examples/prometheus.conf.example
+++ /dev/null
@@ -1,28 +0,0 @@
-##--------------------------------------------------------------------
-## Prometheus
-##
-## Settings for reporting metrics to Prometheus
-##--------------------------------------------------------------------
-
-prometheus {
- ## URL of Prometheus server
- push_gateway_server = "http://127.0.0.1:9091"
-
- ## Data reporting interval
- interval = 15s
-
- ## A HTTP Headers when pushing to Push Gateway.
- headers = {
- Authorization = "some-authz-tokens",
- Connection = "keep-alive"
- }
-
- ## Job Name that is pushed to the Push Gateway.
- ## Available variable:
- ## - ${name}: Name of EMQX node
- ## - ${host}: Host name of EMQX node
- job_name = "${name}/instance/${name}~${host}"
-
- ## set to false to enable this
- enable = true
-}
diff --git a/mix.exs b/mix.exs
index 67b58cff0..128fa06a5 100644
--- a/mix.exs
+++ b/mix.exs
@@ -539,11 +539,24 @@ defmodule EMQXUmbrella.MixProject do
profile = System.get_env("MIX_ENV")
File.cp_r!(
- "examples",
+ "rel/config/examples",
Path.join(etc, "examples"),
force: overwrite?
)
+ # copy /rel/config/ee-examples if profile is enterprise
+ case profile do
+ "emqx-enterprise" ->
+ File.cp_r!(
+ "rel/config/ee-examples",
+ Path.join(etc, "examples"),
+ force: overwrite?
+ )
+
+ _ ->
+ :ok
+ end
+
# this is required by the produced escript / nodetool
Mix.Generator.copy_file(
Path.join(release.version_path, "start_clean.boot"),
diff --git a/rebar.config.erl b/rebar.config.erl
index 085972554..0228be3ea 100644
--- a/rebar.config.erl
+++ b/rebar.config.erl
@@ -521,12 +521,12 @@ relx_overlay(ReleaseType, Edition) ->
{copy, "bin/nodetool", "bin/nodetool-{{release_version}}"}
] ++ etc_overlay(ReleaseType, Edition).
-etc_overlay(ReleaseType, _Edition) ->
+etc_overlay(ReleaseType, Edition) ->
Templates = emqx_etc_overlay(ReleaseType),
[
{mkdir, "etc/"},
- {copy, "{{base_dir}}/lib/emqx/etc/certs", "etc/"},
- {copy, "examples", "etc/"}
+ {copy, "{{base_dir}}/lib/emqx/etc/certs", "etc/"}
+ | copy_examples(Edition)
] ++
lists:map(
fun
@@ -536,6 +536,14 @@ etc_overlay(ReleaseType, _Edition) ->
Templates
).
+copy_examples(ce) ->
+ [{copy, "rel/config/examples", "etc/"}];
+copy_examples(ee) ->
+ [
+ {copy, "rel/config/examples", "etc/"},
+ {copy, "rel/config/ee-examples/*", "etc/examples/"}
+ ].
+
emqx_etc_overlay(ReleaseType) ->
emqx_etc_overlay_per_rel(ReleaseType) ++
emqx_etc_overlay().
diff --git a/examples/file_transfer-with-local-exporter.conf.example b/rel/config/ee-examples/file_transfer-with-local-exporter.conf.example
similarity index 74%
rename from examples/file_transfer-with-local-exporter.conf.example
rename to rel/config/ee-examples/file_transfer-with-local-exporter.conf.example
index 8dbd04f66..860826d38 100644
--- a/examples/file_transfer-with-local-exporter.conf.example
+++ b/rel/config/ee-examples/file_transfer-with-local-exporter.conf.example
@@ -1,12 +1,6 @@
-##--------------------------------------------------------------------
-## File Transfer
+## File Transfer over MQTT exporting files to local file system
##
-## Enables the File Transfer over MQTT feature
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-## Note: This configuration only works for the EMQX Enterprise version
+## NOTE: This configuration is only applicable in EMQX Enterprise edition 5.1 or later.
file_transfer {
## Enable the File Transfer feature
diff --git a/examples/file_transfer-with-s3-exporter.conf.example b/rel/config/ee-examples/file_transfer-with-s3-exporter.conf.example
similarity index 80%
rename from examples/file_transfer-with-s3-exporter.conf.example
rename to rel/config/ee-examples/file_transfer-with-s3-exporter.conf.example
index a59c7918c..497f5d645 100644
--- a/examples/file_transfer-with-s3-exporter.conf.example
+++ b/rel/config/ee-examples/file_transfer-with-s3-exporter.conf.example
@@ -1,12 +1,7 @@
-##--------------------------------------------------------------------
-## File Transfer
+## File Transfer over MQTT
##
## Enables the File Transfer over MQTT feature
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-## Note: This configuration only works for the EMQX Enterprise version
+## Note: This configuration is only applicable for EMQX Enterprise edition 5.1 or later.
file_transfer {
## Enable the File Transfer feature
@@ -62,9 +57,6 @@ file_transfer {
## Timeout for connection attempts
connect_timeout = 15s
-
- ## Attempt to talk through IPv6 first
- ipv6_probe = true
}
}
}
diff --git a/examples/license.conf.example b/rel/config/ee-examples/license.conf.example
similarity index 54%
rename from examples/license.conf.example
rename to rel/config/ee-examples/license.conf.example
index 7444ae795..2cb0dc3bd 100644
--- a/examples/license.conf.example
+++ b/rel/config/ee-examples/license.conf.example
@@ -1,12 +1,6 @@
-##--------------------------------------------------------------------
-## License
-##
-## Defines the EMQX Enterprise license
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## EMQX Enterprise License
-## Note: This configuration only works for the EMQX Enterprise version
+## NOTE: This configuration is only applicable for the EMQX Enterprise eidtion
license {
## License Key
diff --git a/rel/config/examples/README.md b/rel/config/examples/README.md
new file mode 100644
index 000000000..326b5c730
--- /dev/null
+++ b/rel/config/examples/README.md
@@ -0,0 +1,24 @@
+# Examples
+
+Here are examples of how to configure EMQX.
+The main purpose of the examples are to serve as a reference for configuration layout and syntax, but not a guide to how to configure EMQX.
+For more information about EMQX configuration, please refer to EMQX documentation (links below).
+
+There are two ways to extend the configuration of EMQX:
+
+* By adding the configs to `emqx.conf` file.
+* By adding the configs to a new file and include it in `emqx.conf` file. For example, add `include "mylisteners.conf"` to `emqx.conf` file and add the listeners to `mylisteners.conf`.
+
+EMQX configuration consists of two parts: static configs and dynamic configs.
+
+* Configs loaded from `emqx.conf` (and included files) are static configs.
+* Configs added or updated from the dashboard or CLI are dynamic configs which are synced to all nodes in the cluster and stored in the data directory on each node.
+
+It is important to note that static configs are loaded when EMQX starts and overlays on top of the dynamic configs,
+to avoid confusion, it is highly recommended NOT to use the same config name for both static and dynamic configs.
+
+## Documentation
+
+The EMQX documentation is available at [www.emqx.io/docs/en/latest/](https://www.emqx.io/docs/en/latest/).
+
+The EMQX Enterprise documentation is available at [docs.emqx.com/en/](https://docs.emqx.com/en/).
diff --git a/examples/alarm.conf.example b/rel/config/examples/alarm.conf.example
similarity index 55%
rename from examples/alarm.conf.example
rename to rel/config/examples/alarm.conf.example
index 537341ea2..e7f505b59 100644
--- a/examples/alarm.conf.example
+++ b/rel/config/examples/alarm.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## Alarm
-##
-## Configuring how to handle the alarms generated from sysmon.*.conf.example
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
alarm {
## The actions triggered when the alarm is activated
diff --git a/rel/config/examples/cluster-with-dns.conf.example b/rel/config/examples/cluster-with-dns.conf.example
new file mode 100644
index 000000000..4cade3b54
--- /dev/null
+++ b/rel/config/examples/cluster-with-dns.conf.example
@@ -0,0 +1,21 @@
+## Cluster discovery via DNS resolution
+
+cluster {
+ ## Human-friendly name of the EMQX cluster.
+ name = emqxcl
+
+ ## Service discovery method for the cluster nodes
+ discovery_strategy = dns
+
+ ## If true, the node will try to heal network partitions automatically
+ autoheal = true
+
+ dns {
+ ## The domain name from which to discover peer EMQX nodes' IP addresses
+ name = localhost
+
+ ## DNS record type
+ ## Type: enum: a | srv
+ record_type = a
+ }
+ }
diff --git a/rel/config/examples/cluster-with-etcd-ssl.conf.example b/rel/config/examples/cluster-with-etcd-ssl.conf.example
new file mode 100644
index 000000000..9f9486bae
--- /dev/null
+++ b/rel/config/examples/cluster-with-etcd-ssl.conf.example
@@ -0,0 +1,37 @@
+## Cluster discovery using 'etcd'
+## connect to etcd over TLS
+
+cluster {
+ name = emqxcl
+
+ ## Service discovery method for the cluster nodes
+ discovery_strategy = etcd
+
+ ## If true, the node will try to heal network partitions automatically
+ autoheal = true
+
+ etcd {
+ ## List of endpoint URLs of the etcd cluster
+ server = "http://ur1,http://ur2"
+
+ ## Key prefix used for EMQX service discovery
+ prefix = emqxcl
+
+ ## Expiration time of the etcd key associated with the node.
+ node_ttl = 1m
+
+ ssl_options {
+ ## Trusted PEM format CA certificates bundle file
+ cacertfile = "${EMQX_ETC_DIR}/certs/etcd-cacert.pem"
+
+ ## PEM format certificates chain file
+ certfile = "${EMQX_ETC_DIR}/certs/etcd-client-cert.pem"
+
+ ## PEM format private key file
+ keyfile = "${EMQX_ETC_DIR}/certs/etcd-client-key.pem"
+
+ ## Enable or disable peer verification
+ verify = verify_none ## use verify_peer to enable
+ }
+ }
+}
diff --git a/examples/cluster-with-etcd.conf.example b/rel/config/examples/cluster-with-etcd.conf.example
similarity index 51%
rename from examples/cluster-with-etcd.conf.example
rename to rel/config/examples/cluster-with-etcd.conf.example
index 3eae3b980..2ec888b42 100644
--- a/examples/cluster-with-etcd.conf.example
+++ b/rel/config/examples/cluster-with-etcd.conf.example
@@ -1,10 +1,5 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery using 'etcd' service mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Cluster discovery using 'etcd' service
+## Connect to etcd over plain TCP (not TLS)
cluster {
## Human-friendly name of the EMQX cluster.
@@ -13,9 +8,6 @@ cluster {
## Service discovery method for the cluster nodes
discovery_strategy = etcd
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
## If true, the node will try to heal network partitions automatically
autoheal = true
diff --git a/examples/cluster-with-k8s.conf.example b/rel/config/examples/cluster-with-k8s.conf.example
similarity index 55%
rename from examples/cluster-with-k8s.conf.example
rename to rel/config/examples/cluster-with-k8s.conf.example
index 7a0ad3b29..a24409a3c 100644
--- a/examples/cluster-with-k8s.conf.example
+++ b/rel/config/examples/cluster-with-k8s.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
-## Cluster in service discovery via Kubernetes API server mode
-##
-## Configs to instruct how individual nodes can discover each other
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Cluster discovery via Kubernetes API server mode
cluster {
## Human-friendly name of the EMQX cluster.
@@ -13,9 +7,6 @@ cluster {
## Service discovery method for the cluster nodes
discovery_strategy = k8s
- ## List of core nodes that the replicant will connect to
- core_nodes = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
-
## If true, the node will try to heal network partitions automatically
autoheal = true
diff --git a/rel/config/examples/cluster-with-manual.conf.example b/rel/config/examples/cluster-with-manual.conf.example
new file mode 100644
index 000000000..7df0f305f
--- /dev/null
+++ b/rel/config/examples/cluster-with-manual.conf.example
@@ -0,0 +1,12 @@
+## Cluster discovery via `emqx ctl cluster` command
+
+cluster {
+ ## Human-friendly name of the EMQX cluster.
+ name = emqxcl
+
+ ## Service discovery method for the cluster nodes
+ discovery_strategy = manual
+
+ ## If true, the node will try to heal network partitions automatically
+ autoheal = true
+ }
diff --git a/rel/config/examples/cluster-with-static.conf.example b/rel/config/examples/cluster-with-static.conf.example
new file mode 100644
index 000000000..7013ee7ad
--- /dev/null
+++ b/rel/config/examples/cluster-with-static.conf.example
@@ -0,0 +1,15 @@
+## Cluster discovery via static seed nodes
+
+cluster {
+ ## Human-friendly name of the EMQX cluster.
+ name = emqxcl
+
+ ## Service discovery method for the cluster nodes
+ discovery_strategy = static
+
+ ## If true, the node will try to heal network partitions automatically
+ autoheal = true
+
+ ## List EMQX node names in the static cluster
+ static.seeds = ["emqx1@192.168.0.1", "emqx2@192.168.0.2"]
+ }
diff --git a/rel/config/examples/conn_congestion.conf.example b/rel/config/examples/conn_congestion.conf.example
new file mode 100644
index 000000000..785ee5ab5
--- /dev/null
+++ b/rel/config/examples/conn_congestion.conf.example
@@ -0,0 +1,11 @@
+## Connection Congestion
+##
+## Emit alarms when MQTT connection congested
+
+conn_congestion {
+ ## Enable or disable connection congestion alarm
+ enable_alarm = true
+
+ ## Minimal time before clearing the alarm
+ min_alarm_sustain_duration = 1m
+}
diff --git a/examples/dashboard-with-http.conf.example b/rel/config/examples/dashboard-with-http.conf.example
similarity index 72%
rename from examples/dashboard-with-http.conf.example
rename to rel/config/examples/dashboard-with-http.conf.example
index 8cf68ab33..e6107e116 100644
--- a/examples/dashboard-with-http.conf.example
+++ b/rel/config/examples/dashboard-with-http.conf.example
@@ -1,10 +1,6 @@
-##--------------------------------------------------------------------
-## Dashboard with HTTP Listener
+## Dashboard on HTTP
##
-## Configuration for EMQX dashboard
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Configure HTTP for EMQX dashboard
dashboard {
## JWT token expiration time
diff --git a/examples/dashboard-with-https.conf.example b/rel/config/examples/dashboard-with-https.conf.example
similarity index 88%
rename from examples/dashboard-with-https.conf.example
rename to rel/config/examples/dashboard-with-https.conf.example
index 5cc277e47..8e15077e0 100644
--- a/examples/dashboard-with-https.conf.example
+++ b/rel/config/examples/dashboard-with-https.conf.example
@@ -1,10 +1,6 @@
-##--------------------------------------------------------------------
-## Dashboard with HTTPS Listener
+## Dashboard on HTTPS
##
-## Configuration for EMQX dashboard
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Configure HTTPS for EMQX dashboard
dashboard {
## JWT token expiration time
diff --git a/examples/delayed.conf.example b/rel/config/examples/delayed.conf.example
similarity index 100%
rename from examples/delayed.conf.example
rename to rel/config/examples/delayed.conf.example
diff --git a/examples/exhook.conf.example b/rel/config/examples/exhook.conf.example
similarity index 86%
rename from examples/exhook.conf.example
rename to rel/config/examples/exhook.conf.example
index 8adcfcab9..cf9fffc71 100644
--- a/examples/exhook.conf.example
+++ b/rel/config/examples/exhook.conf.example
@@ -1,8 +1,6 @@
-##--------------------------------------------------------------------
## gRPC Hook Extension
##
-## Allows users to process EMQX Hooks using other programming languages
-##--------------------------------------------------------------------
+## Allows users to provide hook callbacks over gRPC for EMQX message lifecycle events.
exhook.servers = [
{
diff --git a/rel/config/examples/flapping_detect.conf.example b/rel/config/examples/flapping_detect.conf.example
new file mode 100644
index 000000000..fe4522b1e
--- /dev/null
+++ b/rel/config/examples/flapping_detect.conf.example
@@ -0,0 +1,17 @@
+## Flapping Detect
+##
+## Ban the client when the times of connections exceed the limit in the configured time window
+
+flapping_detect {
+ ## use 'true' to enable this feature
+ enable = false
+
+ ## Time window for flapping detection
+ window_time = 1m
+
+ ## Maximum number of connects allowed for a MQTT Client in window_time
+ max_count = 15
+
+ ## How long the flapping clientid will be banned
+ ban_time = 5m
+}
diff --git a/rel/config/examples/force_gc.conf.example b/rel/config/examples/force_gc.conf.example
new file mode 100644
index 000000000..ee07ee4d2
--- /dev/null
+++ b/rel/config/examples/force_gc.conf.example
@@ -0,0 +1,12 @@
+## Force Elrang VM garbage collection
+
+force_gc {
+ ## set 'false' to disable this feature
+ enable = true
+
+ ## GC the process after this many received messages
+ count = 16000
+
+ ## GC the process after specified number of bytes have passed through
+ bytes = 16MB
+}
diff --git a/rel/config/examples/force_shutdown.conf.example b/rel/config/examples/force_shutdown.conf.example
new file mode 100644
index 000000000..d0a466aa0
--- /dev/null
+++ b/rel/config/examples/force_shutdown.conf.example
@@ -0,0 +1,15 @@
+## Force Shutdown
+##
+## Forced shutdown MQTT clients for overload protection
+
+force_shutdown {
+ ## set 'false' to disable force shutdown feature
+ enable = true
+
+ ## Maximum mailbox size for each Erlang process
+ ## Note: Do not modify this unless you know what this is for
+ max_mailbox_size = 1000
+
+ ## Maximum heap size for each session process
+ max_heap_size = 32MB
+}
diff --git a/examples/gateway.coap.conf.example b/rel/config/examples/gateway.coap.conf.example
similarity index 100%
rename from examples/gateway.coap.conf.example
rename to rel/config/examples/gateway.coap.conf.example
diff --git a/examples/gateway.exproto.conf.example b/rel/config/examples/gateway.exproto.conf.example
similarity index 67%
rename from examples/gateway.exproto.conf.example
rename to rel/config/examples/gateway.exproto.conf.example
index 04c95d98c..fcedb944b 100644
--- a/examples/gateway.exproto.conf.example
+++ b/rel/config/examples/gateway.exproto.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## Gateway Exproto
-##
-## Add an Exproto gateway
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
gateway.exproto {
diff --git a/examples/gateway.lwm2m.conf.example b/rel/config/examples/gateway.lwm2m.conf.example
similarity index 87%
rename from examples/gateway.lwm2m.conf.example
rename to rel/config/examples/gateway.lwm2m.conf.example
index 2c9b55c04..60943f47c 100644
--- a/examples/gateway.lwm2m.conf.example
+++ b/rel/config/examples/gateway.lwm2m.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## Gateway LwM2M
-##
-## Add a LwM2M gateway
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
gateway.lwm2m {
diff --git a/examples/gateway.mqttsn.conf.example b/rel/config/examples/gateway.mqttsn.conf.example
similarity index 77%
rename from examples/gateway.mqttsn.conf.example
rename to rel/config/examples/gateway.mqttsn.conf.example
index 7785454f3..aac7d6898 100644
--- a/examples/gateway.mqttsn.conf.example
+++ b/rel/config/examples/gateway.mqttsn.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## Gateway MQTT-SN
-##
-## Add a MQTT-SN gateway
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
gateway.mqttsn {
diff --git a/examples/gateway.stomp.conf.example b/rel/config/examples/gateway.stomp.conf.example
similarity index 66%
rename from examples/gateway.stomp.conf.example
rename to rel/config/examples/gateway.stomp.conf.example
index ab09a45f7..e90a04620 100644
--- a/examples/gateway.stomp.conf.example
+++ b/rel/config/examples/gateway.stomp.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## Gateway STOMP
-##
-## Add STOMP CoAP gateway
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
gateway.stomp {
diff --git a/examples/listeners.quic.conf.example b/rel/config/examples/listeners.quic.conf.example
similarity index 65%
rename from examples/listeners.quic.conf.example
rename to rel/config/examples/listeners.quic.conf.example
index 49d4f58a1..52161e828 100644
--- a/examples/listeners.quic.conf.example
+++ b/rel/config/examples/listeners.quic.conf.example
@@ -1,13 +1,6 @@
-##--------------------------------------------------------------------
-## QUIC Listener
-##
-## Add a QUIC Listener
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT over QUIC Listener
-## Note: Modifying the 'quicname' to what you need
-listeners.quic.quicname {
+listeners.quic.my_quick_listener_name {
## Port or Address to listen on, 0 means disable
bind = 14567 ## or with an IP, e.g. "127.0.0.1:14567"
@@ -28,8 +21,8 @@ listeners.quic.quicname {
## Type: infinity | Integer
max_connections = infinity
- ## TLS cipher suite names
- ciphers = ["TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256"]
+ ## TLS v1.3 exclusive cipher suite names
+ ciphers = "TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_CHACHA20_POLY1305_SHA256"
ssl_options {
## Trusted PEM format CA certificates bundle file
diff --git a/examples/listeners.ssl.conf.example b/rel/config/examples/listeners.ssl.conf.example
similarity index 76%
rename from examples/listeners.ssl.conf.example
rename to rel/config/examples/listeners.ssl.conf.example
index 11078db6c..4a74f1a27 100644
--- a/examples/listeners.ssl.conf.example
+++ b/rel/config/examples/listeners.ssl.conf.example
@@ -1,16 +1,6 @@
-##--------------------------------------------------------------------
-## SSL Listener
-##
-## Add a SSL Listener
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT over TLS(SSL) Listener
-## The SSL listener also supports all the fields listed in listeners.tcp.conf.example
-## only the SSL-specific fields are shown here
-
-## Note: Modifying the 'sslname' to what you need
-listeners.ssl.sslname {
+listeners.ssl.my_ssl_listener_name {
## Port or Address to listen on, 0 means disable
bind = 8883 ## or with an IP e.g. "127.0.0.1:8883"
enabled = true
@@ -33,13 +23,13 @@ listeners.ssl.sslname {
}
ssl_options {
## Trusted PEM format CA certificates bundle file
- cacertfile = "data/certs/cacert.pem"
+ cacertfile = "${EMQX_ETC_DIR}/certs/cacert.pem"
## PEM format certificates chain file
- certfile = "data/certs/cert.pem"
+ certfile = "${EMQX_ETC_DIR}/certs/cert.pem"
## PEM format private key file
- keyfile = "data/certs/key.pem"
+ keyfile = "${EMQX_ETC_DIR}/certs/key.pem"
## Enable or disable peer verification
verify = verify_none ## use verify_peer to enable
@@ -58,7 +48,7 @@ listeners.ssl.sslname {
## TLS cipher suite names
## Note: By default, all available suites are supported, you do not need to set this
- ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+ ciphers = "TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,ECDHE-RSA-AES256-GCM-SHA384"
## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
secure_renegotiate = true
@@ -82,7 +72,7 @@ listeners.ssl.sslname {
ocsp {
enable_ocsp_stapling = false
responder_url = "http://ocsp.example.com"
- issuer_pem = true
+ issuer_pem = "${EMQX_ETC_DIR}/certs/ocsp-issuer-cert.pem"
refresh_http_timeout = 15s
refresh_interval = 5m
}
diff --git a/examples/listeners.tcp.conf.example b/rel/config/examples/listeners.tcp.conf.example
similarity index 87%
rename from examples/listeners.tcp.conf.example
rename to rel/config/examples/listeners.tcp.conf.example
index 42e98b071..f03d98cc2 100644
--- a/examples/listeners.tcp.conf.example
+++ b/rel/config/examples/listeners.tcp.conf.example
@@ -1,13 +1,6 @@
-##--------------------------------------------------------------------
-## TCP Listener
-##
-## Add a TCP Listener
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT over TCP Listener
-## Note: Modifying the 'tcpname' to what you need
-listeners.tcp.tcpname {
+listeners.tcp.my_tcp_listener_name {
## Port or Address to listen on, 0 means disable
bind = 1883 ## or with an IP e.g. "127.0.0.1:1883"
diff --git a/examples/listeners.ws.conf.example b/rel/config/examples/listeners.ws.conf.example
similarity index 80%
rename from examples/listeners.ws.conf.example
rename to rel/config/examples/listeners.ws.conf.example
index 60523ac7a..f6a6adae8 100644
--- a/examples/listeners.ws.conf.example
+++ b/rel/config/examples/listeners.ws.conf.example
@@ -1,16 +1,6 @@
-##--------------------------------------------------------------------
-## WebSocket Listener
-##
-## Add a WebSocket Listener
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT over WebSocket (HTTP) Listener
-## The WebSocket listener supports all the fields listed in listeners.tcp.conf.example
-## only the WebSocket-specific fields are shown here
-
-## Note: Modifying the 'wsname' to what you need
-listeners.ws.wsname {
+listeners.ws.my_ws_listener_name {
## Port or Address to listen on, 0 means disable
bind = "0.0.0.0:8083" # or just a port number, e.g. 8083
enabled = true
diff --git a/examples/listeners.wss.conf.example b/rel/config/examples/listeners.wss.conf.example
similarity index 82%
rename from examples/listeners.wss.conf.example
rename to rel/config/examples/listeners.wss.conf.example
index 799d082d7..cbc632e30 100644
--- a/examples/listeners.wss.conf.example
+++ b/rel/config/examples/listeners.wss.conf.example
@@ -1,16 +1,6 @@
-##--------------------------------------------------------------------
-## WSS Listener
-##
-## Add a WSS Listener
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT over Secured Websocket (HTTPS) Listener
-## The WSS listener supports all the fields listed in listeners.ws.conf.example
-## only the WSS-specific fields are shown here
-
-## Note: Modifying the 'wssname' to what you need
-listeners.wss.wssname {
+listeners.wss.my_wss_listener_name = {
## Port or Address to listen on, 0 means disable
bind = 8084 ## or with an IP, e.g. "127.0.0.1:8084"
enabled = true
@@ -76,11 +66,11 @@ listeners.wss.wssname {
depth = 10
## Which versions are to be supported
- versions = [tlsv1.3, tlsv1.2]
+ versions = ["tlsv1.3", "tlsv1.2"]
## TLS cipher suite names
## Note: By default, all available suites are supported, you do not need to set this
- ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256"]
+ ciphers = "TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,ECDHE-RSA-AES256-GCM-SHA384"
## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
secure_renegotiate = true
diff --git a/examples/log.console.conf.example b/rel/config/examples/log.console.conf.example
similarity index 59%
rename from examples/log.console.conf.example
rename to rel/config/examples/log.console.conf.example
index 1dd30e120..9bb01b0d9 100644
--- a/examples/log.console.conf.example
+++ b/rel/config/examples/log.console.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
-## Log
-##
-## Configure the log output location, log level, log file storage path, and parameters
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Log to console
log.console {
## set true to enable this
diff --git a/examples/log.file.conf.example b/rel/config/examples/log.file.conf.example
similarity index 57%
rename from examples/log.file.conf.example
rename to rel/config/examples/log.file.conf.example
index deb9b16b9..e6f408f61 100644
--- a/examples/log.file.conf.example
+++ b/rel/config/examples/log.file.conf.example
@@ -1,21 +1,14 @@
-##--------------------------------------------------------------------
-## Log
-##
-## Configure the log output location, log level, log file storage path, and parameters
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## Log to file
-## The default-enabled log handler can use all the above fields listed fields
log.file {
- ## use false to disable this
+ ## Enable file log handler
enable = true
## Log level
## Type: debug | info | notice | warning | error | critical | alert | emergency
level = warning
- ## Log formatter, text for free text, and json for structured logging
+ ## Log formatter, text for free text, and json for more structured logging
## Type: text | json
formatter = text
diff --git a/examples/mqtt.conf.example b/rel/config/examples/mqtt.conf.example
similarity index 93%
rename from examples/mqtt.conf.example
rename to rel/config/examples/mqtt.conf.example
index c5f81f753..64c73524c 100644
--- a/examples/mqtt.conf.example
+++ b/rel/config/examples/mqtt.conf.example
@@ -1,10 +1,5 @@
-##--------------------------------------------------------------------
-## MQTT
-##
-## MQTT configuration
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## MQTT protocol related settings
+## Settings in this section is applied globally to all MQTT connections/sessions in this node
mqtt {
## After the TCP connection is established,
@@ -121,4 +116,4 @@ mqtt {
## - hash_clientid :: select the subscribers by hashing the `clientIds`
## - hash_topic :: select the subscribers by hashing the source topic"""
shared_subscription_strategy = round_robin
- }
+}
diff --git a/rel/config/examples/node.conf.example b/rel/config/examples/node.conf.example
new file mode 100644
index 000000000..596e9884d
--- /dev/null
+++ b/rel/config/examples/node.conf.example
@@ -0,0 +1,39 @@
+## EMQX Node
+
+## Note: all fields in this section are immutable after EMQX started, and most of the time you only need to modify the value for the name and cookie.
+node {
+ ## The actions triggered when the alarm is activated
+ ## Type: Formatted String
+ ## Format: any_name@any_domain or an_name@any_ip
+ ## Note: Make sure the IP resolve from the domain is deterministic and unique and never change
+ name = "emqx@127.0.0.1"
+
+ ## Secret cookie is a random string that should be the same on all nodes in the cluster, but unique per EMQX cluster
+ cookie = "Yzc0NGExM2Rj"
+
+ ## Select a node role
+ ## Possible values:
+ ## - core: This is a core node which provides durability of the client states, and takes care of writes
+ ## - replicant: This is a stateless worker node
+ role = core
+
+ ## Maximum number of simultaneously existing processes for this Erlang system
+ process_limit = 2097152
+
+ ## Maximum number of simultaneously open files and sockets for this Erlang system
+ max_ports = 1048576
+
+ ## Erlang's distribution buffer busy limit in kilobytes.
+ ## Range from 1 to 2097152
+ dist_buffer_size = 8192
+
+ ## NOTE: keep this the same for all nodes in the cluster.
+ ## Path to the persistent data directory.
+ ## This config is pre-filled when the EMQX distribution package is built.
+ ## You are advised to use the default value.
+ data_dir = "data" # when running a zip package or in docker container
+ #data_dir = "/var/lib/emqx" # when installed from deb/rpm packages
+
+ ## Type: Periodic garbage collection interval
+ global_gc_interval = 15m
+}
diff --git a/examples/plugin.conf.example b/rel/config/examples/plugins.conf.example
similarity index 63%
rename from examples/plugin.conf.example
rename to rel/config/examples/plugins.conf.example
index d704f9981..6fcc09cbb 100644
--- a/examples/plugin.conf.example
+++ b/rel/config/examples/plugins.conf.example
@@ -1,12 +1,5 @@
-##--------------------------------------------------------------------
-## Plugin
-##
-## Manage EMQX plugins
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
-
-plugin {
+## Plugin management
+plugins {
## Plugins declaration
## Note: The plugins are started in the defined order
states = [
diff --git a/rel/config/examples/prometheus-pushgateway.conf.example b/rel/config/examples/prometheus-pushgateway.conf.example
new file mode 100644
index 000000000..70b74794a
--- /dev/null
+++ b/rel/config/examples/prometheus-pushgateway.conf.example
@@ -0,0 +1,28 @@
+## Prometheus push-gateway integration
+
+## EMQX's Prometheus scraping endpoint is enabled by default without authentication.
+## e.g. curl -f "127.0.0.1:18083/api/v5/prometheus/stats"
+## If you want to use push-gateway
+
+prometheus {
+ ## Set to true to make EMQX send metrics to push-gateway
+ enable = false
+
+ ## URL of push-gateway server
+ push_gateway_server = "http://127.0.0.1:9091"
+
+ ## Data push interval
+ interval = 15s
+
+ ## A HTTP Headers when pushing to Push-gateway
+ headers = {
+ Authorization = "some-authz-tokens",
+ Connection = "keep-alive"
+ }
+
+ ## Job Name that is pushed to the Push-gateway
+ ## Available variable:
+ ## - ${name}: Name of EMQX node
+ ## - ${host}: Host name of EMQX node
+ job_name = "${name}/instance/${name}~${host}"
+}
diff --git a/rel/config/examples/prometheus.conf.example b/rel/config/examples/prometheus.conf.example
new file mode 100644
index 000000000..3b186e93f
--- /dev/null
+++ b/rel/config/examples/prometheus.conf.example
@@ -0,0 +1,10 @@
+## Prometheus
+
+## EMQX's Prometheus scraping endpoint is enabled by default without authentication.
+## And there is no way to turn it off.
+## You can inspect it with a curl command: curl -f "127.0.0.1:18083/api/v5/prometheus/stats"
+
+prometheus {
+ # turn off this expensive collector
+ vm_dist_collector = disabled
+}
diff --git a/examples/psk_authentication.conf.example b/rel/config/examples/psk_authentication.conf.example
similarity index 54%
rename from examples/psk_authentication.conf.example
rename to rel/config/examples/psk_authentication.conf.example
index 272eb41b5..6c3482638 100644
--- a/examples/psk_authentication.conf.example
+++ b/rel/config/examples/psk_authentication.conf.example
@@ -1,13 +1,7 @@
-##--------------------------------------------------------------------
## Pre-Shared Keys authentication
-##
-## Config to enable TLS-PSK authentication
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
psk_authentication {
- ## set to false to disable
+ ## Set to false to disable
enable = true
## If init_file is specified, EMQX will import PSKs from the file into the built-in database at startup for use by the runtime
diff --git a/examples/retainer.conf.example b/rel/config/examples/retainer.conf.example
similarity index 64%
rename from examples/retainer.conf.example
rename to rel/config/examples/retainer.conf.example
index 1cef31c30..51101c9c7 100644
--- a/examples/retainer.conf.example
+++ b/rel/config/examples/retainer.conf.example
@@ -3,20 +3,12 @@
##
## Configuration related to handling PUBLISH packets with a retain flag set to 1
##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
retainer {
- ## set to false to disable this
+ ## set to false to disable retainer
enable = true
- ## Message retention time. 0 means message will never be expired
- msg_expiry_interval = 0s
-
- ## Periodic interval for cleaning up expired messages. Never clear if the value is 0
- msg_clear_interval = 0s
-
- ## Maximum retained message size
+ ## Maximum message size allowed
max_payload_size = 1MB
## When the retained flag of the PUBLISH message is set and Payload is empty, whether to continue to publish the message
@@ -27,10 +19,10 @@ retainer {
## Retained messages store backend
backend {
- ## Backend type
+ ## Built-in database (Mnesia)
type = built_in_database
- ## Specifies whether the messages are stored in RAM or persisted on disc
+ ## Specifies whether the messages are stored in RAM or persisted on disk
## Type: enum: ram | disc
storage_type = ram
diff --git a/examples/sys_topics.conf.example b/rel/config/examples/sys_topics.conf.example
similarity index 65%
rename from examples/sys_topics.conf.example
rename to rel/config/examples/sys_topics.conf.example
index b249efd35..e4d0611b1 100644
--- a/examples/sys_topics.conf.example
+++ b/rel/config/examples/sys_topics.conf.example
@@ -1,10 +1,5 @@
-##--------------------------------------------------------------------
## System Topic
-##
## Publishing client lifecycle events to "$SYS" topics
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
sys_topics {
## Time interval of publishing `$SYS` messages
diff --git a/examples/sysmon.os.conf.example b/rel/config/examples/sysmon.os.conf.example
similarity index 59%
rename from examples/sysmon.os.conf.example
rename to rel/config/examples/sysmon.os.conf.example
index 95e7aa1ec..08e025da0 100644
--- a/examples/sysmon.os.conf.example
+++ b/rel/config/examples/sysmon.os.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
-## System Monitoring For System
-##
-## System monitoring and introspection
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
+## System Monitoring of the host machine
sysmon.os {
## Time interval for the periodic CPU check
@@ -17,9 +11,9 @@ sysmon.os {
cpu_low_watermark = 60%
## Time interval for the periodic memory check
- ## Type:
- ## - disabled :: Never check
- ## - Time Duration :: The time period
+ ## Possible values:
+ ## disabled: Never check
+ ## Duration: Check every Duration
mem_check_interval = 60s
## For how much system memory can be allocated before the corresponding alarm is raised
diff --git a/examples/sysmon.vm.conf.example b/rel/config/examples/sysmon.vm.conf.example
similarity index 76%
rename from examples/sysmon.vm.conf.example
rename to rel/config/examples/sysmon.vm.conf.example
index d68141cea..6ca6ee411 100644
--- a/examples/sysmon.vm.conf.example
+++ b/rel/config/examples/sysmon.vm.conf.example
@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
## System Monitoring For Erlang VM
-##
-## System monitoring and introspection
-##--------------------------------------------------------------------
-## Note: This is an example of how to configure this feature
-## you should copy and paste the below data into the emqx.conf for working
sysmon.vm {
## Time interval for the periodic process limit check
@@ -25,7 +19,7 @@ sysmon.vm {
## Generating an alarm is generated when the Erlang VM detect a task scheduled for too long
## Type:
## - disabled :: Never alarm
- ## - Time During :: The maximum schedule time for generating an alarm
+ ## - Duration:: The maximum schedule time for generating an alarm
long_schedule = 240ms
## Generating an alarm when an Erlang process consumed a large amount of memory for its heap space
diff --git a/rel/i18n/emqx_conf_schema.hocon b/rel/i18n/emqx_conf_schema.hocon
index 416b3ca76..bc45fa009 100644
--- a/rel/i18n/emqx_conf_schema.hocon
+++ b/rel/i18n/emqx_conf_schema.hocon
@@ -135,7 +135,7 @@ log_overload_kill_restart_after.label:
"""Handler Restart Timer"""
log_file_handler_max_size.desc:
-"""This parameter controls log file rotation. The value `infinity` means the log file will grow indefinitely, otherwise the log file will be rotated once it reaches `max_size` in bytes."""
+"""This parameter controls log file rotation. The value `infinity` means the log file will grow indefinitely, otherwise the log file will be rotated once it reaches `rotation_size` in bytes."""
log_file_handler_max_size.label:
"""Rotation Size"""
@@ -389,17 +389,6 @@ cluster_mcast_ttl.desc:
cluster_mcast_ttl.label:
"""Cluster Multicast TTL"""
-db_core_nodes.desc:
-"""List of core nodes that the replicant will connect to.
-Note: this parameter only takes effect when the backend
is set
-to rlog
and the role
is set to replicant
.
-This value needs to be defined for manual or static cluster discovery mechanisms.
-If an automatic cluster discovery mechanism is being used (such as etcd
),
-there is no need to set this value."""
-
-db_core_nodes.label:
-"""Db Core Node"""
-
log_file_handler_file.desc:
"""Name the log file."""
@@ -514,15 +503,13 @@ cluster_autoclean.label:
process_limit.desc:
"""Maximum number of simultaneously existing processes for this Erlang system.
-The actual maximum chosen may be much larger than the Number passed.
For more information, see: https://www.erlang.org/doc/man/erl.html"""
process_limit.label:
"""Erlang Process Limit"""
max_ports.desc:
-"""Maximum number of simultaneously existing ports for this Erlang system.
-The actual maximum chosen may be much larger than the Number passed.
+"""Maximum number of simultaneously open files and sockets for this Erlang system.
For more information, see: https://www.erlang.org/doc/man/erl.html"""
max_ports.label:
diff --git a/rel/i18n/emqx_prometheus_schema.hocon b/rel/i18n/emqx_prometheus_schema.hocon
index d68e1d418..d665343e9 100644
--- a/rel/i18n/emqx_prometheus_schema.hocon
+++ b/rel/i18n/emqx_prometheus_schema.hocon
@@ -18,30 +18,32 @@ For example, when the EMQX node name is emqx@127.0.0.1
then the ${name}/instance/${name}~${host}"""
mnesia_collector.desc:
-"""Enable or disable Mnesia collector, collects Mnesia metrics mainly using mnesia:system_info/1 ."""
+"""Enable or disable Mnesia metrics collector"""
prometheus.desc:
-"""Settings for reporting metrics to Prometheus"""
+"""EMQX's Prometheus scraping endpoint is enabled by default without authentication.
+You can inspect it with a `curl` command like this: `curl -f "127.0.0.1:18083/api/v5/prometheus/stats"`
+The 'enable' flag is used to turn on and off for the push-gateway integration."""
prometheus.label:
"""Prometheus"""
push_gateway_server.desc:
-"""URL of Prometheus server"""
+"""URL of Prometheus server. Pushgateway is optional, should not be configured if prometheus is to scrape EMQX."""
vm_dist_collector.desc:
"""Enable or disable VM distribution collector, collects information about the sockets and processes involved in the Erlang distribution mechanism."""
vm_memory_collector.desc:
-"""Enable or disable VM memory collector, collects information about memory dynamically allocated by the Erlang emulator using erlang:memory/0 , also provides basic (D)ETS statistics ."""
+"""Enable or disable VM memory metrics collector."""
vm_msacc_collector.desc:
-"""Enable or disable VM msacc collector, collects microstate accounting metrics using erlang:statistics(microstate_accounting) ."""
+"""Enable or disable VM microstate accounting metrics collector."""
vm_statistics_collector.desc:
-"""Enable or disable VM statistics collector, collects Erlang VM metrics using erlang:statistics/1 ."""
+"""Enable or disable VM statistics collector."""
vm_system_info_collector.desc:
-"""Enable or disable VM system info collector, collects Erlang VM metrics using erlang:system_info/1 ."""
+"""Enable or disable VM system info collector."""
}
diff --git a/rel/i18n/emqx_retainer_schema.hocon b/rel/i18n/emqx_retainer_schema.hocon
index 49b55d259..e6679dbf7 100644
--- a/rel/i18n/emqx_retainer_schema.hocon
+++ b/rel/i18n/emqx_retainer_schema.hocon
@@ -34,11 +34,11 @@ mnesia_config_type.desc:
"""Backend type."""
msg_clear_interval.desc:
-"""Periodic interval for cleaning up expired messages.
-Never clear if the value is 0."""
+"""Interval for EMQX to scan expired messages and delete them. Never scan if the value is 0."""
msg_expiry_interval.desc:
-"""Message retention time. 0 means message will never be expired."""
+"""Message retention time. This config is only applicable for messages without the Message Expiry Interval message property.
+0 means message will never expire."""
stop_publish_clear_msg.desc:
"""When the retained flag of the `PUBLISH` message is set and Payload is empty,
diff --git a/scripts/test/check-example-configs.sh b/scripts/test/check-example-configs.sh
new file mode 100755
index 000000000..f71fb15eb
--- /dev/null
+++ b/scripts/test/check-example-configs.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+PROJ_DIR="$(git rev-parse --show-toplevel)"
+
+PROFILE="${PROFILE:-emqx}"
+DIR_NAME='examples'
+SCHEMA_MOD='emqx_conf_schema'
+if [ "${PROFILE}" = 'emqx-enterprise' ]; then
+ DIR_NAME='ee-examples'
+ SCHEMA_MOD='emqx_enterprise_schema'
+fi
+
+IFS=$'\n' read -r -d '' -a FILES < <(find "${PROJ_DIR}/rel/config/${DIR_NAME}" -name "*.example" 2>/dev/null | sort && printf '\0')
+
+prepare_erl_libs() {
+ local libs_dir="$1"
+ local erl_libs="${ERL_LIBS:-}"
+ local sep=':'
+ for app in "${libs_dir}"/*; do
+ if [ -d "${app}/ebin" ]; then
+ if [ -n "$erl_libs" ]; then
+ erl_libs="${erl_libs}${sep}${app}"
+ else
+ erl_libs="${app}"
+ fi
+ fi
+ done
+ export ERL_LIBS="$erl_libs"
+}
+
+# This is needed when checking schema
+export EMQX_ETC_DIR="${PROJ_DIR}/apps/emqx/etc"
+
+prepare_erl_libs "_build/$PROFILE/lib"
+
+check_file() {
+ local file="$1"
+ erl -noshell -eval \
+ "File=\"$file\",
+ case emqx_hocon:load_and_check($SCHEMA_MOD, File) of
+ {ok, _} ->
+ io:format(\"check_example_config_ok: ~s~n\", [File]),
+ halt(0);
+ {error, Reason} ->
+ io:format(\"failed_to_check_example_config: ~s~n~p~n\", [File, Reason]),
+ halt(1)
+ end."
+}
+
+for file in "${FILES[@]}"; do
+ check_file "$file"
+done