Configure listeners and auth
This guide sets the client ports, TLS, and the NATS permissions of the gateway and its clients. NATS, not the gateway, accepts each credential and enforces its permissions.
Before you start, you need:
- A config file, with its streams and buckets provisioned.
- A
nats-server.confthat you can edit and reload.
Choose an auth mode for each port
| Clients on the port | Mode |
|---|---|
| Each client sends its own NATS username and password, as the MQTT username and password or the SASL PLAIN credential | passthrough (the default) |
| Devices that send no credential, or that you do not trust with one. All of them act as one restricted NATS user | fixed |
1. List the listeners
mqtt:
listeners:
- { name: public, addr: ":1883" }
- { name: telemetry, addr: ":1884", auth: { mode: fixed, creds: /etc/nats/telemetry.creds } }
- { name: ws, addr: ":8080", ws-path: /mqtt }
amqp:
listeners:
- { name: amqp, addr: ":5672" }
- { name: legacy, addr: ":5673", auth: { mode: fixed, user: legacy, password: env://LEGACY_PASSWORD } }
- Each list holds every port for its protocol.
ws-pathserves the protocol over WebSocket at that path.- A
fixedlistener takes one credential:creds,nkey,userandpassword,jwtandseed, orcontext. Each value can be anenv://orfile://location. - A block with no
listenersserves one passthrough port: MQTT on:1883, AMQP on:5672.
2. Generate the permissions
mq-gateway generate --config gateway.yaml --format nats-server > permissions.conf
permissions.conf defines one variable for each kind of NATS user:
$gateway_permissions: the user the gateway acts as in an account.$client_permissions: the users that clients act as.$operator_permissions, commented out: a user that sends admin requests.
Each account under accounts gets its own gateway variable, such as
$FLEET_B_gateway_permissions. An account with its own bindings also gets
its own client variable.
3. Narrow the client topics
The config file cannot know which topics each client uses. So each topic
list holds all bound subjects, under a NARROW comment.
- In
$client_permissions, replace eachNARROWlist with the subjects that the user publishes and subscribes to. - Add the QoS 0 topics that the user uses outside the bindings.
- For each subscribe subject that ends in
.>, keep its parent subject too. For example, keeporderswithorders.>. - For users with different topics, copy the variable under a new name for each user.
- In
$gateway_permissions, narrow the will topics to the ones your clients set.
An MQTT topic is a subject with / replaced by .. See Mapping to
NATS.
4. Give each user its permissions
Include the file in nats-server.conf and set permissions on each user:
include "permissions.conf"
accounts {
FLEET_A: {
jetstream: enabled
users: [
{ user: gateway-a, password: "gw-a-secret", permissions: $gateway_permissions }
{ user: device, password: "device-secret", permissions: $client_permissions }
]
}
FLEET_B: {
jetstream: enabled
users: [
{ user: gateway-b, password: "gw-b-secret", permissions: $FLEET_B_gateway_permissions }
{ user: sensor, password: "sensor-secret", permissions: $client_permissions }
]
}
}
- Give each account exactly one gateway user.
- Delete each variable that no user takes. nats-server refuses to load an unused variable.
- Keep the system account. The gateway asks it which account each user is in.
- In operator mode, put the same subjects in the user JWTs.
Reload the server:
nats-server --signal reload
5. Give the gateway its users
Put the gateway user of the gateway's own account under nats. Put each
other gateway user under accounts, with the account name as the key:
nats:
url: nats://nats.example.com:4222
user: gateway-a
password: env://GW_A_PASSWORD
accounts:
FLEET_B: { user: gateway-b, password: env://GW_B_PASSWORD }
In operator mode, the key is the public key of the account. The gateway refuses to start if a user is not in the account that its key names.
Serve TLS
Add a tls block. TLS then applies to every listener. A WebSocket listener
becomes wss:// and an AMQP listener becomes amqps://:
tls:
cert: server.pem
key: server-key.pem
ca: clients-ca.pem # optional: require client certificates
With tls.ca, every client on every listener must present a certificate
that the CA signed. The certificate only admits the client. The auth mode
of the port still sets the NATS user.
To serve a plain port and a TLS port, run two gateways.
Check it works
mq-gateway check --config gateway.yaml --verbose
mq-gateway --config gateway.yaml
The gateway logs listener enabled for each port and account ready for
each account. Then connect a client on each port:
mqttx pub -h 127.0.0.1 -p 1884 -t 'orders/x' -m 'hello' # fixed: no credential
mqttx sub -h 127.0.0.1 -p 1883 -u device -P device-secret -q 1 -t 'orders/#'
The subscriber gets QoS 1. This shows that its user can create its consumer.
Things to know
- A passthrough client with no username connects to NATS with no
credential. NATS refuses it, or connects it as the server's
no_auth_user. Use afixedlistener to give these clients one restricted NATS user. - Clients cannot use the admin subjects. The gateway refuses a client
publish or subscription on
$MQGW.admin.>, whatever the user's permissions allow. - A client without permission gets Not authorized. See Errors for each code and its fix.