Chapter 19

ngrok TCP tunnel

The ngrok TCP tunnel built into the Woow EMQX add-on: ngrok_enabled, authtoken, a reserved TCP address, the risks of exposing 1883, and Cloudflare Tunnel as the alternative.

Why this matters

The EMQX on your home network accepts connections from the local network only, so outside devices cannot reach it at all. But as soon as you want to subscribe or publish while you are away — to check the living-room sensor after you have gone out, or to turn off the hallway light remotely — you need a path between the local network and the outside world. From add-on version 5.9.0 onward, Woow EMQX has ngrok built in, and one setting turns raw MQTT (port 1883) into a public TCP tunnel.

Switch it on without thinking through the authtoken, the reserved address and the exposure risk, and you have handed the broker's front door to the whole internet. By the end of this chapter you will know what each of the three ngrok options controls, which line of the log carries the public URL, when to use Cloudflare Tunnel instead, and what you have to lock down before you go live.

Core concepts

ngrok is a tunneling service: it runs an agent on your machine, the agent opens a connection to the ngrok cloud, and traffic from outside is forwarded back through it to a local port. The Woow add-on uses that mechanism to turn the broker's 1883 into a public TCP address, and an outside MQTT client that connects to the address can publish or subscribe.

Keep the two version numbers apart: add-on version 5.9.0 only adds the built-in ngrok TCP tunnel, and the core underneath is still EMQX 5.8.9. When you change options such as ngrok_enabled and ngrok_authtoken you are changing the add-on layer; the authentication, ACL and monitoring behavior EMQX 5.8.9 already has does not change.

An ngrok tunnel carries its own security consequences: once 1883 is open to the public internet, anyone who can reach that address can attempt a connection. If EMQX has no Authentication configured it lets every client in, so the rule for this chapter is: set up authentication and the ACL first, and only then decide whether to switch ngrok on.

Terms at a glance

TermPlain EnglishIn one line
ngroktunneling serviceTurns a local port into a public TCP endpoint
TCP TunnelTCP tunnelA tunnel that forwards raw MQTT (1883) straight through
AuthtokenauthtokenYour ngrok account credential, required when you enable the tunnel
Reserved Addressreserved addressA TCP address reserved with ngrok that stays the same after a restart
Public URLpublic URLThe external endpoint ngrok creates, printed in the log
Cloudflare TunnelCloudflare TunnelThe alternative, and the better fit for WebSocket (8083)

Of these, authtoken is a secret: it is equivalent to the permissions on your ngrok account. Do not write your own token into HTML or paste it into a log; this guide always shows it as a placeholder (YOUR_TOKEN, <your-ngrok-authtoken>).

Hands-on

  1. Check your authentication first

    Before you turn ngrok on, go to Access Control → Authentication in the EMQX Dashboard and create a user, then set least privilege under Authorization. At a minimum, make sure that going public will not leave anonymous connections from the internet open.

  2. Turn on the add-on's ngrok settings

    In Home Assistant, go to Settings → Add-ons → Woow EMQX → the Configuration tab, find the three ngrok options and set ngrok_enabled to true.

  3. Fill in the authtoken (required)

    Paste your ngrok authtoken into ngrok_authtoken (shown here as <your-ngrok-authtoken>). If you have already reserved a TCP address on your ngrok account, put it in ngrok_tcp_addr; otherwise leave it empty.

  4. Restart and check the log

    Go back to the Overview tab and click "Restart". Once the add-on is up, open the Log and look for a line of the form >>> MQTT ngrok: <public_url> — that is the public address an outside MQTT client connects to.

The add-on's config.yaml defines the schema for the three options as: ngrok_enabled is bool (default false), ngrok_authtoken is password?, and ngrok_tcp_addr is str?.

The three ngrok options

Three options control the ngrok feature. Know their types and defaults and you know how much you have actually opened up.

OptionTypeDefaultWhat it does
ngrok_enabledboolfalseStarts and stops the ngrok TCP 1883 tunnel
ngrok_authtokenpasswordemptyAccount credential, required when you enable the tunnel
ngrok_tcp_addrstringemptyNames a reserved address so you get a fixed endpoint

The runtime behavior is straightforward. When ngrok_enabled is false, the ngrok service simply idles; when it is enabled but the authtoken is empty, the service logs an error and stays idle (EMQX itself keeps running as usual). Only once the authtoken has a value does it run ngrok tcp 1883, and if you filled in ngrok_tcp_addr it runs ngrok tcp 1883 --remote-addr=<address> instead.

If you only want outside access now and then, the simplest setup is an authtoken with everything else left empty, and let ngrok assign a temporary address.

The public address and the log

When ngrok is enabled the add-on runs a second service, ngrok-announce: it polls the ngrok agent's local API (http://127.0.0.1:4040/api/tunnels) every two seconds for up to about 120 seconds, and once it has the public URL of the first tunnel it prints it into the add-on log.

So the place to read the public URL is Home Assistant → Settings → Add-ons → Woow EMQX → Log. If it is not there right after a start, the service is probably still waiting for ngrok to come up, which takes up to about two minutes. If it still has not appeared after that, look at the ngrok service's own log — the usual cause is an authtoken that was not filled in correctly.

That public URL matters in practice: the MQTT client on an outside device has to be configured with it, port included, not with your Home Assistant address on the local network.

The risks of exposing 1883, and the alternatives

Exposing raw MQTT is not a matter of pushing a port out and forgetting about it. Read these points before you decide:

  • Anyone can attempt a connection: the ngrok address is public by definition, so it hands the broker's 1883 entrance to the whole internet. With Authentication not set up, EMQX lets anonymous clients through.
  • TLS is a separate job: the ngrok TCP tunnel is raw TCP, and it does not encrypt the connection for you. If you need encryption, switch to or add an MQTTS (8883) listener.
  • A temporary address does not last: with no reserved address filled in, the endpoint ngrok assigns can change on every restart.
  • Keep exposure minimal: if you need it only occasionally, open it for a set window and close it again when you are done; for long-term exposure, finish authentication, the ACL and whatever TLS you need first.

If what you need is WebSocket rather than raw TCP, this will not connect: the add-on's ngrok covers 1883 (raw MQTT) only, and 8083 (MQTT over WebSocket) is outside the scope of ngrok, so use Cloudflare Tunnel instead.

Troubleshooting

  • Enabled, but no URL in the log: first confirm that ngrok_enabled is true and the authtoken is filled in, then check whether the log holds an "enabled but authtoken is empty" error. If both are right and there is still nothing, restart the add-on or look at the ngrok service's own log.
  • All you see is "ngrok not enabled": the setting has not taken effect. Go back to the Configuration tab, check ngrok_enabled, restart, and read the log again.
  • An outside client cannot connect: check that it uses the full URL and port ngrok printed rather than a local-network address, and that you have created the account in EMQX and the ACL allows that topic. If the address keeps changing, switch to a reserved address (ngrok_tcp_addr).
  • Any client on the internet can get into 1883: turn ngrok off first, go back to EMQX and set up Authentication and Authorization, and only then decide whether to expose it again. A public broker that accepts anonymous connections is an obvious warning sign.

FAQ

Do I have to use ngrok to reach EMQX from outside

No. ngrok is only the most convenient method the add-on ships with; a VPN, Cloudflare Tunnel or another reverse proxy can forward to 1883 just as well. If you already run a VPN or a tunneling service, use that first — it keeps the broker off the public internet.

Does the automatic address really change on every restart

Quite possibly. The temporary TCP endpoint ngrok assigns often comes back with a different number after a restart, so when you want a fixed public endpoint, reserve one on your ngrok account and put it in ngrok_tcp_addr; the same address then survives a restart.

Can 8083 (MQTT over WebSocket) go through ngrok

No. The add-on's ngrok handles 1883 raw MQTT only; to serve WebSocket externally, use Cloudflare Tunnel — that is the alternative the official CHANGELOG and README point to.

What is the minimum to configure before going public

At a minimum you have to be able to refuse anonymous connections: create an authenticator under Access Control → Authentication in EMQX (Password-Based → Built-in Database is the recommended choice), then set least privilege under Authorization. If you need encryption, consider an MQTTS (8883) listener.

Official sources