Skip to content

Remote Access and Security

CONNECT has exactly one access rule, evaluated per request:

A caller is allowed in if it is on the local machine, if it presents a valid API key, or if it presents a valid dev key while remote development is switched on.

All other requests receive 401. A single authentication instance handles requests, except that /health requires no authentication. Individual endpoints add authorization checks to control who may do what; they do not use separate authentication methods.

The third case is remote development mode, which uses a second, separate key and is off by default. Developers of realvirtual use it to work on one running session from two machines. If you do not need this mode, leave the key empty and nothing changes.

For a gateway used only on the PC it runs on, this means: nothing to configure, and nothing reachable from outside without a key.

The one access rule /health is always answered without proof. Any other request is allowed if it comes from the local machine, otherwise if it carries a valid API key, otherwise if it carries a valid dev key while remote development is switched on. Everything else is answered with 401. Request Local machine? loopback peer Valid API key? header, Bearer, cookie Dev key + switch? development only 401 no no no yes yes yes Allowed in individual endpoints may still check what this caller may do /health → always answered (no proof)
/health bypasses proof; other requests follow the access rule.

Set ApiKey in appsettings.json next to the executable and restart the gateway:

{ "ApiKey": "a-long-random-value" }

An empty key disables the key mechanism, which is fine as long as the gateway is only used locally.

A key can be presented in three ways:

WayUsed by
X-API-Key headerScripts, Unity, MCP clients
Authorization: Bearer <key>HTTP clients that prefer it
Session cookieBrowsers, after the one-time link below

A browser cannot attach a header to a page it is asked to load, so a remote HMI would not be able to fetch even its own model. The one-time link solves this:

http://<host>:5100/?apikey=<key>

Opening that URL once exchanges the key for a session cookie and redirects to the address without the key. The cookie is httpOnly, SameSite=Strict and valid for one working day. Every later request from that browser, including every model download, carries the cookie.

The exchange happens on a page navigation only. Scripts, Unity and AI clients keep using the header and are unaffected.

Windows binds all network adapters by default, so other machines can reach a gateway without explicit setup. If the gateway is reachable beyond the local machine and has no API key, the tray menu shows a notice. It tells you to set ApiKey, then open the gateway once with the one-time link.

A purely local installation shows no notice.

CONNECT does not terminate TLS itself. The supported remote setup is a reverse proxy that terminates TLS and speaks plain HTTP to the gateway on the local machine.

When you do that, configure TrustedProxies with the proxy’s address so CONNECT can read the real client address from the forwarding headers. Without it, the original address is unknown, so requests arriving through the proxy need the API key, even when they start on the same machine. /health remains the exception.

TLS through a reverse proxy The browser talks HTTPS to a reverse proxy, which terminates TLS and forwards plain HTTP to CONNECT on the same machine. TrustedProxies lets CONNECT read the real client address from forwarding headers. Without it, requests through the proxy need the API key even when they start on the same machine, because the original address is unknown; /health remains the exception. Remote browser or script Reverse proxy terminates TLS CONNECT same machine, port 5100 HTTPS HTTP TrustedProxies = the proxy's address → CONNECT reads the real client address from the forwarding headers Without TrustedProxies: API key required through the proxy, even for a local client. Exception: /health answers without proof.
TrustedProxies lets CONNECT identify the original client behind the proxy.

The gateway warns at startup when it is reachable beyond the local machine without TLS, without trusted proxies or without an API key.

There are two exceptions:

/health answers without any proof. This allows monitoring without authentication. It returns only liveness, version identity and yes/no capability flags. Operational details (signal and client counts, license state) are available at /health/detail, which follows the normal access rule.

Some development routes refuse remote callers even with a valid API key. One runs a test command, so access with the gateway API key would allow remote code execution. Remote access to these routes requires the separate dev key below and a switch that is off by default.

This section is for developers of realvirtual. If you run CONNECT as a gateway, skip it - the feature is off and stays off unless you deliberately turn both halves on.

When CONNECT runs the realvirtual development server, only the local machine can access it. The normal API key does not grant remote access. A development workspace contains source files and customer project data; it is not a delivery. You can work on one running session from a second machine while preserving live reload and the plant connection. This supports desktop and laptop access, in the office or on the road. Configure both settings below:

HalfWhere
A dev key, Dev.ApiKeyappsettings.json next to the executable — empty by default
The switch realvirtual WEB → Allow remote access (dev)Tray menu — off by default, applies immediately

Either one missing means the remote machine is refused. The normal ApiKey never opens this.

Publish the gateway port to your tailnet using the tested setup below. Use the same port to keep the page, live-reload socket, HMI bridge and AI endpoint on one address:

Terminal window
tailscale serve --bg --https=5100 http://127.0.0.1:5100
# close it again
tailscale serve --https=5100 off

Then open this once on the other machine:

https://<magicdns-name>:5100/?devkey=<your dev key>

The key is exchanged for a session cookie and removed from the address, as with the API-key link above. Subsequent requests, including sources, live reload and the HMI, use that cookie. Scripts use the X-Dev-Key header instead.

  • The AI endpoint needs its own switch. MCP server → Allow remote clients is a separate setting that the dev key does not change. You can use remote development without allowing remote AI clients.
  • Switching the toggle off applies to new requests. A live-reload connection that is already open keeps running until it goes idle. Close the browser tab to end it immediately.

On Linux the startup gate still requires the normal ApiKey whenever the gateway is reachable beyond the local machine; the dev key does not substitute for it. An unlicensed installation gets no remote development either.

The access rule alone cannot detect a DNS rebinding attack. The attacker’s page keeps the same name while that name resolves to the local address. Three surfaces therefore also check the browser’s origin:

SurfaceRestriction
MCP endpointTrusted origins only, and local clients only unless remote MCP clients are explicitly allowed
Bundled HMI bridgeTrusted origins or the gateway’s own origin
Update confirmationTrusted origins or the gateway’s own origin

A bare IP address is accepted as a host, which is what keeps a remote HMI on http://192.168.x.y:5100 working: rebinding needs a name whose DNS answer can be changed after the page was served.

Trusted origins are the named entries of AllowedOrigins in appsettings.json and the ones added in the tray (Details ▸ Allowed origins); a * in that list counts for nothing. realvirtual’s own origins (https://web.realvirtual.io, https://realvirtual.io, https://www.realvirtual.io) are always allowed, without an entry: the hosted viewer and the public demo can read and control a gateway on the same PC with no configuration. Their AI Bridge asks for a one-time pairing in the tray — see AI clients. A viewer served from your own domain needs its origin added to AllowedOrigins.

The gateway exposes an MCP endpoint for AI tools. It is on by default, and writes are allowed by default, subject to the access rule above. Both switches are in the tray menu:

  • MCP server → Enabled: a startup switch. The tray offers a restart to apply a change.
  • MCP server → Allow write access: read live. Connected clients are notified when it changes.

Remote MCP clients are refused unless explicitly allowed. Details: AI clients.