Security
Network exposure defaults, unauthenticated protocol endpoints, writable members, and Docker port binding for Miravo.
Miravo is a simulator for development, testing, and demos. Run it on a laptop, a CI runner, or an isolated lab network. Do not expose it to the internet or to a production OT network.
Bind defaults
| Listener | Default bind | Opt in to remote access |
|---|---|---|
| Admin API and Console | 127.0.0.1:8080 | --admin-host or MIRAVO_ADMIN_HOST |
| Embedded MQTT broker | 127.0.0.1:1883 | --mqtt-host, MIRAVO_MQTT_HOST, or template protocols.mqtt.host |
| OPC UA | 127.0.0.1:4840 | --opcua-host, MIRAVO_OPCUA_HOST, or template protocols.opcua.host |
| Modbus TCP | 127.0.0.1:1502 | --modbus-host, MIRAVO_MODBUS_HOST, or template protocols.modbus.host |
Set a host to 0.0.0.0 to listen on every interface, or to a specific interface address.
What the endpoints do not protect
- OPC UA accepts anonymous sessions. Its endpoints use a self-signed certificate, so signing and encryption do not restrict who can connect.
- Modbus TCP has no authentication. Any client that reaches the port can read and write.
- The embedded MQTT broker has no authentication or TLS. Any client can subscribe and publish.
- Members with
readwriteaccess accept writes over Modbus and OPC UA. MQTT is publish-only. A remote client can change simulated setpoints and states. - The admin API uses Basic Auth. The default password is
admin. SetMIRAVO_ADMIN_PASSWORDbefore binding it beyond loopback.
Docker
The image binds the admin API and all protocol listeners to 0.0.0.0 inside the container, so published ports work. Control exposure on the host side with the port mapping:
ports:
- "127.0.0.1:1883:1883"
- "127.0.0.1:8080:8080"A bare -p 1883:1883 publishes on every host interface. Use the 127.0.0.1: prefix unless you want LAN access.
Secrets
No command takes a secret as a flag value, because flag values leak into shell history and process listings.
- Litmus Edge API token: set
LITMUS_EDGE_API_TOKENforle applyandle cleanup, or save it in a target.le target addandle target updateread it from stdin with--api-token-stdin, andle target addasks through a hidden prompt on a terminal when the flag is omitted. - External MQTT broker password: set
MIRAVO_MQTT_PASSWORD.starthas no password flag. The username and password are never written to the saved state file; setMIRAVO_MQTT_USERNAMEtoo. If it is missing at the next start, restore refuses to enable the MQTT adapter instead of connecting without it, and startup leaves MQTT off unless you pass an explicit--mqtt-*flag. - Saved targets, including their tokens, live in
~/.miravo/integrations/targets.json.le target inspectmasks the token unless you pass--show-token.
printf %s "$LE_TOKEN" | miravo le target add --label demo --hostname 10.0.0.20 --source-hostname 172.17.0.1 --api-token-stdinChecklist
- Keep the default loopback binds unless another machine must connect.
- Place exposed instances on an isolated network or behind a firewall that limits source addresses.
- Change
MIRAVO_ADMIN_PASSWORDwhen the admin API is reachable by others. - Treat writable members as open to every client on that network.
- Pass secrets through environment variables or stdin, never as flag values.
Outbound traffic
Miravo has no telemetry. The CLI makes one optional request: an update check against the GitHub Releases API.
- Interactive terminal runs only. Skipped when stdout or stderr is not a TTY, when
CIis set, with--quiet, with JSON output, and forcompletion. - At most once every 24 hours. The result is cached in
~/.miravo/state/update-check.json. - Sends an HTTPS request to
api.github.comwith amiravo/<version>user agent. It sends no other data. - Disable with
MIRAVO_NO_UPDATE_CHECK=1. The Docker image sets it by default.
Was this page useful?
Last updated on
Miravo