IronOps is live at ironops.us, with the app itself running at app.ironops.us. It is a hybrid edge-cloud MES for small and mid-sized manufacturers, the kind of shop that does not need a giant SCADA project or a black-box SaaS tool. It needs a practical, trustworthy bridge between the machine and the decision.
The edge gateways are Raspberry Pi CM4 boards on industrial carriers, built from a reproducible golden image with pi-gen. The OS, the agent, and the OTA public key are baked in before a device ever ships. I treat them as cattle, not pets. A device is claimed with a short-lived token from an on-device console, and once claimed it gets its own scoped MQTT credentials. Nothing is shared across devices, and nothing is hand-configured after the fact.
Support does not run over a remote shell, because there is no remote-login surface at all. Diagnostics run as typed, expiring verbs through a command inbox. If that is not enough, there is a physical support dongle, and after that, a device swap. I would rather ship a slightly less convenient support story than leave an open door into a customer's plant network.
Connecting a machine goes through a Connect-a-Machine wizard. A protocol schema registry drives the forms, so Modbus TCP and OPC UA get the fields they actually need, and there is a test-connection step before anything commits. Machine templates and CSV tag import handle the repetitive part of onboarding a line.
The data model itself is being rebuilt in two stages with a translation layer between them: physical acquisition tags first, then logical signals with a defined purpose, attachable at any level of the plant hierarchy. That separation is the part I keep coming back to. Raw tags are what the machine gives you. Signals are what the plant actually means.
Under the hood it is a Python edge agent, a FastAPI backend, TimescaleDB on PostgreSQL, a React frontend, MQTT through Mosquitto with dynamic security, all Dockerized and reachable through a Cloudflare Tunnel.
Build log