Chapter 20

Network and secure deployment

Keep Matter's IPv6, mDNS and operational traffic on local paths you control, and handle VLANs, OTBR, Ingress, base path, Basic Auth, the IP allowlist and secret data correctly; shrink the exposed surface first, and talk about convenience after that.

Matter reachability and admin-interface security are two separate lines

A Matter controller has to discover the bridge over mDNS and then open an operational session over IPv6 or a similar path; the admin browser works through HAMH's HTTP, REST and WebSocket interfaces. Putting the HTTP side behind a reverse proxy does not forward Matter multicast for you, and getting an mDNS reflector working does not add authentication to the admin interface. When you design this, draw "controller to bridge" and "admin to the Web UI / API" as two separate paths.

In the pinned Stable 2.0.55, the Home Assistant add-on mirror sets host_network: true, turns on Ingress, mounts addon_config for persistence, and exposes the app log level, disable log colors, mDNS interface and strip global IPv6 options. Those are fixed facts about the add-on; a plain Docker or npm install is driven by start options instead, so do not assume the two interfaces have exactly the same fields.

Never expose it straight to the internet: behind the Web UI sit bridge controls, backups, plugin installation, Lock Credentials and the API. Basic Auth and the allowlist are a single layer of risk reduction, not multi-account RBAC, SSO, full auditing or a brute-force-resistant platform. Put it behind a trusted LAN / VPN and a controlled reverse proxy first.
PlaneTrafficRequired capabilityMain risk
HA planeHAMH to Home Assistant HTTP / WebSocketA reachable URL, a valid access tokenLeaked secrets, excessive permissions
Matter discoverymDNS multicastThe right LAN interface, IPv4 / IPv6 advertisementsMulti-interface mistakes, VLANs blocking it
Matter operationalUDP on the port the bridge is set to; a camera setup may also need TCPThe controller reachable in both directionsFirewalls, OTBR misrouting
Admin planeHTTP, REST, WebSocketIngress / proxy, authenticationUnauthorized actions and information disclosure

IPv6, mDNS, VLANs and OTBR

An IPv6 link-local address only works inside the same Layer 2 segment, so it is not a routing plan for crossing VLANs; going across subnets needs a routable Unique Local Address (ULA) and the right firewall and route entries. mDNS uses multicast to announce and query services; most routers will not forward it across VLANs on their own, so you need an explicit mDNS reflector / gateway policy, and the operational traffic from the controller to the bridge still has to be allowed in both directions.

On a host with several network cards, if you let mDNS advertise on every interface the controller may pick the Docker bridge, a virtual interface, the Thread interface or a global IPv6 address with no return path. mdns-network-interface limits mDNS to the real LAN interface; mdns-strip-global-ipv6 removes global IPv6 from the mDNS address set and keeps the locally reachable addresses; mdns-disable-ipv4 stops advertising IPv4 entirely, and you may only use it once you have confirmed that the controller and the whole path have IPv6.

An OpenThread Border Router (OTBR) can share a host with HAMH, but the Thread interface is not an ordinary LAN. Besides not binding mDNS to the Thread interface, check whether the IPv6 routes OTBR adds pull the cross-VLAN ULA return path into the Thread mesh. If the request arrives but the reply cannot get back, commissioning may show up as peer unresponsive; the fix is for the network admin to add a more specific LAN ULA route, not to turn IPv6 off.

The smallest workable topology: for the first commissioning, put the phone, the controller hub and HAMH on a controlled subnet where multicast and IPv6 both reach in each direction. Once that is stable, add VLAN policy one item at a time; change one layer per pass and verify it with Health Network Diagnostics.

Stable 2.0.55 start options and their limits

You can verify the options below in v2.0.55's start-options-builder.ts. The release channel is Stable and the maturity of the command-line and environment configuration is Stable; neither of those says anything about whether a particular controller supports IPv4, IPv6 or crossing VLANs. Server Mode, Camera and Security appear in Stable, but their product maturity is still experimental (experimental-in-Stable), and you must not confuse that with how settled the network options are.

OptionSecurity / network meaningMain limit
protocol-log-levelmatter.js MessageChannel / Exchange log detaildebug gives you per-packet payloads; use it only temporarily and protect the log
http-ip-whitelistAllows only the IPv4, IPv6 or CIDR entries you listAllows everything by default; behind a proxy the source address and the trusted headers have to be right
mdns-disable-ipv4Advertises mDNS over IPv6 onlyA controller without IPv6 cannot discover it
mdns-network-interfaceLimits which interface mDNS usesInterface names depend on the host; pick the wrong one and the bridge is never found
mdns-strip-global-ipv6Does not publish a GUA over mDNSDoes not exclude the Thread ULA; you still have to bind the right interface
http-auth-username / http-auth-passwordTurns on a single HTTP Basic Auth credentialNot multi-account, RBAC or SSO; needs TLS or a trusted proxy to protect the transport
http-base-pathMounts the Web UI and the API under a sub-pathThe proxy rewrite, the WebSocket and the prefix all have to agree
home-assistant-url / home-assistant-access-tokenTrust and connection from HAMH to HAThe token is required and is a secret; keep it out of public files, logs and URLs
storage-locationWhere identity, settings and backups are persistedNeeds least-privilege file permissions, a reliable volume and controlled backups
http-portThe admin HTTP listen portNot the Matter bridge operational port, and not proof that the firewall is safe
log-level / json-logsOperational records and log centralizationCentralized logs still need access control, redaction and a retention policy

The pinned add-on mirror only exposes the options its schema lists; do not write every plain start option up as an add-on UI field. The other way round, the Ingress URL is managed by the Supervisor, so never hard-code an ingress token or a base path. In documents and tickets, use explicit placeholders only, such as <INGRESS_PATH>, <LAN_INTERFACE> and <TRUSTED_PROXY>.

A safe deployment and change process

  1. Draw the two data paths

    List the segments and boundaries for HAMH to HA, controller hub to HAMH, and admin browser to HAMH. Mark <LAN_INTERFACE>, the VLANs, the proxy and OTBR, but keep real addresses, hostnames and identifying data out of a shared document.

  2. Verify IPv6 and mDNS first

    In Health → Network Diagnostics, read off the available LAN interfaces, the IPv6 types and the interface currently bound, without changing anything. Crossing VLANs requires a routable ULA, mDNS forwarding and firewall rules in both directions; while all you have is link-local, do not cross VLANs yet.

  3. Limit mDNS to the right interface

    On the add-on, set mdns_network_interface in Configuration to the LAN interface you confirmed on that read-only screen; on a plain deployment, use the matching start option. Only turn on strip global IPv6 when the global IPv6 return path is unreliable; only disable IPv4 when you are sure the IPv4 advertisement is unreachable and every controller supports IPv6.

  4. Build the smallest firewall rule set

    Allow mDNS between the subnets that need it, plus the operational port each HAMH bridge is actually configured with and its return path; let admin HTTP in only from the management VLAN / proxy. Do not assume a fixed list of bridge ports from a document; go by what the Bridges page actually says. If you run a bridge dedicated to the Camera Plugin, assess TCP on that same operational port as well.

  5. Protect the Web UI, the API and the WebSocket

    Prefer add-on Ingress or a trusted reverse proxy. In v2.0.55 the WebSocket path does apply the base path, but the upgrade is attached straight to the raw HTTP server and bypasses HAMH's Express Basic Auth and the application IP allowlist; the proxy has to authenticate and restrict the upgrade itself, and the backend must not be exposed directly to an untrusted network. On a plain deployment, the path rewrite, the frontend assets, REST and the WebSocket still all have to use the same prefix.

  6. Then add Basic Auth and the allowlist

    Supply the credentials through a secret manager or a restricted environment configuration; do not put the values in a compose example or your command history. List only the admin sources you need in the allowlist. Keep the monitoring requirement for health live / ready in mind: the code lets those two probes skip Basic Auth, which is all the more reason to restrict who can reach them on the network.

  7. Verify one change at a time, and roll back

    Change one thing at a time. After the restart, check Network Diagnostics, Health ready, the WebSocket live status, the bridge session and one low-risk endpoint. If it fails, roll back to the last known-good configuration; do not change mDNS, VLANs, the proxy and authentication all at once.

Ingress, Basic Auth, Lock Credentials and secrets

Ingress and the base path

When a non-root base path is configured, WebApi redirects the root path to that prefix and mounts the API and the Web UI on the same app router. It also supports Home Assistant Ingress and proxy location headers. Because prefix headers change how URLs are rebuilt, a trusted proxy should strip any incoming header of the same name and then write a fixed value; and the HAMH backend is best not listening directly on an untrusted subnet.

The reverse proxy has to proxy both ordinary HTTP and the WebSocket upgrade. Security exception: in v2.0.55 the upgrade does not inherit HAMH's Express Basic Auth or the application IP allowlist; a trusted proxy or network boundary has to authenticate and restrict the WebSocket, and block direct connections to the backend. If the page loads but the state never updates and Live Event shows Offline, the usual cause is that the WebSocket is not being forwarded or the base path does not match, not a broken Matter session.

Basic Auth and the IP allowlist

Basic Auth can come from an environment option or from the stored settings in Settings; when the environment setting exists, the code treats the environment as the source of truth. Its semantics are one username / password pair, not tiered permissions for several users. Without TLS, Basic Auth does not give you enough transport confidentiality; behind a proxy you also have to handle the source IP, or the allowlist may only ever see the proxy, or be swayed by a spoofed header.

http-ip-whitelist accepts IPv4, IPv6 or CIDR and can be given more than once; in ENV mode you can only give one value, and when it is unset every source is allowed by default. It is a network filter. It does not replace authentication, TLS, CSRF / browser risk management or application-level authorization.

Lock Credentials

Lock Credentials is a page you can reach in Stable 2.0.55, used to link a specific Home Assistant lock entity to a Matter PIN credential; when requirePinForRemoteOperation is on, a remote unlock / unbolt has to verify the PIN, while lock is still allowed without one. List responses come back redacted and the UI never echoes the secret; what is persisted is a PBKDF2 hash and a salt, not retrievable plaintext, but a short PIN has low entropy, so you still have to guard against offline guessing. You can add, update, enable / disable or delete entries. This is not a Matter commissioning credential, and it is not an ordinary website login password.

Security impact: Lock Credentials are used along with control commands, so both the storage and the backups have to be treated as highly sensitive. Never let a value appear in a screenshot, a log, a translation file, a support ticket or version control; after you rotate one, verify it in a low-risk, supervised situation, and do not use any real code value from this text.

HA tokens and secret handling

The HA access token, the Basic Auth password, plugin secrets, Lock Credentials and a full Matter identity backup all need a secret manager, a restricted environment or a root-only config, with the HA permissions and the set of people who can read the backups kept as small as possible. Protocol debug output, HTTP access logs and diagnostic exports need a short retention period and a manual check before you share them. Keep full backups encrypted and offline, and if you suspect a leak after a restore, run the matching rotation rather than only deleting a file.

Single-subnet, VLAN and OTBR scenarios

A single home LAN: add-on host networking, with the phone, the controller hub and HA on the same controlled segment. You still have to confirm that multicast is not suppressed by AP isolation or an IGMP setting, and keep the admin entry point limited to Ingress. A simple topology is not the same as being free to turn IPv6 off or to make the Web UI public.

A small-office VLAN: the controller hub sits on the IoT VLAN, HAMH on the Server VLAN, and admins come from the Management VLAN through a proxy. The network admin configures ULA routing and an mDNS gateway, and allows only the bridge operational traffic in both directions; admin HTTP only ever arrives through the proxy. Basic Auth is extra protection, not a substitute for the cross-VLAN firewall.

OTBR on the same host: pin mDNS to the LAN interface, and Network Diagnostics should not be showing the Thread interface as the advertisement exit. If a ULA VLAN is only reachable one way, check route selection; fix the return path with a more specific LAN route instead of bluntly deleting the Thread routes or turning IPv6 off.

Expose things in this order: LAN only first, then Ingress / VPN, then a trusted proxy with TLS; open it up across VLANs only when there is a concrete need. Do not read "the controller needs local access" as "any outside user has to be able to reach the HTTP interface".

Symptom, check, safe fix

  1. Commissioning cannot find the bridge

    Check: the phone / hub segment, mDNS forwarding, the bound interface, IPv6 and AP isolation. Safe fix: go back to one controlled Layer 2 segment and verify there, then restore the VLAN policy one item at a time; do not start with repeated factory resets.

  2. No Response after a successful commissioning

    Check: whether mDNS is publishing an unreachable interface or GUA, the firewall in both directions for the operational port, and session health. Safe fix: bind the LAN interface, strip global IPv6 if you have to, and restart the one bridge after fixing the firewall.

  3. Cross-VLAN connectivity drops after OTBR starts

    Check: whether the return IPv6 route has been taken over by Thread's broad ULA route. Safe fix: have the admin add a more specific LAN route for the remote controller VLAN, then verify the route; do not disable the whole of Thread.

  4. The reverse-proxied page opens but the data never updates

    Check: the WebSocket upgrade, the base path, and the ingress / forwarded prefix header. Safe fix: make the rewrite and the prefix agree, have the proxy overwrite the header, and reload the page.

  5. Turning on the allowlist locks the admin out too

    Check: whether the backend sees the client or the proxy, and how the CIDR and IPv6 entries are written. Safe fix: restore the previous config from the console and re-add the sources you have actually confirmed as trusted; do not open it to everyone as a temporary measure.

  6. Basic Auth forgotten, or the sources conflict

    Check: whether Settings shows the source as environment; the environment source wins. Safe fix: update or remove the matching secret from the host's controlled console, restart, and rotate it immediately; do not paste the value into an issue.

FAQ

Can Matter Hub disable IPv6 completely?
It should not. Matter operational connectivity depends on IPv6. mdns-disable-ipv4 only stops the IPv4 advertisement in mDNS; it does not disable IPv6. Crossing VLANs needs a routable ULA all the more.
Is Basic Auth multi-account, or RBAC?
No. In Stable 2.0.55 the semantics are one HTTP Basic Auth credential, with no roles, no fine-grained API permissions and no SSO guarantee.
Can the IP allowlist replace the password and the proxy?
No. It only filters source addresses, and the proxy topology can change which source is visible; you still need a controlled network, authentication and TLS.
Are Ingress and http-base-path the same thing?
No. Ingress is a proxy path the Home Assistant Supervisor provides; the base path is the mount setting for a plain web app. Both need the assets, the API and the WebSocket to share one prefix.
Why can mDNS not be bound to the Thread interface?
A controller on the LAN usually cannot use a Thread mesh-local address; even when both are ULAs, that does not make them routable to each other. Bind the real LAN interface.
Does the Lock Credentials list show values in plaintext?
The frontend uses a sanitized response and shows it redacted; but storage, use in commands and backups are still sensitive, so do not relax the protection just because the UI redacts it.

Pinned-version sources