Skip to content
SZ-MCP
Get Support

Reach a private or self-signed controller

A controller that is not reachable from the internet, or that has a self-signed certificate, can be reached through the controller tunnel: a Cloudflare Tunnel that SZ-MCP creates for your organisation. You run its connector, cloudflared, on a machine next to the controller. That machine needs only outbound HTTPS, so you open no inbound port.

The tunnel is in limited rollout and must be enabled for your account: contact support to have it enabled. Until then the card reads “Controller tunnels are in limited rollout; ask an sz-mcp admin to enable them for your account.” Only an organisation admin (or the owner) can create, change or remove a tunnel. Every member can see its status.

A controller with a publicly trusted certificate on a public address doesn’t need the tunnel. See Controller requirements.

How does the tunnel connect SZ-MCP to my controller?

Section titled “How does the tunnel connect SZ-MCP to my controller?”

SZ-MCP calls a hostname of its own on Cloudflare, and Cloudflare forwards the request down the tunnel to cloudflared, which calls your controller on the LAN. Each organisation’s tunnel gets:

  • a random hostname such as sz-abcdefghijkl.neuralconfig.dev, served on port 443;
  • a Cloudflare Access application on that hostname that admits one service token. Only SZ-MCP holds it, and it is sent with every request, so nobody else gets past Cloudflare’s edge;
  • a tunnel whose only route is your controller’s LAN address. Requests whose path starts /wsg/api/ or /switchm/api/ (the WSG and SwitchM APIs) are passed through. Everything else, including the controller’s web UI, gets a 404.
Your networkCloudflare edgeHTTPS to the tunnelhostname, port 443/wsg/api/ and /switchm/api/onlyHTTPS, certificate notcheckedSZ-MCP(Cloudflare Worker)Accessadmits only SZ-MCP'sservice tokencloudflared(outbound HTTPS only)SmartZone controllerhttps://LAN address:port

On the last hop, cloudflared connects to the controller over HTTPS but does not check the controller’s certificate. That is why a self-signed controller works through the tunnel. The certificate SZ-MCP checks is Cloudflare’s own, for the tunnel hostname.

Everything happens on Configure › Controller (/settings/controller), in the Private controller (tunnel) card and the SmartZone login card above it.

  1. Create the tunnel. Under Controller address on your network, enter the controller’s address as the machine running cloudflared reaches it: a name, an IPv4 address or a bracketed IPv6 address, such as 192.168.1.20 or sz.corp.local. Set Port to the controller’s HTTPS API port; it defaults to 8443. Click Create tunnel. Private addresses are fine here, because only cloudflared connects to them.

  2. Run the connector next to the controller. The card shows two commands; run either one on a machine on the controller’s network:

    Terminal window
    cloudflared tunnel --no-autoupdate run --token <token>
    Terminal window
    docker run -d --name sz-mcp-tunnel --restart unless-stopped cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <token>

    The token is the tunnel’s credential: keep it like a password. If you need the commands again later, an admin can click Show run command.

  3. Use the tunnel for the login. Click Use for the login. The SmartZone login form fills in the tunnel hostname and port 443, clears the password, and says “Host set to the controller tunnel. Enter the username and password, then Save & detect.”

  4. Save & detect. Enter the SmartZone username and password and click Save & detect. SZ-MCP logs in through the tunnel and detects the API version, as for any controller. See SmartZone credentials.

  5. Test. Click Test connection to check the saved login end to end. The tunnel card now shows Used by the login: yes.

When the login uses the tunnel, the port is always 443, whatever you choose. A hostname in the tunnel’s domain must be your own organisation’s tunnel. Anyone else’s is refused with forbidden_host and ”… is not this organisation’s controller tunnel”.

The chip is Cloudflare’s view of the tunnel. Next to it, the card shows how many connections cloudflared holds and which Cloudflare locations they go to.

ChipMeaning
waiting for cloudflaredThe tunnel exists but cloudflared has never connected. Run the command from step 2
healthycloudflared is connected
degradedCloudflare reports the tunnel as degraded. The chip is drawn as a warning
downCloudflare reports the tunnel as down. The chip is drawn as critical
deletedThe tunnel no longer exists on Cloudflare
unknownCloudflare did not report a status. If the status could not be read at all, the card also says “Couldn’t read the tunnel’s status: …”

The card also lists the Hostname (with “(port 443)”), the Controller on your network (the LAN address and port you entered), and whether it is Used by the login.

LimitValueAt the limit
Tunnels per organisation1This organisation already has a controller tunnel.
Tunnel creations per organisation5 an hourrate_limited
Tunnels on the service200 in totalNo more controller tunnels can be created right now.
Paths passed to the controller/wsg/api/… and /switchm/api/…Any other path gets 404 from Cloudflare

Use Change address when the controller moves, and Remove when you no longer need the tunnel.

  • Change address points the same tunnel at a new LAN address and port. The hostname and the token stay the same, so cloudflared and the saved login carry on. The card says “LAN address changed.”
  • Remove deletes the hostname, the Access application and its token, and the tunnel itself. After confirming “Remove the controller tunnel?” the hostname stops working at once, and you can stop cloudflared.

You can’t remove a tunnel while the controller login uses it. The card hides Remove and says “To remove the tunnel, change or delete the controller login first.” The API refuses with tunnel_in_use: “The controller login uses this tunnel: remove or change the login first.”

Three errors come from Cloudflare’s edge rather than from the controller. They appear when SZ-MCP logs in through the tunnel: on Save & detect, on Test connection, or when it fetches a fresh SmartZone service ticket for Claude or for background polling.

CodeDetailWhat to check
tunnel_downno cloudflared is connected to the tunnel: start it next to the controllercloudflared is running; the chip shows down or waiting for cloudflared
tunnel_origin_unreachablecloudflared is running but cannot reach the controller at the LAN address the tunnel namesThe controller’s LAN address and port. Use Change address if it moved
tunnel_access_deniedCloudflare Access refused the tunnel's service tokenContact support

These errors are treated as temporary. Unlike a rejected password, they do not pause the background inventory sync or metric polling, which retry on their next run.

Errors from the card itself appear as Error: …:

CodeMessage
tunnel_existsThis organisation already has a controller tunnel.
invalid_originName the controller as the LAN reaches it, not a tunnel hostname.
tunnel_in_useThe controller login uses this tunnel: remove or change the login first.
tunnel_capacityNo more controller tunnels can be created right now.
tunnel_failedCloudflare refused a step; the detail names the step. A failed creation undoes what it made, and a failed removal can be retried