VL3 Edge Setup
The Phoenix Contact VL3 UPC 2440 EDGE is the primary hardware host for the Consystence edge runtime. A single DIN-rail device runs both the deterministic control runtime and the Consystence intelligence layer, sitting between the field and the site server. This page covers how to provision one: 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 the PLCnext acts as the field gateway, see the PLCnext border gateway.
The two-process model
Section titled “The two-process model”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 unit ships as consystence-edge.service and runs the published Consystence.Edge binary 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=ASPNETCORE_URLS=http://+:8080Environment=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.ASPNETCORE_URLS=http://+:8080— the local diagnostics API binds port 8080. The systemd unit sets the binding through this environment variable; the shippedappsettings.jsonbinds the same port through itsKestrel:Endpointssection (which is how a containerised deploy binds it, withoutASPNETCORE_URLS). See the caution below on securing that management surface.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-org" }, "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. (Licensing identity is provisioned by the account, not derived from hardware — see licensing.) |
Edge:Site, Edge:TenantCode | The site code and org slug the edge reports itself under. |
Upstream:ServerUrl | Where the edge phones home — set this explicitly to the site server’s hostname or address. |
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 | Attempts HTTP/3 (QUIC) upstream. The site server currently serves HTTP/1.1 and HTTP/2 only, so set this to false (as the workshop config does) — gRPC then runs over HTTP/2 TLS. |
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 wherever ASPNETCORE_URLS points (port 8080 in the unit above); there is no localApi config section.
Registration flow
Section titled “Registration flow”- The VL3 powers on and gets an IP (DHCP in the workshop).
consystence-edgereads its local configuration, takes its identity fromEdge:Id, and registers with the site server atUpstream:ServerUrl.- For a single-site org — the normal site-server topology — the server registers the edge into that site on first contact and returns
Approved; the device then appears in the site’s edge directory. - For a multi-site org where the edge is not yet known, the server returns
Pendingand the edge retries until it is admitted to a site. - Nothing is pushed after registration — the edge runs on the configuration it already holds locally.
The site server runs the same codebase in ServerMode.Site; see the server model for how sites sit under an org.
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 is implemented behind the edge’s IPlcDriver abstraction. The relevant drivers:
| Driver | Use |
|---|---|
plcnext-grpc | Primary. Reads/writes PLCnext GDS/PORT variables over gRPC-over-UDS. |
ethernet-ip | Direct EtherNet/IP CIP from the edge — interop path for third-party/legacy controllers; on the VL3 the PLCnext owns the field link. |
modbus-tcp | Direct Modbus TCP (port 502) from the edge — interop path for Modbus devices. |
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”The VL3 is a dual-homed IT/OT boundary device. The runtime expects two interfaces — eth0 on the IT side (upstream to the site server) and eth1 on the OT side (the field network) — with nftables enforcing the segmentation. Get this right before going live: the OT side should reach only the PLCnext and field devices, and the IT side only the site server. See network security for the firewall ruleset and the full topology.
Orin as an alternative host
Section titled “Orin as an alternative host”The VL3 is the primary hardware, but the Nvidia Orin is a supported, GPU-capable alternative that runs the same .NET 10 edge runtime — the same Consystence.Edge binary, the same systemd unit, the same appsettings.json configuration model. The Orin is not a standalone ML appliance; it is simply an edge host with a GPU. See Orin setup for the differences.
Next steps
Section titled “Next steps”- PLCnext border gateway — how the PLCnext bridges edge and field.
- Network security — IT/OT segmentation and the
nftablesrules. - PLC communication — the
IPlcDriverlayer in depth. - Orin setup — the GPU-capable alternative host.
- Edge deployment — fleet rollout and upgrade workflow.