Skip to main content

Config file reference

The config file is one YAML document. Give it with --config or MQGW_CONFIG. The gateway serves a protocol when the file has its block, even an empty one (amqp: {}). Every other key has a default, so a file can be as short as mqtt: {}.

Example​

id: gw-1 # unique per gateway; also --id
log: { level: info, format: json }
monitor: { addr: ":8222" } # /livez, /readyz and /healthz
ldm: { duration: 2m, grace-period: 10s }
tls: # TLS on every MQTT and AMQP listener
cert: /etc/mqgw/tls.crt
key: /etc/mqgw/tls.key

nats:
url: nats://nats-1:4222,nats://nats-2:4222,nats://nats-3:4222
creds: /etc/mqgw/gateway.creds # the gateway's own NATS user

bindings: # subjects that a stream stores
- { subjects: [orders, orders.>], stream: ORDERS }
- { subjects: [plant1.*.*.alarms], stream: ALARMS }

mqtt:
listeners:
- { name: public, addr: ":1883" } # client's username and password
- { name: telemetry, addr: ":1884", auth: { mode: fixed, creds: /etc/mqgw/telemetry.creds } }
- { name: ws, addr: ":8080", ws-path: /mqtt }
bindings: [ORDERS, ALARMS] # QoS 1 and 2 on these streams
retained: { bucket: MQTT_RETAINED }
sessions: { bucket: MQTT_SESSIONS }

amqp: # one passthrough listener on :5672
bindings: [ORDERS] # unsettled transfers on ORDERS
delivery-counts: { bucket: AMQP_COUNTS }
routes:
- { subject: orders, template: "orders.{region}" }

This gateway serves MQTT on three ports and AMQP on one. MQTT stores QoS 1 and 2 messages in both streams. AMQP stores unsettled transfers in ORDERS only. Everything else travels over core NATS.

Gateway​

KeyDefaultDescription
idrandomA NATS subject token that names the gateway in the admin subjects, unique per gateway
log.levelinfodebug, info, warn or error
log.formattexttext, or json for one object per line, on standard error
monitor.addrnoneHTTP address for the health endpoints
ldm.duration2mTime that lame duck mode takes to move all clients
ldm.grace-period10sWait, shorter than ldm.duration, before lame duck mode closes the first connection
tls.cert, tls.keynonePEM certificate and key for every MQTT and AMQP listener
tls.canonePEM CA that must sign every client's certificate
license.filenoneFile with the license JWT, read only by a licensed build
license.tokennoneThe license JWT, used when license.file is unset
bindingsnoneStreams that store subjects (see Routing)
accountsnoneTables and credentials per NATS account (see Accounts)

mqtt​

KeyDefaultDescription
mqtt.listenersmqtt on :1883The MQTT ports (see Listeners)
mqtt.connect-timeout5sTime a client has to send its CONNECT
mqtt.max-packet-size67108864Largest packet in bytes from a client, capped for v5 clients at the NATS payload limit
mqtt.max-inflight1024Unacknowledged QoS 1 and 2 messages per client in each direction (1–65535)
mqtt.ack-wait30sTime before the gateway sends an unacknowledged delivery again to an MQTT 3.1.1 client (1s–1h). A v5 client gets no resend on the same connection
mqtt.ack-batch64Deliveries the gateway acknowledges to the stream together (1 for each one)
mqtt.topic-alias-max0Topic aliases a v5 client may use (0 for none)
mqtt.server-keepalive0Keep-alive in seconds that replaces a v5 client's own (0 for the client's)
mqtt.server-referencenoneServer Reference that v5 clients get when the gateway stops, often host:port
mqtt.sessions.max-expiry24hLongest time a persistent session outlives its connection (at least 1s)
mqtt.sessions.sweep1mInterval at which the gateway ends expired sessions and publishes due wills
mqtt.sessions.bucketnoneKV bucket that keeps persistent sessions
mqtt.sessions.domainnoneJetStream domain of the sessions bucket
mqtt.bindingsnoneBinding names that store QoS 1 and 2 messages
mqtt.routesnoneRoutes for v5 publishes (see Routing)
mqtt.retained.bucketnoneKV bucket that keeps retained messages
mqtt.retained.domainnoneJetStream domain of the retained bucket
mqtt.sparkplug.awarefalseRetain Sparkplug B births on $sparkplug/certificates/ (needs mqtt.retained.bucket)

Without mqtt.bindings, MQTT offers QoS 0 only. Without a retained bucket, the gateway ignores RETAIN. Without a sessions bucket, each session ends with its connection. Gateways that share a sessions bucket should use the same mqtt.ack-wait. See Run Sparkplug B clients for mqtt.sparkplug.aware.

amqp​

KeyDefaultDescription
amqp.listenersamqp on :5672The AMQP ports (see Listeners)
amqp.connect-timeout5sTime a client has for the SASL exchange, and again for its open
amqp.max-frame-size131072Largest frame in bytes that a client may send (at least 512)
amqp.max-inflight1024Credit for a sending link, and unsettled deliveries per queue (1–65535)
amqp.ack-wait30sTime before the stream sends an unsettled delivery again (1s–1h)
amqp.queue-inactive1hTime an address's queue stays with no receiver attached
amqp.bindingsnoneBinding names that store unsettled transfers
amqp.routesnoneRoutes for transfers (see Routing)
amqp.delivery-counts.bucketnoneKV bucket that keeps delivery counts (required with amqp.bindings)
amqp.delivery-counts.domainnoneJetStream domain of the delivery-counts bucket

Without amqp.bindings, AMQP takes settled transfers only. A queue keeps the amqp.ack-wait from when the gateway created it. A new value applies after the queue expires.

nats​

KeyDefaultDescription
nats.urlnats://localhost:4222NATS server URLs, comma-separated, without credentials
nats.user, nats.password, nats.creds, nats.nkey, nats.jwt, nats.seed, nats.contextnoneThe gateway's own NATS user (see Credentials)
nats.tls.cert, nats.tls.keynoneClient certificate and key for the gateway's NATS connections
nats.tls.canoneCA that signed the NATS servers' certificates
nats.ping-interval10sInterval between pings on each NATS connection
nats.max-pings-out2Unanswered pings before a connection moves to another server
nats.reconnect.maxforeverAttempts per server before a connection closes, or forever
nats.reconnect.wait2sPause before a connection tries a server again
nats.embedfalseRun a NATS server with JetStream in the gateway process (not with nats.url)
nats.host127.0.0.1Embedded server's client listen host
nats.portrandomEmbedded server's client port
nats.store-dirtemporaryEmbedded server's JetStream directory (the gateway deletes a temporary one at stop)
nats.confignonenats-server config file for the whole embedded server (not with nats.host, nats.port or nats.store-dir)

A connection detects a lost server after about nats.ping-interval × nats.max-pings-out. When a client's NATS connection closes, the gateway disconnects that client. When the gateway's own connection closes, only a restart opens it again. nats.host, nats.port, nats.store-dir and nats.config need nats.embed: true.

Listeners​

Each entry of mqtt.listeners or amqp.listeners is one port. The list replaces the protocol's default listener.

KeyDefaultDescription
addrrequiredTCP listen address
nameaddrListener name in log lines
ws-pathnoneWebSocket path to serve the protocol on (wss:// with tls)
auth.modepassthroughpassthrough or fixed
auth.user, auth.password, auth.creds, auth.nkey, auth.jwt, auth.seed, auth.context, auth.tlsnoneThe NATS credential for every client on a fixed port (see Credentials)

On a passthrough port, the client's username and password become its NATS user and password. A client that sends none connects with no credential, so NATS refuses it or makes it the server's no_auth_user. On a fixed port, every client connects with the listener's credential, and the gateway ignores the client's own. Configure listeners and auth shows both.

Routing​

A routing table binds NATS subjects to streams. Each protocol then lists the bindings that it stores in. The top-level bindings and the routing keys in mqtt and amqp form the table for every account that has no table of its own.

KeyDefaultDescription
bindings[].subjectsrequiredNATS subjects that the stream stores, with * and > as wildcards
bindings[].streamrequiredAn existing stream, which the gateway never creates or changes
bindings[].namethe streamName that mqtt.bindings and amqp.bindings list
bindings[].domainnoneJetStream domain of the stream, for a stream in another domain
mqtt.routes[].subject, amqp.routes[].subjectrequiredA subject without wildcards that clients publish to
mqtt.routes[].template, amqp.routes[].templaterequiredSubject to publish under instead, such as orders.{region}

A {name} token in a template takes the value of the message's property name. For MQTT, that is a v5 User Property. For AMQP, it is an application property. A selector on that property then becomes a subject filter that NATS applies. A subject routed in both blocks must have the same template in each. A binding must cover the template's subjects, here orders.>. Mapping to NATS shows how topics and addresses become subjects, and which publishes a route refuses.

orders.> does not cover orders. To store what an MQTT orders/# filter matches, list both, as the example does. mq-gateway binding prints that entry from MQTT filters (see CLI).

Accounts​

The gateway serves the account of its own NATS user. Each entry under accounts adds an account, gives an account its own table, or both. The key is the account name, or in operator mode its public key (A…).

mqtt: {}
accounts:
PLANT_A: # the gateway user's account, own table
bindings:
- { subjects: [uagv.v2.*.*.order], stream: VDA_ORDERS }
mqtt:
bindings: [VDA_ORDERS]
sessions: { bucket: VDA_SESSIONS }
PLANT_B: # another account, reached with its own user
creds: /etc/mqgw/gw-plant-b.creds
bindings:
- { subjects: [spBv1//0.*.NDEATH.*], stream: SPARKPLUG }
mqtt:
bindings: [SPARKPLUG]
KeyDescription
accounts.<account>.user, .password, .creds, .nkey, .jwt, .seed, .context, .tlsThe gateway's NATS user in the account, which adds the account
accounts.<account>.bindings, .mqtt, .amqpThe account's own table, with routing keys only

An account's own table replaces the top-level table. The gateway does not merge the two. An entry needs a credential, a table or both.

Credentials​

The nats block, account entries and fixed listeners take a credential in the same keys. Give exactly one kind. Add tls to any kind except context, or use tls alone. The gateway refuses a NATS token.

KeyCredential
user, passwordA user and its password
credsA credentials file with the user's JWT and nkey seed
nkeyAn nkey seed file
jwt, seedA user JWT and its nkey seed, in two files
contextA saved nats CLI context, without its server URL
tls.cert, tls.key, tls.caClient certificate files, for a server that maps certificates to users

creds, nkey, jwt and seed are locations. password is a plain value unless it is an env://, file:// or op:// location.

LocationRead from
/path or file:///pathThe file
env://NAMEThe environment variable
op://vault/item/fieldop read, the 1Password CLI, on PATH
nsc://Operator/Account/UserThe creds file from nsc generate profile, on PATH

The gateway reads a creds file again at each reconnect, so a rotated file takes effect without a restart. It reads every other secret once, at start. It never logs a secret.

Rules​

  • Unknown keys fail. The gateway refuses a key that it does not know, in any block. A typo stops the start, so it cannot leave a setting at its default.
  • Durations are strings. Write 500ms, 90s, 2m or 1h30m. The gateway refuses a bare number.
  • Flags and variables win. id, nats.url, log.level, log.format, license.file and license.token also have a flag and an MQGW_ variable. The order is flag, then variable, then file, then default. An empty variable counts as unset. --mqtt and --amqp turn a protocol on or off. See CLI.
  • Bindings are NATS subjects. A binding subject uses * and >, not + and #. It cannot start with a wildcard. It cannot overlap $JS.>, $JSC.>, $NRG.>, $SYS.> or $MQGW.>. Each subject appears once in a table, and mqtt.bindings or amqp.bindings must list each binding.
  • Streams and buckets must exist. The gateway checks them at start, in each account. It refuses the clients of an account that fails. Run mq-gateway check before you deploy, and see Provision streams and buckets.
  • Changes need a restart. The gateway reads the file only at start. An error in it stops the gateway with exit status 1 and names the file and key. See Change the config.

Fixed values​

These values are not in the file:

ValueFixed at
Time a stream has to acknowledge a store5s
Wait for connections to close at shutdown10s
Lame duck mode overrun before connections close at once10s
AMQP idle timeout (the gateway advertises half)60s
Idle NATS connections kept per listener and credential8, for 5m