Bläddra i källkod

Merge pull request #11127 from zmstone/0622-refine-examples

0622 refine examples
Zaiming (Stone) Shi 2 år sedan
förälder
incheckning
4ed422cb9a
65 ändrade filer med 540 tillägg och 590 borttagningar
  1. 24 0
      .github/workflows/run_test_cases.yaml
  2. 27 1
      apps/emqx/src/emqx_hocon.erl
  3. 13 1
      apps/emqx/src/emqx_schema.erl
  4. 2 0
      apps/emqx_conf/src/emqx_conf_schema.erl
  5. 70 1
      apps/emqx_conf/test/emqx_conf_schema_tests.erl
  6. 1 1
      apps/emqx_prometheus/src/emqx_prometheus.app.src
  7. 14 8
      apps/emqx_prometheus/src/emqx_prometheus_schema.erl
  8. 0 16
      examples/README.md
  9. 0 30
      examples/cluster-with-dns.conf.example
  10. 0 81
      examples/cluster-with-etcd-ssl.conf.example
  11. 0 21
      examples/cluster-with-manual.conf.example
  12. 0 24
      examples/cluster-with-static.conf.example
  13. 0 15
      examples/conn_congestion.conf.example
  14. 0 21
      examples/flapping_detect.conf.example
  15. 0 18
      examples/force_gc.conf.example
  16. 0 19
      examples/force_shutdown.conf.example
  17. 0 43
      examples/node.conf.example
  18. 0 28
      examples/prometheus.conf.example
  19. 14 1
      mix.exs
  20. 11 3
      rebar.config.erl
  21. 2 8
      examples/file_transfer-with-local-exporter.conf.example
  22. 2 10
      examples/file_transfer-with-s3-exporter.conf.example
  23. 2 8
      examples/license.conf.example
  24. 24 0
      rel/config/examples/README.md
  25. 0 6
      examples/alarm.conf.example
  26. 21 0
      rel/config/examples/cluster-with-dns.conf.example
  27. 37 0
      rel/config/examples/cluster-with-etcd-ssl.conf.example
  28. 2 10
      examples/cluster-with-etcd.conf.example
  29. 1 10
      examples/cluster-with-k8s.conf.example
  30. 12 0
      rel/config/examples/cluster-with-manual.conf.example
  31. 15 0
      rel/config/examples/cluster-with-static.conf.example
  32. 11 0
      rel/config/examples/conn_congestion.conf.example
  33. 2 6
      examples/dashboard-with-http.conf.example
  34. 2 6
      examples/dashboard-with-https.conf.example
  35. 0 0
      rel/config/examples/delayed.conf.example
  36. 1 3
      examples/exhook.conf.example
  37. 17 0
      rel/config/examples/flapping_detect.conf.example
  38. 12 0
      rel/config/examples/force_gc.conf.example
  39. 15 0
      rel/config/examples/force_shutdown.conf.example
  40. 0 0
      rel/config/examples/gateway.coap.conf.example
  41. 0 6
      examples/gateway.exproto.conf.example
  42. 0 6
      examples/gateway.lwm2m.conf.example
  43. 0 6
      examples/gateway.mqttsn.conf.example
  44. 0 6
      examples/gateway.stomp.conf.example
  45. 5 12
      examples/listeners.quic.conf.example
  46. 8 18
      examples/listeners.ssl.conf.example
  47. 3 10
      examples/listeners.tcp.conf.example
  48. 2 12
      examples/listeners.ws.conf.example
  49. 5 15
      examples/listeners.wss.conf.example
  50. 1 7
      examples/log.console.conf.example
  51. 3 10
      examples/log.file.conf.example
  52. 3 8
      examples/mqtt.conf.example
  53. 39 0
      rel/config/examples/node.conf.example
  54. 2 9
      examples/plugin.conf.example
  55. 28 0
      rel/config/examples/prometheus-pushgateway.conf.example
  56. 10 0
      rel/config/examples/prometheus.conf.example
  57. 1 7
      examples/psk_authentication.conf.example
  58. 4 12
      examples/retainer.conf.example
  59. 0 5
      examples/sys_topics.conf.example
  60. 4 10
      examples/sysmon.os.conf.example
  61. 1 7
      examples/sysmon.vm.conf.example
  62. 2 15
      rel/i18n/emqx_conf_schema.hocon
  63. 9 7
      rel/i18n/emqx_prometheus_schema.hocon
  64. 3 3
      rel/i18n/emqx_retainer_schema.hocon
  65. 53 0
      scripts/test/check-example-configs.sh

+ 24 - 0
.github/workflows/run_test_cases.yaml

@@ -88,6 +88,30 @@ jobs:
           name: source-${{ matrix.profile }}-${{ matrix.otp }}
           name: source-${{ matrix.profile }}-${{ matrix.otp }}
           path: source.zip
           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:
   static_checks:
     needs:
     needs:
       - build-matrix
       - build-matrix

+ 27 - 1
apps/emqx/src/emqx_hocon.erl

@@ -24,7 +24,8 @@
     compact_errors/2,
     compact_errors/2,
     format_error/1,
     format_error/1,
     format_error/2,
     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.
 %% @doc Format hocon config field path to dot-separated string in iolist format.
@@ -135,3 +136,28 @@ compact_errors(SchemaModule, Error, Stacktrace) ->
         exception => Error,
         exception => Error,
         stacktrace => Stacktrace
         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.

+ 13 - 1
apps/emqx/src/emqx_schema.erl

@@ -3271,7 +3271,19 @@ tombstone() ->
 tombstone_map(Name, Type) ->
 tombstone_map(Name, Type) ->
     %% marked_for_deletion must be the last member of the union
     %% marked_for_deletion must be the last member of the union
     %% because we need to first union member to populate the default values
     %% 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
 %% inverse of mark_del_map
 get_tombstone_map_value_type(Schema) ->
 get_tombstone_map_value_type(Schema) ->

+ 2 - 0
apps/emqx_conf/src/emqx_conf_schema.erl

@@ -154,6 +154,8 @@ fields("cluster") ->
             sc(
             sc(
                 node_array(),
                 node_array(),
                 #{
                 #{
+                    %% This config is nerver needed (since 5.0.0)
+                    importance => ?IMPORTANCE_HIDDEN,
                     mapping => "mria.core_nodes",
                     mapping => "mria.core_nodes",
                     default => [],
                     default => [],
                     'readOnly' => true,
                     'readOnly' => true,

+ 70 - 1
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).
 -module(emqx_conf_schema_tests).
@@ -488,3 +500,60 @@ check(Config) ->
         atom_key => false, required => false, format => map
         atom_key => false, required => false, format => map
     }),
     }),
     emqx_utils_maps:unsafe_atom_key_map(Conf).
     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}
+    ].

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

@@ -2,7 +2,7 @@
 {application, emqx_prometheus, [
 {application, emqx_prometheus, [
     {description, "Prometheus for EMQX"},
     {description, "Prometheus for EMQX"},
     % strict semver, bump manually!
     % strict semver, bump manually!
-    {vsn, "5.0.12"},
+    {vsn, "5.0.13"},
     {modules, []},
     {modules, []},
     {registered, [emqx_prometheus_sup]},
     {registered, [emqx_prometheus_sup]},
     {applications, [kernel, stdlib, prometheus, emqx, emqx_management]},
     {applications, [kernel, stdlib, prometheus, emqx, emqx_management]},

+ 14 - 8
apps/emqx_prometheus/src/emqx_prometheus_schema.erl

@@ -86,61 +86,67 @@ fields("prometheus") ->
             )},
             )},
         {vm_dist_collector,
         {vm_dist_collector,
             ?HOCON(
             ?HOCON(
-                hoconsc:enum([enabled, disabled]),
+                hoconsc:enum([disabled, enabled]),
                 #{
                 #{
-                    default => enabled,
+                    default => disabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(vm_dist_collector)
                     desc => ?DESC(vm_dist_collector)
                 }
                 }
             )},
             )},
+        %% Mnesia metrics mainly using mnesia:system_info/1
         {mnesia_collector,
         {mnesia_collector,
             ?HOCON(
             ?HOCON(
                 hoconsc:enum([enabled, disabled]),
                 hoconsc:enum([enabled, disabled]),
                 #{
                 #{
                     default => enabled,
                     default => enabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(mnesia_collector)
                     desc => ?DESC(mnesia_collector)
                 }
                 }
             )},
             )},
+        %% Collects Erlang VM metrics using erlang:statistics/1.
         {vm_statistics_collector,
         {vm_statistics_collector,
             ?HOCON(
             ?HOCON(
                 hoconsc:enum([enabled, disabled]),
                 hoconsc:enum([enabled, disabled]),
                 #{
                 #{
                     default => enabled,
                     default => enabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(vm_statistics_collector)
                     desc => ?DESC(vm_statistics_collector)
                 }
                 }
             )},
             )},
+        %% Collects Erlang VM metrics using erlang:system_info/1.
         {vm_system_info_collector,
         {vm_system_info_collector,
             ?HOCON(
             ?HOCON(
                 hoconsc:enum([enabled, disabled]),
                 hoconsc:enum([enabled, disabled]),
                 #{
                 #{
                     default => enabled,
                     default => enabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(vm_system_info_collector)
                     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,
         {vm_memory_collector,
             ?HOCON(
             ?HOCON(
                 hoconsc:enum([enabled, disabled]),
                 hoconsc:enum([enabled, disabled]),
                 #{
                 #{
                     default => enabled,
                     default => enabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(vm_memory_collector)
                     desc => ?DESC(vm_memory_collector)
                 }
                 }
             )},
             )},
+        %% Collects microstate accounting metrics using erlang:statistics(microstate_accounting).
         {vm_msacc_collector,
         {vm_msacc_collector,
             ?HOCON(
             ?HOCON(
                 hoconsc:enum([enabled, disabled]),
                 hoconsc:enum([enabled, disabled]),
                 #{
                 #{
                     default => enabled,
                     default => enabled,
                     required => true,
                     required => true,
-                    importance => ?IMPORTANCE_HIDDEN,
+                    importance => ?IMPORTANCE_LOW,
                     desc => ?DESC(vm_msacc_collector)
                     desc => ?DESC(vm_msacc_collector)
                 }
                 }
             )}
             )}

+ 0 - 16
examples/README.md

@@ -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/).
-

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

@@ -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
-     }
- }

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

@@ -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
-      }
-    }
-}

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

@@ -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
- }

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

@@ -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"]
- }

+ 0 - 15
examples/conn_congestion.conf.example

@@ -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
-}

+ 0 - 21
examples/flapping_detect.conf.example

@@ -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
-}

+ 0 - 18
examples/force_gc.conf.example

@@ -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
-}

+ 0 - 19
examples/force_shutdown.conf.example

@@ -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
-}

+ 0 - 43
examples/node.conf.example

@@ -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
-}

+ 0 - 28
examples/prometheus.conf.example

@@ -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
-}

+ 14 - 1
mix.exs

@@ -539,11 +539,24 @@ defmodule EMQXUmbrella.MixProject do
     profile = System.get_env("MIX_ENV")
     profile = System.get_env("MIX_ENV")
 
 
     File.cp_r!(
     File.cp_r!(
-      "examples",
+      "rel/config/examples",
       Path.join(etc, "examples"),
       Path.join(etc, "examples"),
       force: overwrite?
       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
     # this is required by the produced escript / nodetool
     Mix.Generator.copy_file(
     Mix.Generator.copy_file(
       Path.join(release.version_path, "start_clean.boot"),
       Path.join(release.version_path, "start_clean.boot"),

+ 11 - 3
rebar.config.erl

@@ -521,12 +521,12 @@ relx_overlay(ReleaseType, Edition) ->
         {copy, "bin/nodetool", "bin/nodetool-{{release_version}}"}
         {copy, "bin/nodetool", "bin/nodetool-{{release_version}}"}
     ] ++ etc_overlay(ReleaseType, Edition).
     ] ++ etc_overlay(ReleaseType, Edition).
 
 
-etc_overlay(ReleaseType, _Edition) ->
+etc_overlay(ReleaseType, Edition) ->
     Templates = emqx_etc_overlay(ReleaseType),
     Templates = emqx_etc_overlay(ReleaseType),
     [
     [
         {mkdir, "etc/"},
         {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(
         lists:map(
             fun
             fun
@@ -536,6 +536,14 @@ etc_overlay(ReleaseType, _Edition) ->
             Templates
             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(ReleaseType) ->
     emqx_etc_overlay_per_rel(ReleaseType) ++
     emqx_etc_overlay_per_rel(ReleaseType) ++
         emqx_etc_overlay().
         emqx_etc_overlay().

+ 2 - 8
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 {
 file_transfer {
     ## Enable the File Transfer feature
     ## Enable the File Transfer feature

+ 2 - 10
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
 ## 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 {
 file_transfer {
     ## Enable the File Transfer feature
     ## Enable the File Transfer feature
@@ -62,9 +57,6 @@ file_transfer {
 
 
                     ## Timeout for connection attempts
                     ## Timeout for connection attempts
                     connect_timeout = 15s
                     connect_timeout = 15s
-
-                    ## Attempt to talk through IPv6 first
-                    ipv6_probe = true
                }
                }
            }
            }
         }
         }

+ 2 - 8
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 {
     ## License Key
     ## License Key

+ 24 - 0
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/).

+ 0 - 6
examples/alarm.conf.example

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## Alarm
 ## 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 {
 alarm {
     ## The actions triggered when the alarm is activated
     ## The actions triggered when the alarm is activated

+ 21 - 0
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
+     }
+ }

+ 37 - 0
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
+      }
+    }
+}

+ 2 - 10
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 {
 cluster {
     ## Human-friendly name of the EMQX cluster.
     ## Human-friendly name of the EMQX cluster.
@@ -13,9 +8,6 @@ cluster {
     ## Service discovery method for the cluster nodes
     ## Service discovery method for the cluster nodes
     discovery_strategy = etcd
     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
     ## If true, the node will try to heal network partitions automatically
     autoheal = true
     autoheal = true
 
 

+ 1 - 10
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 {
 cluster {
     ## Human-friendly name of the EMQX cluster.
     ## Human-friendly name of the EMQX cluster.
@@ -13,9 +7,6 @@ cluster {
     ## Service discovery method for the cluster nodes
     ## Service discovery method for the cluster nodes
     discovery_strategy = k8s
     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
     ## If true, the node will try to heal network partitions automatically
     autoheal = true
     autoheal = true
 
 

+ 12 - 0
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
+ }

+ 15 - 0
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"]
+ }

+ 11 - 0
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
+}

+ 2 - 6
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 {
 dashboard {
     ## JWT token expiration time
     ## JWT token expiration time

+ 2 - 6
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 {
 dashboard {
     ## JWT token expiration time
     ## JWT token expiration time

examples/delayed.conf.example → rel/config/examples/delayed.conf.example


+ 1 - 3
examples/exhook.conf.example

@@ -1,8 +1,6 @@
-##--------------------------------------------------------------------
 ## gRPC Hook Extension
 ## 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 = [
 exhook.servers = [
     {
     {

+ 17 - 0
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
+}

+ 12 - 0
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
+}

+ 15 - 0
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
+}

examples/gateway.coap.conf.example → rel/config/examples/gateway.coap.conf.example


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

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## Gateway Exproto
 ## 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 {
 gateway.exproto {
 
 

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

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## Gateway LwM2M
 ## 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 {
 gateway.lwm2m {
 
 

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

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## Gateway MQTT-SN
 ## 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 {
 gateway.mqttsn {
 
 

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

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## Gateway STOMP
 ## 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 {
 gateway.stomp {
 
 

+ 5 - 12
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
-
-## Note: Modifying the 'quicname' to what you need
-listeners.quic.quicname {
+## MQTT over QUIC Listener
+
+listeners.quic.my_quick_listener_name {
     ## Port or Address to listen on, 0 means disable
     ## Port or Address to listen on, 0 means disable
     bind = 14567 ## or with an IP, e.g. "127.0.0.1:14567"
     bind = 14567 ## or with an IP, e.g. "127.0.0.1:14567"
 
 
@@ -28,8 +21,8 @@ listeners.quic.quicname {
     ## Type: infinity | Integer
     ## Type: infinity | Integer
     max_connections = infinity
     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 {
     ssl_options {
         ## Trusted PEM format CA certificates bundle file
         ## Trusted PEM format CA certificates bundle file

+ 8 - 18
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
-
-## 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 {
+## MQTT over TLS(SSL) Listener
+
+listeners.ssl.my_ssl_listener_name {
     ## Port or Address to listen on, 0 means disable
     ## Port or Address to listen on, 0 means disable
     bind = 8883 ## or with an IP e.g. "127.0.0.1:8883"
     bind = 8883 ## or with an IP e.g. "127.0.0.1:8883"
     enabled = true
     enabled = true
@@ -33,13 +23,13 @@ listeners.ssl.sslname {
     }
     }
     ssl_options {
     ssl_options {
         ## Trusted PEM format CA certificates bundle file
         ## Trusted PEM format CA certificates bundle file
-        cacertfile = "data/certs/cacert.pem"
+        cacertfile = "${EMQX_ETC_DIR}/certs/cacert.pem"
 
 
         ## PEM format certificates chain file
         ## PEM format certificates chain file
-        certfile = "data/certs/cert.pem"
+        certfile = "${EMQX_ETC_DIR}/certs/cert.pem"
 
 
         ## PEM format private key file
         ## PEM format private key file
-        keyfile = "data/certs/key.pem"
+        keyfile = "${EMQX_ETC_DIR}/certs/key.pem"
 
 
         ## Enable or disable peer verification
         ## Enable or disable peer verification
         verify = verify_none  ## use verify_peer to enable
         verify = verify_none  ## use verify_peer to enable
@@ -58,7 +48,7 @@ listeners.ssl.sslname {
 
 
         ## TLS cipher suite names
         ## TLS cipher suite names
         ## Note: By default, all available suites are supported, you do not need to set this
         ## 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
         ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
         secure_renegotiate = true
         secure_renegotiate = true
@@ -82,7 +72,7 @@ listeners.ssl.sslname {
         ocsp {
         ocsp {
              enable_ocsp_stapling = false
              enable_ocsp_stapling = false
              responder_url = "http://ocsp.example.com"
              responder_url = "http://ocsp.example.com"
-             issuer_pem = true
+             issuer_pem = "${EMQX_ETC_DIR}/certs/ocsp-issuer-cert.pem"
              refresh_http_timeout = 15s
              refresh_http_timeout = 15s
              refresh_interval = 5m
              refresh_interval = 5m
         }
         }

+ 3 - 10
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
-
-## Note: Modifying the 'tcpname' to what you need
-listeners.tcp.tcpname {
+## MQTT over TCP Listener
+
+listeners.tcp.my_tcp_listener_name {
     ## Port or Address to listen on, 0 means disable
     ## Port or Address to listen on, 0 means disable
     bind = 1883 ## or with an IP e.g. "127.0.0.1:1883"
     bind = 1883 ## or with an IP e.g. "127.0.0.1:1883"
 
 

+ 2 - 12
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
     ## Port or Address to listen on, 0 means disable
     bind = "0.0.0.0:8083" # or just a port number, e.g. 8083
     bind = "0.0.0.0:8083" # or just a port number, e.g. 8083
     enabled = true
     enabled = true

+ 5 - 15
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
-
-## 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 {
+## MQTT over Secured Websocket (HTTPS) Listener
+
+listeners.wss.my_wss_listener_name = {
     ## Port or Address to listen on, 0 means disable
     ## Port or Address to listen on, 0 means disable
     bind = 8084 ## or with an IP, e.g. "127.0.0.1:8084"
     bind = 8084 ## or with an IP, e.g. "127.0.0.1:8084"
     enabled = true
     enabled = true
@@ -76,11 +66,11 @@ listeners.wss.wssname {
         depth = 10
         depth = 10
 
 
         ## Which versions are to be supported
         ## Which versions are to be supported
-        versions = [tlsv1.3, tlsv1.2]
+        versions = ["tlsv1.3", "tlsv1.2"]
 
 
         ## TLS cipher suite names
         ## TLS cipher suite names
         ## Note: By default, all available suites are supported, you do not need to set this
         ## 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
         ## Allows a client and a server to renegotiate the parameters of the SSL connection on the fly
         secure_renegotiate = true
         secure_renegotiate = true

+ 1 - 7
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 {
 log.console {
     ## set true to enable this
     ## set true to enable this

+ 3 - 10
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 {
 log.file {
-    ## use false to disable this
+    ## Enable file log handler
     enable = true
     enable = true
 
 
     ## Log level
     ## Log level
     ## Type: debug | info | notice | warning | error | critical | alert | emergency
     ## Type: debug | info | notice | warning | error | critical | alert | emergency
     level = warning
     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
     ## Type: text | json
     formatter = text
     formatter = text
 
 

+ 3 - 8
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 {
 mqtt {
     ## After the TCP connection is established,
     ## After the TCP connection is established,
@@ -121,4 +116,4 @@ mqtt {
     ##   - hash_clientid :: select the subscribers by hashing the `clientIds`
     ##   - hash_clientid :: select the subscribers by hashing the `clientIds`
     ##   - hash_topic :: select the subscribers by hashing the source topic"""
     ##   - hash_topic :: select the subscribers by hashing the source topic"""
     shared_subscription_strategy = round_robin
     shared_subscription_strategy = round_robin
- }
+}

+ 39 - 0
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
+}

+ 2 - 9
examples/plugin.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
     ## Plugins declaration
     ## Note: The plugins are started in the defined order
     ## Note: The plugins are started in the defined order
     states = [
     states = [

+ 28 - 0
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}"
+}

+ 10 - 0
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
+}

+ 1 - 7
examples/psk_authentication.conf.example

@@ -1,13 +1,7 @@
-##--------------------------------------------------------------------
 ## Pre-Shared Keys authentication
 ## 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 {
 psk_authentication {
-    ## set to false to disable
+    ## Set to false to disable
     enable = true
     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
     ## If init_file is specified, EMQX will import PSKs from the file into the built-in database at startup for use by the runtime

+ 4 - 12
examples/retainer.conf.example

@@ -3,20 +3,12 @@
 ##
 ##
 ## Configuration related to handling PUBLISH packets with a retain flag set to 1
 ## 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 {
 retainer {
-    ## set to false to disable this
+    ## set to false to disable retainer
     enable = true
     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
     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
     ## 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
     ## Retained messages store backend
     backend {
     backend {
-      ## Backend type
+      ## Built-in database (Mnesia)
       type = built_in_database
       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
       ## Type: enum: ram | disc
       storage_type = ram
       storage_type = ram
 
 

+ 0 - 5
examples/sys_topics.conf.example

@@ -1,10 +1,5 @@
-##--------------------------------------------------------------------
 ## System Topic
 ## System Topic
-##
 ## Publishing client lifecycle events to "$SYS" topics
 ## 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 {
 sys_topics {
     ## Time interval of publishing `$SYS` messages
     ## Time interval of publishing `$SYS` messages

+ 4 - 10
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 {
 sysmon.os {
     ## Time interval for the periodic CPU check
     ## Time interval for the periodic CPU check
@@ -17,9 +11,9 @@ sysmon.os {
     cpu_low_watermark = 60%
     cpu_low_watermark = 60%
 
 
     ## Time interval for the periodic memory check
     ## 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
     mem_check_interval = 60s
 
 
     ## For how much system memory can be allocated before the corresponding alarm is raised
     ## For how much system memory can be allocated before the corresponding alarm is raised

+ 1 - 7
examples/sysmon.vm.conf.example

@@ -1,10 +1,4 @@
-##--------------------------------------------------------------------
 ## System Monitoring For Erlang VM
 ## 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 {
 sysmon.vm {
     ## Time interval for the periodic process limit check
     ## 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
     ## Generating an alarm is generated when the Erlang VM detect a task scheduled for too long
     ## Type:
     ## Type:
     ##   - disabled :: Never alarm
     ##   - 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
     long_schedule = 240ms
 
 
     ## Generating an alarm when an Erlang process consumed a large amount of memory for its heap space
     ## Generating an alarm when an Erlang process consumed a large amount of memory for its heap space

+ 2 - 15
rel/i18n/emqx_conf_schema.hocon

@@ -135,7 +135,7 @@ log_overload_kill_restart_after.label:
 """Handler Restart Timer"""
 """Handler Restart Timer"""
 
 
 log_file_handler_max_size.desc:
 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:
 log_file_handler_max_size.label:
 """Rotation Size"""
 """Rotation Size"""
@@ -389,17 +389,6 @@ cluster_mcast_ttl.desc:
 cluster_mcast_ttl.label:
 cluster_mcast_ttl.label:
 """Cluster Multicast TTL"""
 """Cluster Multicast TTL"""
 
 
-db_core_nodes.desc:
-"""List of core nodes that the replicant will connect to.<br/>
-Note: this parameter only takes effect when the <code>backend</code> is set
-to <code>rlog</code> and the <code>role</code> is set to <code>replicant</code>.<br/>
-This value needs to be defined for manual or static cluster discovery mechanisms.<br/>
-If an automatic cluster discovery mechanism is being used (such as <code>etcd</code>),
-there is no need to set this value."""
-
-db_core_nodes.label:
-"""Db Core Node"""
-
 log_file_handler_file.desc:
 log_file_handler_file.desc:
 """Name the log file."""
 """Name the log file."""
 
 
@@ -514,15 +503,13 @@ cluster_autoclean.label:
 
 
 process_limit.desc:
 process_limit.desc:
 """Maximum number of simultaneously existing processes for this Erlang system.
 """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"""
 For more information, see: https://www.erlang.org/doc/man/erl.html"""
 
 
 process_limit.label:
 process_limit.label:
 """Erlang Process Limit"""
 """Erlang Process Limit"""
 
 
 max_ports.desc:
 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"""
 For more information, see: https://www.erlang.org/doc/man/erl.html"""
 
 
 max_ports.label:
 max_ports.label:

+ 9 - 7
rel/i18n/emqx_prometheus_schema.hocon

@@ -18,30 +18,32 @@ For example, when the EMQX node name is <code>emqx@127.0.0.1</code> then the <co
 Default value is: <code>${name}/instance/${name}~${host}</code>"""
 Default value is: <code>${name}/instance/${name}~${host}</code>"""
 
 
 mnesia_collector.desc:
 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:
 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"`<br/>
+The 'enable' flag is used to turn on and off for the push-gateway integration."""
 
 
 prometheus.label:
 prometheus.label:
 """Prometheus"""
 """Prometheus"""
 
 
 push_gateway_server.desc:
 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:
 vm_dist_collector.desc:
 """Enable or disable VM distribution collector, collects information about the sockets and processes involved in the Erlang distribution mechanism."""
 """Enable or disable VM distribution collector, collects information about the sockets and processes involved in the Erlang distribution mechanism."""
 
 
 vm_memory_collector.desc:
 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:
 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:
 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:
 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."""
 
 
 }
 }

+ 3 - 3
rel/i18n/emqx_retainer_schema.hocon

@@ -34,11 +34,11 @@ mnesia_config_type.desc:
 """Backend type."""
 """Backend type."""
 
 
 msg_clear_interval.desc:
 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:
 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:
 stop_publish_clear_msg.desc:
 """When the retained flag of the `PUBLISH` message is set and Payload is empty,
 """When the retained flag of the `PUBLISH` message is set and Payload is empty,

+ 53 - 0
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