# Remote access

> The Remote access page: opening this station's dashboards to other devices on the network, over HTTPS if you choose, who may use them, the browsers connected right now and the tablets and PCs configured to open in a way of their own, and the restart every change costs.

Remote access is a page of its own, the entry of the navigation rail's foot group right after [Agent](agent), drawn only for a role that holds **View remote access**; the `/remote-access` route is guarded by the same permission. Off, the station's web host answers only its own machine on the loopback address, which is how the desktop window itself draws the interface, and nothing listens on the network. On, every network address of the station is bound too, and a tablet or another PC on the same LAN can open the same interface in a browser. The page says what it is under its title: "Opens this station's dashboards in a browser on the computers and tablets of your network. It receives connections and never makes one." It holds three cards, **Status**, **Configuration** and **Client access**: **View remote access** reads them, and **Configure remote access** turns remote access on and off and changes its settings. Every change restarts the web server that draws the very screen you are on, so each asks first.

## On and off {#on-and-off}

The bar at the top of the page reads its state beside its icon: "Turned off", "Listening on port 18760", "Starting…" while the web server comes back after a change, "No network address" or "Could not start". Its dot is grey while remote access is off, green while other devices reach the station, amber while it starts or has no address to give out, and red when the network was refused.

**Enable** and **Disable** on the command bar turn it on and off. On a new station it is off. On: the web host binds each LAN address of the station beside the loopback one, the app adds a Windows Firewall rule named "Ganter Lab Dashboard" (inbound TCP on the port, Private and Domain profiles, local subnet only) and installs an allowlist that refuses any source outside the private address ranges. Off: only loopback is bound and the rule is removed. A role without Configure remote access is not drawn the two verbs, and reads the cards without changing them. Each verb stays drawn and greyed with the reason while remote access is already in its state. Both verbs and the settings are greyed the same way while a unit runs or the runtime is stopped, as on the [Connector](connector#engineering-boundaries), and on the published demonstration, whose address is fixed when it starts: "This demonstration's address is fixed when it starts, so remote access cannot be changed here."

## The settings {#the-settings}

| Field | What it is | Values / default | Effect |
| --- | --- | --- | --- |
| Serve over HTTPS (self-signed certificate) | Drawn only while remote access is on. Encrypts the LAN traffic with a certificate the station makes for itself. | On or off. Off by default. | On: the LAN addresses serve HTTPS; the loopback address stays plain HTTP, so the desktop window is never affected. Each device asks you to accept the station's certificate the first time. |
| Port | "The network port this station listens on. Changing it restarts the web server: this screen reloads on its own, and dashboards open elsewhere have to be reopened at the new address." | 1 to 65535. Default 18760. | The port for loopback and LAN alike. The field commits when you leave it or press Enter, never per keystroke. Text that is not a whole number, and the port already in force, drop back to the value in force without a word. A port the station cannot move to is refused before anything is stored: the reason is said under the field, the field goes back to the port in force, and nothing restarts. Six entries are refused, in this order: a number outside the range, however many digits it has ("Listen port must be between 1 and 65535."); the port agent access is set to on the [Agent](agent) page, whether agent access is on or off ("Port N is already agent access. Pick another port, or move agent access first."); the port of the OPC UA server on [Configuration](connector-opcua-configuration), running or stopped ("Port N is already the OPC UA server. Pick another port, or move the server first."); the port of the [Modbus server](connector-modbus-server) on the Connector page, on or off ("Port N is already the Modbus server. Pick another port, or move the Modbus server first."); the port of the [MQTT broker](connector-mqtt-broker) on the Connector page, on or off ("Port N is already the MQTT broker. Pick another port, or move the MQTT broker first."); and a port something else on this machine already holds ("Port N is in use on this machine. Close what is holding it, or pick another port."). The reason stays under the field until the next entry the field does not refuse. |
| Names this station answers by | "Leave this empty unless the station is opened by a name of its own, such as a DNS alias or the name of a reverse proxy in front of it: a request that arrives under any other name is refused. Separate names with commas, and write only the name, with no http:// in front, no port and no path." | A list of host names separated by commas. Empty by default. | Each name joins what the station answers to, beside the addresses it bound and its own machine name, whether remote access is on or off. The field commits when you leave it or press Enter; an entry that is not a host name is refused under the field and nothing is stored. |

The **Status** card shows where the station is reached. While remote access is off it reads "Remote access is turned off, so only this computer opens the station's dashboards and nothing listens on the network." On a station with a network address, the QR code and the address it will give follow, greyed, under **Open on another device, once remote access is on**: "This code and this address open nothing until remote access is on. Then a browser on the same network opens the station by scanning the code or typing this address:". That address is the first network address of this computer, read the way the host reads them when remote access turns on, so it is the one the host binds first; on a station with no network address the card shows the sentence alone. While it is on, it shows one of three things.

- **Open on another device**: a QR code and the address to type, `http://<address>:<port>/` (or `https://`), where the address is the first LAN address the host bound when it started. Scan it or type it in a browser on the same network.
- "This station isn't on a network yet. Connect it to your plant network to get an address to share.": remote access is on, but the station had no LAN address when the host started, so only loopback is bound and no firewall rule was created. The setting stays on, and the host is rebound when an address appears.
- **Remote access is unavailable**, a caution banner: HTTPS was requested and the certificate could not be loaded or created. The banner carries the reason: "Remote access was not started because its HTTPS certificate could not be loaded or created. Loopback access remains available; check Events and change the remote-access setting to retry." The station never falls back to plain HTTP on its own, and a "Remote dashboard unavailable" notification says the same when the host starts.

Wherever the card shows the code, off or on, a line under it names the address that opens the station on its own computer, `http://localhost:<port>` on the port the station listens on. It answers whatever remote access says, because it is the loopback address the station's window itself is drawn from; a browser there enters as the Not signed in role.

| Where the page is read | The line |
|---|---|
| The station's own window | "Open `http://localhost:<port>` in a browser on this computer: the station opens there already, with nothing to turn on.", the address a link that opens it in the Windows default browser |
| A browser, on this computer or another | "On the station's computer, open `http://localhost:<port>` in a browser: the station opens there already, with nothing to turn on.", the address as text, because on a tablet localhost is the tablet itself |

On the published demonstration it reads "This is the published demonstration: visitors reach it at the address they opened it at."

The **Client access** card says who may come in: a browser on another device enters with its own sign-in, and only while its role holds **Remote access (LAN)** (see [Who may open a dashboard](#who-may-open-a-dashboard)). While remote access is on, it also reads the state of the "Ganter Lab Dashboard" rule under **Windows Firewall**, and offers **Allow local network** while that rule is not in place; only the station's own window can press it (see [The firewall rule and the address watch](#the-firewall-rule-and-the-address-watch)).

## Applying a change: the restart {#applying-a-change-the-restart}

**Enable**, **Disable**, the HTTPS switch, a new port or a new list of names opens the dialog **Restart the web server?**. Its paragraph states the cost and ends with "This screen is drawn by that server, so it stops for a few seconds and comes back on its own.":

- **Enable**: "Opening dashboards on other devices restarts the web server.";
- **Disable**: "Closing dashboards on other devices restarts the web server, and a device that reads this station over the network stops reaching it.";
- HTTPS on: "Serving over HTTPS restarts the web server, and each device asks you to accept this station's own certificate the first time."; HTTPS off: "Serving over plain HTTP again restarts the web server.";
- a new port: "Moving this station to port N restarts the web server.";
- names declared: "Answering by these names restarts the web server."; the field emptied: "Answering only by this station's own addresses again restarts the web server."

**Cancel** stores nothing: remote access and the HTTPS switch stay on what the station listens on, as they did under the question, and the port field and the names field go back to what the station listens on and answers by. **Apply and reload** saves the setting; the app then removes the old firewall rule, stops the host, starts it with the new options and recreates the rule. While that happens a cover titled **Restarting the web server** stands over the app: "The screen comes back on its own as soon as the station answers again." on the desktop window, "The screen comes back on its own as soon as the new address answers." in a browser, followed there by "You sign in again when the screen comes back: a browser's session ends with the restart.", and in both "Acquisition, recording and the OPC UA server keep running the whole time." A browser probes the new address every half second for up to thirty seconds and goes there when it answers; if nothing answers in time the cover steps aside and the ordinary reconnection screen, with its Try again and Reload, takes over. The desktop window re-points its own view. Whoever asked for the change is the one who waits; every other device simply loses its connection and reconnects. A browser that turned remote access off has, by its own choice, nothing to come back to.

## HTTPS and its certificate {#https-and-its-certificate}

The certificate is self-signed, issued to "Ganter Lab Dashboard", valid for five years, and lists `localhost`, `127.0.0.1` and every LAN address the station had when it was made. It is kept as `dashboard-cert.pfx` under the station's data root and is made again when it is missing, unreadable, within a day of expiring, or no longer covers one of the station's addresses. Browsers do not trust it by themselves: each device shows its own warning once and you accept the station's certificate there. Without HTTPS, sign-in PINs cross the network in clear text, and so does anything else the station shows over the network, including the OPC UA server user name on [Configuration](connector-opcua-configuration); a password typed there crosses the same way on its way in, though the stored one is never sent to the browser.

## The firewall rule and the address watch {#the-firewall-rule-and-the-address-watch}

The "Ganter Lab Dashboard" rule is created and removed with `netsh` as the app applies the setting. Creating a rule needs elevation, and the app does not assume it: a failure is journaled and swallowed, because the bind and the private-range allowlist still confine the host, and Windows then shows its own "allow access" prompt instead. The rule is dropped and recreated on every change, so no stale rule for an old port stays behind. A demonstration or test launch, one whose data folder was moved to a folder of its own, neither creates nor removes the rule: the rule is named for the whole machine, and removing it would take the remote access of the installed program away. A copy of the program that was not installed, such as a development build, leaves the rule alone too, for the same reason.

The station's addresses can move under a running host (a new DHCP lease, a move from Wi-Fi to cable, a dock). The app watches them and, while remote access is on, rebinds the host on the current addresses, which also renews the certificate when it no longer covers them; the address card follows.

## Opening the station by a name of your own {#opening-the-station-by-a-name-of-your-own}

A station knows two kinds of name by itself: the addresses it bound, and the name Windows registers for the machine. Two deployments give it a third that it cannot know. One is a DNS alias, where the plant's own DNS points a friendly name at the station's address. The other is a reverse proxy, where a server in front of the station takes the connection and forwards it. In both, the browser writes that name into the request, the station compares it against what it publishes, and a name nobody declared is turned away with `403` before a page is drawn. **Names this station answers by** is where you write it down: the name exactly as the browser sends it, one name after another with a comma between them, and nothing else, because a scheme, a port or a path in the field would be a name no request can ever carry.

The list is read every time the web server starts, so a change takes effect through the same restart the other settings here cost. It does not follow the state of remote access. A proxy on the station's own machine forwards to the loopback address, which the station keeps open whether remote access is on or off, while a proxy anywhere else on the network needs remote access on to reach the station at all. Declare only names that really lead here: every name you add is one more name a page in a browser is allowed to address this station by.

## Who may open a dashboard {#who-may-open-a-dashboard}

The first question is not who is asking but what the request addressed. The station answers at `127.0.0.1` on its own machine, at every name declared in **Names this station answers by**, and, while remote access is on, at each LAN address it bound and at this machine's own network name; a request that names any other host, or that carries a page of another site as its origin, is refused with `403` and the line "This station answers only at the address it publishes." before a screen, a file or a connection is served. That is what keeps a site you happen to be visiting from driving this station through your browser: such a page can point its own domain at this machine, but it cannot choose the address the browser writes into the request it makes for it, and the attempt is journaled to Events. The agent endpoint refuses its own callers by the same rule.

The web host serves the whole interface, not only dashboards, and every browser is its own connection with its own signed-in user. Whether an identity may enter from the network at all is its role's **Remote access (LAN)** permission on the [Users](users) page: a browser whose identity lacks it sees no page, only the sign-in panel, until someone with the bit signs in. The **Not signed in** role has it off by default, so turning remote access on shares nothing until a user signs in, unless you deliberately grant that role the bit for a kiosk or a tablet. A browser on the station's own machine is never gated by it. From there on the signed-in role decides everything else, exactly as on the station's window; see [Signing in](users-signing-in).

## Connected browsers and configured devices {#connected-browsers-and-configured-devices}

A tablet beside a machine or a PC on the shop floor opens the station's address every day. The **Client access** card lists every browser that has the station open from the network under **Connected now**, and turns any of them into a configured device: one the station recognizes from then on and opens the way its row says, on a screen of its own, locked there if you want, signed in by itself, back at its start after being left alone, or view-only. The device opens the station's address as it always did: there is no QR code or pairing link for it.

### Connected now {#connected-now}

"Every browser that opens this station from another computer or tablet right now, signed in or still at the sign-in screen. This computer's own window is not listed." A browser on the station's own machine is not listed either. Each row names the browser and its system as the browser says them ("Chrome running on Windows", "Safari running on iPad"), or the device's name for a configured one, and a line with its address, the page it has open (**At the sign-in screen** while it has not signed in), who is signed in on it (**Not signed in** when nobody is) and since when. With nobody there the group reads "No browser on another computer or tablet is connected right now."

For a role that holds Configure remote access, each row carries two verbs:

| Verb | What it does |
| --- | --- |
| **Identify** | "Shows a large code across this browser's screen for 30 seconds, and the same code on this row, so you can tell which device the row is." The device's screen shows **The station is identifying this device** and "Check that this code stands beside the right row on the station's screen." beside the code, with **Dismiss**. Nothing is stored. |
| **Configure this device** | Drawn on a browser the station does not know yet. "Gives this browser a key that makes the station recognize it from now on, and lists it under Configured devices. Its screen reloads once." The device then stands under **Configured devices**, named after its browser, with a number after the name when another device already has it, and its row opens for editing. |

### The device's key {#the-devices-key}

Configuring a device never shows a key anywhere. The station sends that browser, through its own connection, to a one-time address that writes a key into a cookie of that browser which no page can read, and the screen reloads once. The station keeps only a hash of the key, nothing is stored if the browser leaves before it reloads, and every page the device loads renews the cookie, so a device in use keeps its key. The key belongs to that browser and to the address the station was opened at: a browser that is cleared or reset, another browser on the same tablet, or the station opened under another of its addresses is an unknown browser again, back under Connected now, and is configured anew. Over plain HTTP the key crosses the network the way a sign-in PIN does; [HTTPS](#https-and-its-certificate) covers both.

### Configured devices {#configured-devices}

"Each device holds a key this station gave its browser, and opens the way its row says. A browser that is cleared or replaced loses its key and comes back under Connected now as an unknown browser." Each row has a dot, green while the device is connected, its name, and a line that says how it opens: **Connected right now** or **Not connected**; then "Starts on Oven overview", "Locked on Oven overview" or **Opens like any browser**; then "Signs in as Vera" or **Asks for a sign-in**; **View-only** when it is; and "Back to its start after 5 min untouched" when it goes back. When something it points at changed, a note under the row says what the device does instead:

- "Its fixed user was deleted, so it asks for a sign-in."
- "The role of Vera no longer holds Remote access (LAN), so it asks for a sign-in."
- "Its start screen was deleted, so it opens on View with the whole program around it and no lock."

Pressing a row opens its settings under it. Each is saved as soon as you leave the field or flip the switch, and reaches the device's open screen at once.

| Field | What it is | Values / default | Effect |
| --- | --- | --- | --- |
| **Name** | "What the station lists this device as, and what the journal records beside everything done from it." | Any text; the browser's name at first. | Renames the device wherever it is listed. |
| **Start screen** | "The screen this device opens on and goes back to. Without one it opens like any browser." | **No start screen** (the default) or one of the station's screens. | The device opens there. A screen deleted later leaves the device opening on View, with the note above. |
| **Locked on its start screen** | The device stays on its screens (see [On the device](#on-the-device)). | Off by default. | Greyed with "Choose a start screen first: a device is locked on it." until a start screen is chosen; clearing the start screen unlocks it. |
| **Sign-in on this device** | Who the device is while nobody has signed in on it. | **Asks for a sign-in** (the default) or a local user whose role holds Remote access (LAN); no other user is offered. | The device enters as that user with no sign-in. Greyed for a role without Manage local users: "Choosing who a device signs in as takes Manage local users besides Configure remote access." |
| **Back after (minutes untouched)** | "After this many minutes without a touch the device goes back to its start screen and to its fixed user. Empty: never." | 1 to 1440, or empty. Empty by default. | A touch, a key or the pointer moving starts the count again. |
| **View-only** | "Nobody commands anything from this device, not even an administrator signed in over it: commands stay drawn, greyed with the reason." | Off by default. | Every command of the device reads "This device is view-only." |

**Forget** on a row deletes the device after "Forget 'Line 3 tablet'?": "Its browser keeps the key, but this station no longer recognizes it: it asks for a sign-in like any browser until it is configured again. This cannot be undone.", with **Forget** and **Keep it**. An open screen of that device becomes an unknown browser at once.

### On the device {#on-the-device}

A device with a start screen opens on it. Locked, it is drawn like the Expand mode of View: no navigation rail, no title bar and no other page, the status bar shown only if the screen keeps it in full screen, and any other address typed into it takes it back to its start screen. Buttons set to **Open another dashboard** are the only way to another screen, and a screen the role in force does not see stays out of reach. The status bar still says the health, the alarms and the recordings, without leading anywhere. A discreet **Sign in** key in the top-right corner opens the usual sign-in dialog; while someone is signed in over the device's user it carries that person's name, and its dialog signs them out again. Nothing on the device lifts the lock: the device is changed here.

What the fixed user, signing in over it, going back after the minutes untouched and view-only do to who is signed in is on [Signing in](users-signing-in#configured-devices). Every record the journal keeps of what was done from a configured device carries its name, read as **Remote device** in the record's details on [Events](events-console) and exported in a column of its own.

A browser cannot put itself in full screen, and a page cannot keep it there: that is the device's own kiosk mode. On an iPad it is Guided Access (in Settings, Accessibility, then a triple press of the side or home button with Safari open); on Android, screen pinning in the security settings, or a kiosk browser; on a Windows PC, Chrome or Edge started with `--kiosk` followed by the station's address, or Windows' assigned access.

### Who may change them {#who-may-change-them}

View remote access reads both lists. Configure remote access identifies, configures, changes and forgets devices, and choosing a fixed user also takes Manage local users, so a role that only configures remote access cannot put an administrator on a tablet. A running unit or a stopped runtime greys the verbs and the fields with the reason, as on the [Connector](connector#engineering-boundaries). The agent reads both lists with `remote_access_devices` and changes a device's settings, never its fixed user, with `remote_access_device_update`. The published demonstration lists neither: "The demonstration lists neither the browsers connected to it nor any device: its visitors are other people."

## What a remote browser cannot do {#what-a-remote-browser-cannot-do}

A few actions exist only on the station's own desktop and stay greyed in a browser with "Available on the station's local desktop only.": opening the backups folder, restarting to take an update, and opening the detached Events window from the Warnings meter. The Desktop zoom row is not drawn at all. Trusting, blocking, revoking and importing certificates on [Client access](connector-opcua-client-access) and [Equipment access](driver-opc-ua#equipment-access), and the OPC UA firewall button, are refused in a browser: "Client access can only be changed in the station's desktop app." Everything else, these remote-access settings included, follows the signed-in role.

## What this section does not do {#what-this-section-does-not-do}

The station is never exposed to the internet and sets up no tunnel: the bind is a LAN bind, the firewall rule is scoped to the local subnet, and the allowlist refuses public addresses even if both were misconfigured. There is no list of devices allowed in or refused (any browser that signs in as a user holding Remote access (LAN) still enters), no way to disconnect a browser from here, no separate password for viewing (identity is the local user), and no language or theme per device: the language is the station's and the theme each browser's own. The port of the agent endpoint is set on the [Agent](agent) page, not here.
