VL3 Edge Setup
The Phoenix Contact VL3 UPC 2440 EDGE is a target platform for the Consystence edge runtime. On it, a single DIN-rail device runs both the deterministic control runtime and the Consystence edge runtime, sitting between the field and the site server. This page describes that target installation: the two-process model, the systemd unit that runs the edge runtime, the local configuration and registration flow, and the local gRPC link to the PLCnext controller.
For the broader edge picture, start at the edge overview. For how a PLCnext acts as the field gateway in the border-gateway topology, see the PLCnext border gateway.
The two-process model
Section titled “The two-process model”In the target installation, the VL3 hosts two cooperating processes, with a clean separation of concerns:
| Process | Role | Runtime |
|---|---|---|
| vPLCnext (Virtual PLCnext Control) | Deterministic real-time control — state machines, interlocks, alarms, IO mapping. Speaks EtherNet/IP CIP to the field and exposes tags over a local gRPC server. | Phoenix Contact PLCnext runtime |
| consystence-edge | Platform functions — tag collection, store-and-forward, store buffering, upstream streaming, local diagnostics. | .NET 10, single-silo Orleans |
The control logic stays in the PLCnext runtime where it belongs; consystence-edge never issues control commands directly. It reads and writes tags through the PLCnext over a local socket, buffers them, and streams them upstream.
flowchart TB
subgraph VL3["VL3 UPC 2440 EDGE"]
EDGE["consystence-edge<br/>.NET 10 / Orleans<br/>store-and-forward (SQLite)"]
PLC["vPLCnext<br/>Virtual PLCnext Control<br/>CSY control program (C# eCLR)"]
EDGE -->|"gRPC over UDS<br/>/run/plcnext/grpc.sock"| PLC
end
EDGE -->|"gRPC (HTTP/2 TLS)<br/>store-and-forward"| SS["Site server"]
PLC -->|"EtherNet/IP CIP<br/>TCP 44818"| FIELD["Field IO / ControlLogix rack"]
The systemd unit
Section titled “The systemd unit”The edge runtime is not yet publicly released; Consystence provides it through beta engagements. On a systemd host it runs as consystence-edge.service, under a dedicated unprivileged consystence user with filesystem hardening:
[Unit]Description=Consystence Edge RuntimeAfter=network-online.targetWants=network-online.target
[Service]Type=notifyExecStart=/opt/consystence/edge/Consystence.EdgeWorkingDirectory=/opt/consystence/edgeEnvironment=DOTNET_ENVIRONMENT=ProductionRestart=alwaysRestartSec=10TimeoutStartSec=30TimeoutStopSec=30User=consystenceGroup=consystence
# Security hardeningNoNewPrivileges=trueProtectSystem=strictProtectHome=trueReadWritePaths=/var/lib/consystence /var/log/consystenceStateDirectory=consystencePrivateTmp=true
# Resource limitsLimitNOFILE=65536MemoryMax=512M
[Install]WantedBy=multi-user.targetPoints worth understanding before you deploy:
StateDirectory=consystence— systemd creates and owns/var/lib/consystenceand, critically, keeps it across a unit replacement or redeploy. This is where the write-once install identity and the offline-licence state persist. Do not delete it between upgrades. Offline licensing degrades gracefully and never gates control writes — see licensing.ProtectSystem=strict+ReadWritePaths— the root filesystem is read-only to the service; only/var/lib/consystence(state, store-and-forward buffer) and/var/log/consystence(logs) are writable.- Local diagnostics API — listens on
127.0.0.1:8080by default, so only the device itself can reach it (use it over SSH). Its address and port come only from theLocalApisection (LocalApi:Address,LocalApi:Port).ASPNETCORE_URLSdoes not move it, and the edge refuses to start if its configuration contains aKestrelendpoints section. Restart=always/RestartSec=10— the edge self-heals after crashes or power events; store-and-forward replays any buffered data on reconnect.
Install and enable:
sudo systemctl daemon-reloadsudo systemctl enable --now consystence-edge.servicesudo systemctl status consystence-edge.servicejournalctl -u consystence-edge.service -fBootstrap and registration
Section titled “Bootstrap and registration”The target design is a minimal bootstrap: an unconfigured edge carries only enough configuration to find and register with the site server, and everything else — the controller/module/channel/tag model, the PLC driver wiring, alarm definitions — is pushed from the server. Server-side push is a target capability, not yet shipping. Today the edge builds its entire runtime model — PLC drivers, poll groups, device instances, command mappings — from its local appsettings.json, with environment-variable overrides (for example Upstream__ServerUrl to point the edge at its site server).
The keys the runtime actually reads, in appsettings.json form:
{ "Edge": { "Id": "edge-01", "Site": "your-site", "TenantCode": "your-tenant" }, "Upstream": { "ServerUrl": "https://site-server.example.internal:5001", "BufferPath": "/var/lib/consystence/buffer.db", "BufferMaxBytes": 536870912, "ForceHttp3": false }, "Plcs": [ { "PlcId": "plcnext-001", "Name": "PLCnext VL3 (local)", "Driver": "plcnext-grpc", "Address": "localhost" } ]}| Key | Meaning |
|---|---|
Edge:Id | The only required setting — the edge’s identity. Bootstrap fails (Edge:Id is required in configuration) if it is missing, and the value is what the edge sends the server as its hardware ID at registration. The target design is an activation flow that enrols the device by its write-once install identity, with Edge:Id remaining a display label — not yet shipped. (The licensing identity is that separate write-once install ID, which the edge mints at first boot; the account-signed licence is bound to it. See licensing.) |
Edge:Site, Edge:TenantCode | The site code and tenant slug the edge reports itself under. |
Upstream:ServerUrl | The site server’s edge listener, the one port on which the site server serves edges (for example https://site-server.example.internal:5001). The listener is off until EdgeListener:Port is set on the site server; set it there with HTTPS configured (see edge listener), and allow only your edge hosts to reach that port. |
Upstream:BufferPath | SQLite store-and-forward buffer, under the writable /var/lib/consystence state directory. Buffers tag data when the upstream link drops and replays on reconnect. |
Upstream:BufferMaxBytes | Disk cap on the store-and-forward buffer (default 536870912 — 512 MiB). On overflow the oldest data is dropped first; drops are counted and reported on the heartbeat, and edge health degrades while overflowing. Size it for the longest outage the site must ride out. |
Upstream:ForceHttp3 | Opt-in HTTP/3 (QUIC) upstream; default false. The site server does not serve HTTP/3, so leave it off; gRPC then runs over HTTP/2 (TLS when Upstream:ServerUrl is https). |
Plcs, PollGroups, Instances, CommandMappings | The full PLC driver wiring, poll schedule, device instances, and command tag writes — all local today. See PLC communication. |
Edge:ConfigVersion | The command-catalogue version this edge’s local config corresponds to. Reported to the site server on the command channel; commands are rejected fail-closed if it does not match the version the site activated for this edge. |
The local diagnostics API binds only from the LocalApi section (default 127.0.0.1:8080). To reach it from a management network, set LocalApi:Address to that interface’s IP address and LocalApi:TokenFile to a file holding an access token of at least 32 characters. Requests from other hosts then need Authorization: Bearer <token> on the /api/* routes.
Registration flow
Section titled “Registration flow”- The VL3 powers on and joins its IT-side network.
consystence-edgereads its local configuration, takes its identity fromEdge:Id, and registers with the site server atUpstream:ServerUrl, presenting that id.- The site server answers
APPROVED,PENDINGorREJECTED. Until the answer isAPPROVED, the edge retries, every five seconds by default; once approved, the edge appears in the site’s edge directory. - Nothing is pushed after registration — the edge runs on the configuration it already holds locally.
One codebase is published as two server artifacts, Site and Cloud; the site server is the Site artifact. See the server model for how sites sit within a tenant.
The gRPC-over-UDS link to PLCnext
Section titled “The gRPC-over-UDS link to PLCnext”consystence-edge reads and writes field data through the co-located PLCnext, not by talking to the field directly. The link is gRPC over a Unix Domain Socket at /run/plcnext/grpc.sock — the PLCnext gRPC server (RSC/Data Access services) also listens on TCP 41100, but the local UDS path is preferred for lowest latency and no network stack.
This link is one driver in the edge’s driver layer. The relevant drivers:
| Driver | Use |
|---|---|
plcnext-grpc | On the VL3, the link to the co-located PLCnext. Reads/writes PLCnext GDS/PORT variables over gRPC-over-UDS (over TCP where the PLCnext is remote or containerised). |
ethernet-ip | Direct EtherNet/IP CIP from the edge to a Rockwell ControlLogix. On the VL3 in the border-gateway topology, the PLCnext owns the field link instead. |
modbus-tcp | Roadmap. Modbus TCP as a runtime acquisition driver is not yet available on the edge. |
stub | In-memory driver for testing and simulation. |
The PLCnext, in turn, speaks EtherNet/IP CIP (TCP 44818) to the ControlLogix rack or field IO. So the data path is: field → PLCnext (CIP) → consystence-edge (gRPC/UDS) → site server (gRPC over HTTP/2 TLS). The edge never speaks CIP itself in this topology.
PLC driver configuration lives in the edge’s local appsettings.json — the Plcs, PollGroups, and Instances sections shown above — so today you provision the link by editing the edge’s own config. Server-pushed driver config after registration is the target design, not current behaviour.
Network placement
Section titled “Network placement”In the target installation the VL3 sits at the IT/OT boundary, with two interfaces: eth0 on the IT side (upstream to the site server) and eth1 on the OT side (the field network). Segment the two before going live, so that the OT side reaches the PLCnext and field devices and the IT side reaches the site server. Network security sets out a reference firewall policy for the edge host.
Nvidia Orin in our workshop
Section titled “Nvidia Orin in our workshop”The same .NET 10 edge runtime runs on an Nvidia Jetson Orin in our workshop today, with the same appsettings.json configuration model. There, one edge reads a physical ControlLogix directly over EtherNet/IP and a virtual PLCnext over gRPC on TCP. The Orin is not a standalone ML appliance; it is an edge host with a GPU. See Orin setup for what differs from the VL3 installation.
Next steps
Section titled “Next steps”- PLCnext border gateway — how a PLCnext bridges edge and field in the border-gateway topology.
- Network security — the reference IT/OT firewall policy for the edge host.
- PLC communication — the driver layer in depth.
- Orin setup — the edge runtime on an Nvidia Jetson Orin.
- Edge deployment — configuring the edge runtime: registration and controller drivers.