Deployment Topology
Jope.SMB runs across two hosts: Plant IPC (Console + Historian) on Windows, and a dedicated Inference Host on the plant LAN running the Python Inference Server. This page covers prerequisites, installer, process management, network config, backup, and upgrade paths for both hosts.
Target Environment
Plant IPC (Console + Historian)
| Item | Requirement |
|---|---|
| OS | Windows 10 21H2+ or Windows 11 21H2+ |
| CPU | 4+ cores @ 2.5 GHz (6+ cores recommended) |
| RAM | 16 GB |
| Disk | 500 GB SSD (historian 7-year retention: ~100-200 GB / year) |
| Network | Isolated plant VLAN; no direct internet access |
Inference Host (dedicated, default)
| Item | Requirement |
|---|---|
| OS | Linux (recommended — Ubuntu 22.04 LTS / Rocky 9), Windows Server 2022, or container host (Docker / Podman) |
| CPU | 8+ cores @ 3.0 GHz |
| RAM | 32 GB (64 GB if models > 500 MB or GPU buffering) |
| GPU (optional) | NVIDIA with CUDA 12+ if GPU-accelerated inference is used |
| Disk | 200 GB SSD |
| Network | Plant VLAN with TCP to Plant IPC on ports 5555, 5556 |
Runtime Prerequisites
Plant IPC (Windows)
| Component | Version | Purpose |
|---|---|---|
| .NET Desktop Runtime 8 | 8.0.x (latest LTS patch) | Runs Jope.SMB Console |
| TimescaleDB | 2.15+ (PostgreSQL 15+) | Historian |
| Visual C++ Redistributable | 2015-2022 | Native dependencies |
Inference Host
| Component | Version | Purpose |
|---|---|---|
| Python | 3.11.x | Runs Inference Server |
| Process manager | systemd (Linux, recommended) or Docker / Podman | Run Inference as daemon with auto-restart |
| CUDA Toolkit (optional) | 12.x | GPU-accelerated inference |
Installation Layout
Plant IPC (Windows)
C:\Jope\
├── SMB\ ← Console binaries
│ ├── Jope.SMB.WPF.exe
│ ├── config\
│ │ ├── app.json ← endpoints, theme, language
│ │ └── devices.json ← device COM port assignments
│ └── logs\
└── Historian\ ← TimescaleDB data dir (may be on D: for capacity)
└── data\
Inference Host (Linux · recommended)
/opt/jope-inference/
├── venv/ ← isolated Python environment
├── main.py
├── models/ ← .joblib files + metadata
├── config/
│ └── server.toml ← endpoint binding, model paths
└── logs/
/etc/systemd/system/
└── jope-inference.service ← systemd unit
Inference Host (Docker · alternative)
jope-inference/
├── Dockerfile
├── docker-compose.yml ← single-service compose
├── models/ ← mounted as volume
└── config/ ← mounted as volume
Process Management
Plant IPC · Service Registration
| Service Name | Process | Start Mode | Depends On |
|---|---|---|---|
postgresql-x64-15 | PostgreSQL + TimescaleDB (Windows Service) | Auto | — |
The Console is NOT a service — it runs interactively under the logged-in operator session. This is intentional: electronic signature dialogs must be visible to the user, and a session-tied UI is a compliance expectation.
Inference Host · daemon
- Linux (recommended):
systemctl enable --now jope-inference.service. Unit file usesRestart=always,User=jope, and setsWorkingDirectory=/opt/jope-inference. - Docker:
docker compose up -d— restart policyunless-stopped.
The daemon exposes ZMQ on :5555 and HTTP on :5556 to the plant LAN.
Network Configuration
| Endpoint | Port | Host | Notes |
|---|---|---|---|
| Inference ZMQ | 5555 | Inference Host | TCP bound to plant LAN; configurable in Console app.json |
| Inference REST | 5556 | Inference Host | HTTP/1.1; JSON |
| Historian | 5432 | Plant IPC (loopback preferred) | PostgreSQL default |
| Raman gateway | 502 | Plant LAN | Modbus TCP |
| Operator Console | — | Plant IPC | no listening port; outbound only |
Firewall Rules
Inference Host (Linux iptables / firewalld, or Windows Firewall):
- Allow inbound
5555+5556only from Plant IPC's address - Block all other inbound from plant VLAN
- Block all outbound to internet (plant is air-gapped)
Plant IPC (Windows Firewall):
- Allow outbound to Inference Host ports
5555+5556 - Block all inbound from plant VLAN
- Block all outbound to internet
Deployment Layout
Two hosts on the plant LAN:
Plant IPC (Windows) Inference Host (Linux recommended)
├── Jope.SMB Console ├── Inference Server (daemon)
└── TimescaleDB (service) └── Model Registry (.joblib files)
│ ▲
└────── plant LAN ─────────────┘
ZMQ :5555 + REST :5556
- Plant IPC — Windows; runs Console interactively + Historian as a service. Owns hardware I/O.
- Inference Host — Linux + systemd (recommended) or Docker / Podman. Runs Python Inference as a long-lived daemon. Own CPU / RAM / optional GPU budget.
Why the separation:
- Plant IPC can focus on real-time hardware polling + operator UI + compliance writes without Python GIL / training CPU spikes interfering
- Inference Host can be sized independently (more RAM for larger models, optional GPU for parallel inference)
- Training jobs (which can saturate CPU for minutes) don't impact Console responsiveness
- Python ML tooling runs natively on Linux; no need to force Windows compatibility for libraries
- Easier to scale / replace the Inference Host over time as models evolve
Latency over the plant LAN is ~1-2 ms, well within the predict p95 ≤ 20 ms target.
Backup
| Scope | Frequency | Target | Retention | Encryption |
|---|---|---|---|---|
| Historian (full) | Daily 02:00 | NAS \\nas01\backup\jope-smb\ | 90 days rolling + monthly archive (1 year) | AES-256 at rest |
| Historian (WAL) | Continuous | Same | With full backups | AES-256 |
Config (C:\Jope\SMB\config\) | Weekly | Same | 90 days | AES-256 |
Models (C:\Jope\Inference\models\) | On change | Same | Unlimited (small) | Signed packages |
Restore requires dual approval per Compliance Mapping · 4-Eyes.
Upgrade Path
Every component has a versioned upgrade script:
- Announce maintenance window — Console shows banner 24 h in advance
- Gracefully stop batch — operator finishes current run; no forced interrupt
- Take full backup + WAL snapshot
- Stop services (Inference, then Console — leave Historian running for queries)
- Run upgrade installer
- Apply DB migrations — TimescaleDB schema updates are versioned;
downscripts exist - Verify — smoke tests in
Jope.SMB.Core.Tests; device connectivity checks - Restart services + Console
- Audit event:
SystemUpgradedwith{old_version, new_version, operator, timestamp}
Rollback: restore from the pre-upgrade backup; dual approval required.
Monitoring
- Windows Event Log: every service writes structured JSON lines
- Operator Console · Status Bar: Inference heartbeat, Historian connectivity, free disk
- Historian self-query:
SELECT COUNT(*) FROM audit_events WHERE ts > now() - interval '24 h'— must grow monotonically - Optional — plant SCADA can poll
/healthon Inference Server for plant-wide dashboards
Installer Responsibility Split
| Item | Owner |
|---|---|
| Installer packaging (Plant IPC MSI + Inference Host image / systemd unit) | Jope engineering |
| Plant OS provisioning | Plant IT |
| User account creation (dev + service) | Plant IT |
| First-boot validation | Jope engineering + Plant QA |
| Ongoing patching (Windows Update) | Plant IT, announced maintenance windows |
| Jope.SMB version upgrades | Jope engineering, dual approval by Plant QA |