Skip to Content

Lock it down, then learn to read the log

last one out locks up
EMQX Guide · Part 9

Lock it down, then learn to read the log

Your broker now carries the MQTT messages for the whole house, which is exactly what makes it one of the doors an attacker most wants to try. This last part of the series does two jobs. First it closes the doors: which of the five ports are actually open on your Home Assistant host, why an EMQX with no authenticator lets every client connect, and how rate limits, TLS and a protected admin surface stack into layers. Then it turns to the day something breaks, with four symptom-and-fix checklists and the diagnostic order — log, ports, resources — that solves most of it before you ever consider reinstalling anything.

5 ports
host_network opens 1883, 8083, 8084, 8883 and 18083 straight on the host
0 checks
Until you configure Authentication, EMQX allows every client to connect
3 places
Log, then ports, then resources — most failures come from one of those three
Four stretches of the path

Security is not one setting, it is four stretches of one path

Everything in this series so far has been about getting messages to move. A broker that carries every sensor reading, every light command and every automation trigger in the house is also the single thing an attacker most wants to reach: anyone who can connect, get past authentication or subscribe could read your sensor data or drive your devices.

The Woow EMQX add-on runs in host_network mode, which opens its ports straight on the Home Assistant host. There is no container-level private network sitting in between. That makes the security boundary thinner than it would be for a container confined to a virtual network, and it means you have to hold that line by hand.

It helps to stop thinking of security as a switch and start thinking of it as four stretches of the path a message travels:

Client → Listener — is there TLS on this port, and is there authentication in front of it?
Authentication → Authorization — who may connect, and once connected, what may they do?
Resource protection — Limit, Blacklist and Flapping Detect, so one client cannot exhaust the broker.
The admin surface — access to the Dashboard and the REST API, which nobody else should reach directly.

The official security checklist points out one fact that is easy to miss, and it is the single most important line in this chapter: until you configure Authentication, EMQX allows every client to connect. Setting up authentication is not extra credit you get around to later. It is something you finish before you start EMQX up.

In plain terms

A shop with the door propped open and nobody on the till is not secure just because nothing has gone missing yet. Nothing going missing is a fact about this afternoon, not about the lock. An EMQX with no authenticator configured is that shop: every client that knocks is let in, and the quiet is not evidence.

flowchart TD
  C["A device, Z2M or
Home Assistant"] --> L["Listener: 1883, 8083, 8084, 8883
is there TLS on this port?"] L --> AU["Authentication
may this client connect at all?"] AU --> AZ["Authorization, the ACL
which topics may it publish
and subscribe to?"] AZ --> R["Resource protection
Rate Limit, Blacklist, Flapping Detect"] R --> B["The broker carries
the message"] ADM["The admin surface
Dashboard and REST API on 18083"] --> B
Where each control sitsThree of the four stretches run down the left-hand column, in the order a message meets them — the listener, then authentication and the ACL, then resource protection — between the client at the top and the broker at the foot. The fourth stretch, the admin surface, is the box on the right, level with resource protection: it reaches the broker by a completely different door and needs its own lock.
TermPlain EnglishIn one line
Host Networkhost network modeThe add-on uses the host's ports directly
Exposureattack surfaceThe range of listener ports that can be reached from outside
Rate Limitrate limitCaps the connection and publish rate so resources are not exhausted
TLStransport encryptionEncrypts the traffic between a client and the broker
Least Privilegeleast privilegeGive an account only the rights it needs to do its job
API KeyAPI keyThe credential the REST API authenticates with, not the Dashboard password
The first security step is to replace the defaults. The Dashboard's admin/public is public knowledge — it is written in the documentation, which means everybody has it. Change it the moment you enable the add-on. And when you write anything down for a colleague or paste it into a forum, keep API keys and MQTT credentials as obvious placeholders such as <your-password> or YOUR_TOKEN, and never print details of your local network.
host_network and what it opens

Five ports, and who can reach them

host_network in the Woow add-on means EMQX uses the Home Assistant host's ports directly. Five of them:

PortWhat it carriesEncrypted
1883MQTTNo — plaintext
8083MQTT over WebSocketNo — plaintext
8084WSS, MQTT over secure WebSocketYes
8883MQTTSYes
18083The Dashboard, the HTTP admin surfaceThe admin port — the last thing you want exposed

The risk comes down to a single question: who can reach those ports? If the Home Assistant host stays on a trusted local network the threat is low and the risk is manageable. But as soon as you forward a port on the router, put the host in a DMZ, or expose 1883 through ngrok, you have pushed the broker onto the public internet, and those listener ports can be scanned from it.

In plain terms

Most add-ons are a flat in a block: to reach the front door, somebody first has to get past the entrance downstairs. host_network is a house that opens straight onto the street. Nothing is wrong with a house on a street — it just means the front door is the only lock there is, so it had better be a good one, and you had better know how many doors the house has.

Secure deployment comes down to one rule: expose only the listeners you need. In practice that is three habits.

  • Open only the listeners you need. Do not expose all five ports at once because it was easier to open them together.
  • Keep plaintext 1883 on the local network, or use it only as a stopgap. For anything facing outward, prefer the encrypted 8883 and 8084.
  • Restrict the Dashboard on 18083 to a trusted network, use HTTPS, and allow only the accounts you actually need.
flowchart TD
  A["A listener port on the
Home Assistant host"] --> B{"Can anything outside the
local network reach it?"} B -->|"no, trusted LAN only"| C["Manageable risk. Still set
authentication and an ACL"] B -->|"yes: router forward,
DMZ or ngrok"| D{"Which port is it?"} D -->|"18083, the Dashboard"| E["Do not expose it. Local network
or a trusted connection only,
over HTTPS"] D -->|"1883, plaintext MQTT"| F["Local network, or a stopgap.
Move outward traffic to 8883"] D -->|"8883 or 8084, encrypted"| G["Acceptable once authentication,
the ACL and a Rate Limit
are all in place"]
Deciding whether a port may face outwardOne diamond splits trusted from exposed, and the second splits the exposed side by port. Four end boxes in total: the single one under “no”, and three under “yes” — one per port group.
One more from the EMQX security checklist. If a Proxy Protocol or WebSocket listener has no trusted proxy rewriting the source IP, turn off the forwarded-address headers. Otherwise a client can put whatever address it likes in the header, and IP-based authorization can be spoofed.
Four steps to close it up

The hands-on pass, in order

Four steps, and the order matters: the password first because it is public knowledge, then who may connect, then what they may do, then how much they may do it.

  1. Step 1

    Change the default admin password

    If the Dashboard asks you to at first login, replace public with a strong password of your own. If it does not ask, go into the Dashboard's user settings and change it by hand anyway. Leaving it means anybody can log in with the published default.

  2. Step 2

    Set up Authentication

    Go to Access Control → Authentication and create an authenticator. Password-Based → Built-in Database is the recommended one to start with. Then create real users, in place of the default anonymous connection. Before you expose a listener you need at least this much: no anonymous connections.

  3. Step 3

    Narrow the ACL with Authorization

    Go to Access Control → Authorization and write each user's Allow rules to least privilege: which topics Home Assistant needs to publish and subscribe to, which ones Z2M needs. List the specific topics one by one. Do not open everything with #.

  4. Step 4

    Add rate limits and review the listeners

    On the Management → Listeners page, set a Rate Limit on every listener that faces outward — max connections per second, for example. While you are on that page, confirm that 18083 is not directly exposed: keep the Dashboard on the local network, or put authentication in front of it.

None of those four steps covers TLS. If your traffic crosses an untrusted network segment, you also have to configure certificates for 8883 (MQTTS) and 8084 (WSS). Part 4 of this series, on listeners and TLS, has the details.
Rate limits and resource protection

What stops one client taking the broker down

Rate Limit — the limiter — is an EMQX 5.0 and later mechanism that caps the rate at the entry point, so a single client or listener cannot be flooded. You set a value per listener on the Dashboard's Management → Listeners page, and you can also set it in emqx.conf.

TypeUI labelWhat it doesDefault behavior when exceeded
bytes_rateData Publish RateBytes published per client per secondStops taking messages from that client
messages_rateMessages Publish RateMessages published per client per secondStops taking messages from that client
max_conn_rateMaximum Connection RateConnections that listener accepts per secondStops taking new connections

Time units are s, m, h and d; sizes are KB, MB and GB. In emqx.conf, limiting the default TCP listener looks like this:

listeners.tcp.default {
bind = "0.0.0.0:1883"
max_conn_rate = "1000/s"
messages_rate = "1000/s"
bytes_rate = "1MB/s"
}

When a listener is exposed, Rate Limit works alongside two other mechanisms. Blacklist shuts out a client you have identified as a problem. Flapping Detect catches a client that connects and disconnects over and over. Together the three stop one client from flooding the broker or abusing reconnects.

Set the Flapping threshold high enough that a normal reconnect does not trip it. Battery devices, a Wi-Fi access point handing a device over, a Home Assistant restart — all of those produce reconnects that are completely healthy. A threshold set too tight locks out the devices you were trying to protect.
TLS and the admin surface

Encryption on the wire, and a lock on the control room

When traffic crosses an untrusted network, use TLS. EMQX's encrypted listeners are 8883 (MQTTS) and 8084 (WSS). Three things go with that:

  • Certificates should be issued by a trusted CA, or by your own internal PKI if you run one.
  • Rotate them before they expire. An expired certificate does not degrade gracefully; every client stops connecting at once.
  • To identify a device by its certificate, add X.509 authentication and mTLS (verify_peer), so the broker checks the client's certificate as well as the client checking the broker's.

The admin surface then has a few hard rules of its own.

Change the password, restrict who can reach it

Leaving the Dashboard on its default password is a warning sign, not a minor oversight. Change it at first login, and make sure only the people who need it can reach the page at all.

Give the REST API its own key

The REST API should authenticate with an API Key from system → API Key, granted the smallest role possible — not with a Dashboard login.

Bind the Dashboard somewhere trusted

Where you can, bind it to a trusted interface: localhost, the local network, or a dedicated management segment.

EMQX Open Source does not use RBAC. In EMQX 5.8 Open Source, every Dashboard user is an administrator — there is no Viewer role to hand out. RBAC (Administrator/Viewer) is an Enterprise feature. So on Open Source, the compensating controls are to keep the number of admin accounts as low as you can, and to give the REST API an API key with the lowest role that works.

Least privilege applies at every layer, and it is the thread running through all of this: give each device its own credentials, let the ACL allow only the topics that are needed, and do not open everything with a wildcard. The finer the controls, the smaller the hole a single leaked credential opens.

In plain terms

The cleaner gets a key to the front door and the store cupboard, not a key that opens the safe and the server room as well. When that key goes missing you change two locks, not fourteen. That is the whole of least privilege, and it is why one credential per device beats one shared credential for the house.

Where to start looking

Log, then ports, then resources

When EMQX misbehaves, the hard part is rarely that something is broken. It is not knowing where to start looking. Plenty of people see the add-on fail to start, remove and reinstall the whole thing, and end up wiping their settings and losing their accounts too.

The Woow add-on README and the EMQX documentation agree on the same first move, and the order is worth memorizing.

FirstRead the log. The add-on log shows the startup sequence, the ngrok status and EMQX errors. Most start failures have their reason right here.
SecondCheck the ports. If another add-on is holding 1883 or 18083, EMQX cannot listen. Check whether Mosquitto, WebRTC and the like are still running.
ThirdCheck resources. EMQX uses more than Mosquitto does. Too little memory makes the add-on restart over and over, or not start at all.
In plain terms

Reinstalling before you have read the log is replacing the boiler because one radiator is cold. It might even work. But you will have spent a weekend and a lot of money on something a bleed key would have fixed in five minutes — and if the real fault was the pump, the new boiler has not fixed it either.

Every repair step should be the smallest safe action. Do not delete data on a hunch, and do not quietly move a port out onto the open network to see whether that helps. Before you touch data at all, take a backup.

Set a diagnostic baseline

  1. Step 1

    Confirm the add-on really started

    Open the Woow EMQX page in Home Assistant and see whether the state is started, or a restart loop. A restart loop usually shows a port or memory reason in the log.

  2. Step 2

    Check 1883 and 18083

    Make sure no Mosquitto or WebRTC is holding 1883 or 8083, so EMQX does not exit at startup because its listener port is taken.

  3. Step 3

    Search the log for keywords

    Searching the add-on log narrows the problem down fast. Three phrases do most of the work:

    address already in use — something else already holds that port
    cannot bind — the same problem, worded differently
    out of memory — the host does not have enough RAM left
  4. Step 4

    Test with an MQTT client you trust

    Connect to 1883 with a small tool you already have — the WebSocket client, or your Home Assistant MQTT integration. If it connects, the broker is accepting connections. If it does not, check whether authentication is set up, and whether the port and address are right.

flowchart TD
  A["The add-on will not start,
or keeps restarting"] --> B["Read the add-on log first"] B --> C{"Does it say address already
in use, or cannot bind?"} C -->|"yes"| D["Port conflict. Mosquitto
holds 1883, WebRTC holds 8083.
Stop the conflicting one"] C -->|"no"| E{"Does it say out of memory,
or not enough system RAM?"} E -->|"yes"| F["Resources. At least 512MB RAM
is recommended. Turn off other
add-ons that eat memory"] E -->|"no"| G["Test a connection to 1883
with a client you trust"] G --> H{"Does it connect?"} H -->|"yes"| I["The broker is accepting.
Look at the client's credentials
and the address it uses"] H -->|"no"| J["Check Authentication, the
listener port and the address"]
The order that answers most failuresReading the log is the only step before the first decision. Every yes branch peels off to the left and ends the search there; the no branch out of the first two diamonds carries on downward, and the last diamond ends both ways.
Four symptoms, four safe fixes

Symptom, check, safe fix

Four checklists cover most of what actually goes wrong. Each one is a symptom you can see, a check that finds the cause, and a fix that deletes nothing.

1 · It will not start, or it is running out of resources

Symptom: the add-on drops back to stopped shortly after it starts, or hangs on starting.

  • Check: read the log first. Then confirm whether another service is holding the port — Mosquitto uses 1883, WebRTC uses 8083 — and confirm the host still has enough memory.
  • Safe fix: stop the conflicting add-on or shed some load, then start EMQX once more. If memory is short, turn off the other add-ons that eat resources. Leave the data directory alone.

EMQX needs more RAM and CPU than Mosquitto does; the Woow README recommends at least 512MB RAM. If your host also runs video or AI services, cut back there before you add anything here.

2 · It cannot connect, or authentication keeps failing

Symptom: Home Assistant, Z2M or an outside device drops when it connects to 1883, or the error says authentication failed.

  • Check: confirm Authentication is configured in EMQX; confirm the username and password you are using exist in the built-in database and are correct; confirm the broker address (homeassistant, 1883) is right.
  • Safe fix: if authentication is not set up, create a user first. If an account was changed by mistake, create it again and switch to the correct password. Never print a real password into a log, or into an answer you give somebody else.

One thing to watch here, and it is the same fact from the start of this article seen from the other side: while EMQX has no authentication configured, it lets every client connect. A connection that works in that state is not proof that anything is set up properly. Either set up authentication, or turn anonymous access off.

3 · The Dashboard will not open, or a port is taken

Symptom: clicking Open Web UI gives you no page, or 18083 will not open.

  • Check: whether another service is holding 18083; whether the add-on is in the started state; whether Ingress is actually reachable.
  • Safe fix: go in through the EMQX icon in the Home Assistant sidebar, which is the Ingress route. Stop or adjust whatever service conflicts with 18083. Restart the add-on and try again.

The Dashboard is the way in to the whole broker. If you do want to reach 18083 directly rather than through Ingress, make sure it is not exposed to the public internet first.

4 · Connections drop after a while

Symptom: everything connects, works for a stretch, and then clients start falling off.

  • Check: the resource limits on the host, and the Rate Limit you set on the listener. EMQX uses more resources than Mosquitto, and a host tight on memory will make it less stable.
  • Safe fix: if normal clients are being dropped after you set a rate limit, check the time unit and the number in the limit, and raise the Flapping threshold to a level a normal reconnect will not trip. Healthy devices should not be locked out by mistake.

The quick reference

SymptomWhat to do
The add-on will not start and the log shows a port already in useStop Mosquitto or WebRTC first; confirm 1883 and 8083 are free, then start it
Cannot connect, and authentication keeps failingConfirm Authentication is set up, the credentials are correct, and the broker address and port are right; stop using the default public
The Dashboard will not openGo in through Ingress; if you hit 18083 directly, confirm there is no port conflict and that it is not exposed straight to the public internet
Connections drop after a whileCheck the resource limits and the Rate Limit; EMQX uses more resources than Mosquitto, and a host tight on memory will make it less stable
ngrok is enabled but there is no public URLGo back to Part 8 of this series: check the authtoken, restart, and read the ngrok service log
1883 is scanned from outside and people start trying to connectTurn the listener off or restrict it to the local network first, and only consider exposing it once both authentication and the ACL are in place
The TLS connection failsCheck the certificate chain, that the private key matches, and the CA; with a self-signed certificate you also have to add that CA to the client's trust store
The Dashboard is reachable straight from the public internet18083 is the HTTP admin port and is the last thing you want exposed. Restrict it to the local network or a trusted connection, and switch to HTTPS with a strong password
flowchart LR
  A["Nothing outside
can connect"] --> B["Test from a client on
the same local network"] B --> C{"Does the local
connection work?"} C -->|"yes"| D["EMQX is fine. Look at
the router, ngrok
or the firewall"] C -->|"no"| E["Usually authentication,
or the listener port
and address"]
Telling EMQX apart from your networkOne test splits the problem in two. The upper branch out of the diamond is the one where the broker is working and the fault is outside it; the lower branch keeps you inside EMQX.
Questions people ask

The ones that come up every time

Do I have to set up TLS for MQTT?
It depends on whether your traffic crosses an untrusted network. If Home Assistant and the devices only talk to each other on the same local network, that network is trustworthy enough — but still use strong passwords and an ACL. As soon as you need to reach outside or cross networks, encrypt with 8883 or 8084.
Will a rate limit slow down normal use?
Set it only on the listeners that face outward, keep the limit above your normal traffic, and you will barely notice it. What it blocks is one client flooding the broker; a normal household sends far less than the default limits, so it never bites. If something really is being throttled, try raising the limit.
After I change the Dashboard password, does MQTT use the same one?
No. The Dashboard password protects the admin interface. An MQTT client uses the account credentials from Access Control → Authentication. They are two separate sets, and both need a strong password.
Does EMQX Open Source have RBAC?
No. In EMQX 5.8 Open Source every Dashboard user is an administrator; RBAC (Administrator/Viewer) is an Enterprise feature. So on Open Source, keep the number of admin accounts as low as you can, and give the REST API an API key with the lowest role that works.
Is reinstalling the add-on faster than fixing it?
Often it is not, and there is a difference worth knowing. Upgrading the add-on does not clear your data, while reinstalling — especially removing it and installing it again — can take the data with it. Read the log first to rule out something you could fix in a minute, then consider a reinstall. And if you do go ahead, back up /data/emqx first.
How do I find out what is holding 1883?
Usually it is Mosquitto, which uses 1883, or the WebRTC integration, which uses 8083. Check the add-on and integration lists in Home Assistant and pause whichever one conflicts.
How do I tell that memory is the problem?
Look in the add-on log for messages such as out of memory or not enough system RAM. At least 512MB is recommended. With the resource-hungry add-ons paused, EMQX settles down more easily.
Nothing outside can connect: is that EMQX or my network?
Test the local connection first, with a client on the same network. If the local network works and the outside does not, go back to the router, ngrok or the firewall. If even the local attempt fails, it is usually the authentication or the listener port settings.
Next

Where to go from here

you made it

That is the whole broker, front door included.

Nine parts ago EMQX was an add-on you had not installed. It now carries your messages, checks who is asking, decides what they may touch, routes what matters through the rule engine, and tells you where to look on the morning it does not. Keep this part bookmarked — the four checklists are the ones you will come back to.

Open the full guide

Part 9 of the WoowTech EMQX Complete Guide series on the Apporo blog.

Adapted from the WoowTech EMQX Complete Guide, produced by WoowTech and released under CC BY 4.0. This adaptation is published by Apporo under the same licence.

Light · Air · Water · Control · apporo

in EMQX
Reading the log, reaching it from outside, and getting it back