Skip to content

Security

Key rules

  • default local and loopback-first flows are safest
  • pairing and discovery are not the same as open remote execution
  • runtime-cloud and remote-access flows need explicit policy

Start with the network model

PLC Networking & Remote Access

This guide explains which ports are used and how to enable remote access safely.

Default ports

  • Web UI: 8080 (HTTP)
  • Discovery: mDNS (UDP 5353)
  • Mesh/data: 5200 (TCP/UDP as configured)
  • MQTT broker (if any configured I/O driver is mqtt): 1883 (TCP, broker-defined)

Local‑only by default

trueST ships in local‑only mode by default. To enable remote access:

  1. Enable a TCP control endpoint in runtime.toml.
  2. Set runtime.control.auth_token (required for TCP).
  3. Use the pairing flow in the Web UI to share access.

Firewall checklist

  • Allow inbound TCP 8080 for Web UI (if remote web access is required).
  • Allow UDP 5353 for discovery (LAN only).
  • Allow TCP/UDP 5200 if mesh is enabled.
  • Allow TCP 1883 only when MQTT integration is explicitly enabled.
  • VPN (WireGuard or OpenVPN)
  • SSH tunnel for Web UI

TLS for remote endpoints

When exposing web/control endpoints beyond localhost, enable TLS explicitly.

Example runtime.toml settings:

[runtime.web]
enabled = true
listen = "0.0.0.0:8080"
auth = "local"
tls = true

[runtime.tls]
mode = "self-managed"
cert_path = "security/server-cert.pem"
key_path = "security/server-key.pem"
require_remote = true

Rules enforced by runtime schema:

  • runtime.web.tls=true requires runtime.tls.mode != "disabled".
  • TLS-enabled mode requires runtime.tls.cert_path and runtime.tls.key_path.
  • if runtime.tls.require_remote=true and web listen is remote, TLS must be enabled.

Troubleshooting

If remote access fails: - Check that the PLC is reachable by IP. - Verify firewall rules. - Confirm runtime.control.auth_token is set for TCP control.

Worked secure remote-access tutorial

Tutorial 16: Secure Remote Access (TCP Control, Token, Pairing, Firewall)

This tutorial configures a runtime for remote access without dropping basic security controls.

Why this tutorial exists

Remote access is where many PLC systems become unsafe. The goal is not only "make it reachable" but "make it reachable with explicit authorization and minimal exposed surface".

What you will learn

  • how to switch control endpoint from local socket to TCP
  • why auth_token is mandatory for TCP control
  • how pairing and firewall rules reduce exposure
  • how to enable and verify TLS for remote web/control exposure
  • how to validate remote access safely

Prerequisites

  • complete Tutorial 13 first
  • two terminals
  • optional second device on same LAN for remote verification
  • openssl available for local certificate generation

Step 1: Create an isolated tutorial copy

Why: do not modify your baseline project while testing network settings.

rm -rf /tmp/trust-remote-secure
cp -R /tmp/trust-tutorial-13 /tmp/trust-remote-secure

Step 2: Configure runtime for remote control with auth

Why: Unix sockets are local-only. Remote access requires TCP, and TCP requires an explicit token.

Edit /tmp/trust-remote-secure/runtime.toml:

[runtime.control]
endpoint = "tcp://0.0.0.0:17777"
auth_token = "replace-with-long-random-token"
mode = "production"
debug_enabled = false

[runtime.web]
enabled = true
listen = "0.0.0.0:18084"
auth = "local"

Recommended token generation:

openssl rand -hex 24

Expected result: - control API is remotely reachable only with token - Web UI is reachable on port 18084

Step 3: Keep network exposure minimal

Why: if every host can reach every port, token-only security is not enough.

Minimum ports to allow: - TCP 18084 for Web UI - TCP 17777 for control endpoint

Keep blocked unless needed: - UDP 5353 discovery (if not used) - mesh ports (if not used)

Use VPN or SSH tunnel for remote access when possible instead of opening WAN ports directly.

Step 4: Build and validate before launch

Why: ensure runtime config changes are valid before opening network services.

trust-runtime build --project /tmp/trust-remote-secure --sources /tmp/trust-remote-secure/src
trust-runtime validate --project /tmp/trust-remote-secure

Step 5: Start runtime

Why: runtime startup confirms endpoint binding and shows any config/auth errors.

trust-runtime run --project /tmp/trust-remote-secure

Expected result: - runtime starts without auth or bind errors

Step 6: Verify local first, then remote

Why: staged verification avoids debugging network and runtime issues at the same time.

  1. Local check: open http://127.0.0.1:18084
  2. Remote LAN check: open http://<host-ip>:18084 from another device

If UI asks for access/pairing, complete the claim flow from Network -> Access PLC.

Step 7: Validate control authorization behavior

Why: secure configuration must reject unauthorized control attempts.

  • attempt access without token/claim first
  • confirm runtime requires auth
  • then access using pairing or token workflow

CLI token handoff example:

trust-runtime ui --token <your-token>

Expected result: - unauthorized access fails - authorized access succeeds

Step 8: Commission TLS for remote access

Why: token auth protects control authorization, but TLS protects transport confidentiality/integrity for credentials and control traffic.

Create local test certificates:

mkdir -p /tmp/trust-remote-secure/security
openssl req -x509 -newkey rsa:2048 -sha256 -nodes \
  -keyout /tmp/trust-remote-secure/security/server-key.pem \
  -out /tmp/trust-remote-secure/security/server-cert.pem \
  -days 365 \
  -subj "/CN=trust-remote-secure"

Add TLS config in /tmp/trust-remote-secure/runtime.toml:

[runtime.web]
enabled = true
listen = "0.0.0.0:18084"
auth = "local"
tls = true

[runtime.tls]
mode = "self-managed"
cert_path = "security/server-cert.pem"
key_path = "security/server-key.pem"
require_remote = true

Then re-validate and restart:

trust-runtime validate --project /tmp/trust-remote-secure
trust-runtime run --project /tmp/trust-remote-secure

Verify HTTPS endpoint:

curl -k https://127.0.0.1:18084/

Expected result: - runtime starts with TLS enabled - HTTPS endpoint responds - plaintext HTTP requests are no longer the commissioning target

Step 9: Harden production posture

Why: remote debugging is a common accidental risk.

Confirm these production-safe defaults:

[runtime.control]
mode = "production"
debug_enabled = false

Keep auth_token rotated and never commit secrets to git.

Common mistakes

  • enabling TCP control without auth_token
  • enabling remote web/control exposure without TLS
  • setting runtime.tls.require_remote = true but leaving runtime.web.tls = false
  • exposing ports to the public internet directly
  • leaving debug enabled in production mode
  • storing token in tracked files

Completion checklist

  • [ ] TCP control endpoint configured with token
  • [ ] web endpoint reachable locally and remotely
  • [ ] unauthorized access blocked
  • [ ] authorized access works via pairing/token
  • [ ] TLS configured and HTTPS verified
  • [ ] debug disabled in production mode