Skip to content

Latest commit

 

History

History
325 lines (247 loc) · 9.2 KB

preamble.en.md

File metadata and controls

325 lines (247 loc) · 9.2 KB

EMQX configuration files are in HOCON format. HOCON, or Human-Optimized Config Object Notation is a format for human-readable data, and a superset of JSON.

Layered

EMQX configuration consists of 3 layers. From bottom up:

  1. Immutable base: emqx.conf + EMQX_ prefixed environment variables.
    Changes in this layer require a full node restart to take effect.
  2. Cluster overrides: $EMQX_NODE__DATA_DIR/configs/cluster-override.conf
  3. Local node overrides: $EMQX_NODE__DATA_DIR/configs/local-override.conf

When environment variable $EMQX_NODE__DATA_DIR is not set, config node.data_dir is used.

The cluster-override.conf file is overwritten at runtime when changes are made from dashboard UI, management HTTP API, or CLI. When clustered, after EMQX restarts, it copies the file from the node which has the greatest uptime.

:::tip Tip Some of the configs (such as node.name) are boot-only configs and not overridable. Config values from *-override.conf are not mapped to boot configs for the config fields attributed with mapping: path.to.boot.config.key :::

For detailed override rules, see Config Overlay Rules.

Syntax

In config file the values can be notated as JSON like objects, such as

node {
    name = "[email protected]"
    cookie = "mysecret"
}

Another equivalent representation is flat, such as

node.name = "127.0.0.1"
node.cookie = "mysecret"

This flat format is almost backward compatible with EMQX's config file format in 4.x series (the so called 'cuttlefish' format).

It is not fully compatible because the often HOCON requires strings to be quoted, while cuttlefish treats all characters to the right of the = mark as the value.

e.g. cuttlefish: node.name = [email protected], HOCON: node.name = "[email protected]".

Strings without special characters in them can be unquoted in HOCON too, e.g. foo, foo_bar and foo_bar_1.

For more HOCON syntax, please refer to the specification

Schema

To make the HOCON objects type-safe, EMQX introduced a schema for it. The schema defines data types, and data fields' names and metadata for config value validation and more.

::: tip Tip The configuration document you are reading now is generated from schema metadata. :::

Complex Data Types

There are 4 complex data types in EMQX's HOCON config:

  1. Struct: Named using an unquoted string, followed by a predefined list of fields. Only lowercase letters and digits are allowed in struct and field names. Alos, only underscore can be used as word separator.
  2. Map: Map is like Struct, however the fields are not predefined.
  3. Union: MemberType1 | MemberType2 | ...
  4. Array: [ElementType]

::: tip Tip If map filed name is a positive integer number, it is interpreted as an alternative representation of an Array. For example:

myarray.1 = 74
myarray.2 = 75

will be interpreated as myarray = [74, 75], which is handy when trying to override array elements. :::

Primitive Data Types

Complex types define data 'boxes' which may contain other complex data or primitive values. There are quite some different primitive types, to name a few:

  • atom().
  • boolean().
  • string().
  • integer().
  • float().
  • number().
  • binary(), another format of string().
  • emqx_schema:duration(), time duration, another format of integer()
  • ...

::: tip Tip The primitive types are mostly self-describing, so there is usually not a lot to document. For types that are not so clear by their names, the field description is to be used to find the details. :::

Config Paths

If we consider the whole EMQX config as a tree, to reference a primitive value, we can use a dot-separated names form string for the path from the tree-root (always a Struct) down to the primitive values at tree-leaves.

Each segment of the dotted string is a Struct filed name or Map key. For Array elements, 1-based index is used.

below are some examples

node.name = "emqx.127.0.0.1"
zone.zone1.max_packet_size = "10M"
authentication.1.enable = true

Environment variables

Environment variables can be used to define or override config values.

Due to the fact that dots (.) are not allowed in environment variables, dots are replaced with double-underscores (__).

And the EMQX_ prefix is used as the namespace.

For example node.name can be represented as EMQX_NODE__NAME

Environment variable values are parsed as HOCON values, this allows users to even set complex values from environment variables.

For example, this environment variable sets an array value.

export EMQX_LISTENERS__SSL__L1__AUTHENTICATION__SSL__CIPHERS='["TLS_AES_256_GCM_SHA384"]'

However this also means a string value should be quoted if it happens to contain special characters such as = and :.

For example, a string value "localhost:1883" would be parsed into object (struct): {"localhost": 1883}.

To keep it as a string, one should quote the value like below:

EMQX_BRIDGES__MQTT__MYBRIDGE__CONNECTOR_SERVER='"localhost:1883"'

::: tip Tip Unknown root paths are silently discarded by EMQX, for example EMQX_UNKNOWN_ROOT__FOOBAR is silently discarded because unknown_root is not a predefined root path.

Unknown field names in environment variables are logged as a warning level log, for example:

[warning] unknown_env_vars: ["EMQX_AUTHENTICATION__ENABLED"]

because the field name is enable, not enabled. :::

Config Overlay Rules

HOCON objects are overlaid, in general:

  • Within one file, objects defined 'later' recursively override objects defined 'earlier'
  • When layered, 'later' (higher layer) objects override objects defined 'earlier' (lower layer)

Below are more detailed rules.

Struct Fields

Later config values overwrites earlier values. For example, in below config, the last line debug overwrites error for console log handler's level config, but leaving enable unchanged.

log {
    console_handler{
        enable=true,
        level=error
    }
}

## ... more configs ...

log.console_handler.level=debug

Map Values

Maps are like structs, only the files are user-defined rather than the config schema. For instance, zone1 in the example below.

zone {
    zone1 {
        mqtt.max_packet_size = 1M
    }
}

## The maximum packet size can be defined as above,
## then overridden as below

zone.zone1.mqtt.max_packet_size = 10M

Array Elements

Arrays in EMQX config have two different representations

  • list, such as: [1, 2, 3]
  • indexed-map, such as: {"1"=1, "2"=2, "3"=3}

Dot-separated paths with number in it are parsed to indexed-maps e.g. authentication.1={...} is parsed as authentication={"1": {...}}

This feature makes it easy to override array elment values. For example:

authentication=[{enable=true, backend="built_in_database", mechanism="password_based"}]
# we can disable this authentication provider with:
authentication.1.enable=false

::: warning Warning List arrays is a full-array override, but not a recursive merge, into indexed-map arrays. e.g.

authentication=[{enable=true, backend="built_in_database", mechanism="password_based"}]
## below value will replace the whole array, but not to override just one field.
authentication=[{enable=true}]

:::

TLS/SSL ciphers

Starting from v5.0.6, EMQX no longer pre-populates the ciphers list with a default set of cipher suite names. Instead, the default ciphers are applied at runtime when starting the listener for servers, or when establishing a TLS connection as a client.

Below are the default ciphers selected by EMQX.

For tlsv1.3:

ciphers =
  [ "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256",
    "TLS_CHACHA20_POLY1305_SHA256", "TLS_AES_128_CCM_SHA256",
    "TLS_AES_128_CCM_8_SHA256"
  ]

For tlsv1.2 or earlier

ciphers =
  [ "ECDHE-ECDSA-AES256-GCM-SHA384",
    "ECDHE-RSA-AES256-GCM-SHA384",
    "ECDHE-ECDSA-AES256-SHA384",
    "ECDHE-RSA-AES256-SHA384",
    "ECDH-ECDSA-AES256-GCM-SHA384",
    "ECDH-RSA-AES256-GCM-SHA384",
    "ECDH-ECDSA-AES256-SHA384",
    "ECDH-RSA-AES256-SHA384",
    "DHE-DSS-AES256-GCM-SHA384",
    "DHE-DSS-AES256-SHA256",
    "AES256-GCM-SHA384",
    "AES256-SHA256",
    "ECDHE-ECDSA-AES128-GCM-SHA256",
    "ECDHE-RSA-AES128-GCM-SHA256",
    "ECDHE-ECDSA-AES128-SHA256",
    "ECDHE-RSA-AES128-SHA256",
    "ECDH-ECDSA-AES128-GCM-SHA256",
    "ECDH-RSA-AES128-GCM-SHA256",
    "ECDH-ECDSA-AES128-SHA256",
    "ECDH-RSA-AES128-SHA256",
    "DHE-DSS-AES128-GCM-SHA256",
    "DHE-DSS-AES128-SHA256",
    "AES128-GCM-SHA256",
    "AES128-SHA256",
    "ECDHE-ECDSA-AES256-SHA",
    "ECDHE-RSA-AES256-SHA",
    "DHE-DSS-AES256-SHA",
    "ECDH-ECDSA-AES256-SHA",
    "ECDH-RSA-AES256-SHA",
    "ECDHE-ECDSA-AES128-SHA",
    "ECDHE-RSA-AES128-SHA",
    "DHE-DSS-AES128-SHA",
    "ECDH-ECDSA-AES128-SHA",
    "ECDH-RSA-AES128-SHA"
  ]

For PSK enabled listeners

ciphers =
  [ "RSA-PSK-AES256-GCM-SHA384",
    "RSA-PSK-AES256-CBC-SHA384",
    "RSA-PSK-AES128-GCM-SHA256",
    "RSA-PSK-AES128-CBC-SHA256",
    "RSA-PSK-AES256-CBC-SHA",
    "RSA-PSK-AES128-CBC-SHA",
    "PSK-AES256-GCM-SHA384",
    "PSK-AES128-GCM-SHA256",
    "PSK-AES256-CBC-SHA384",
    "PSK-AES256-CBC-SHA",
    "PSK-AES128-CBC-SHA256",
    "PSK-AES128-CBC-SHA"
  ]