wrps-demo-kit/02-environment
Clio Liu 5be48b6bbb fix: CI Server on cicore1 is R1.05, not R1.03
Corrected in README.md, CLAUDE.md, 02-environment/README.md and
03-plc/VERSIONS.md.

The @VERSION 1.03.00 header inside the .qli files is the quickload FILE
FORMAT version, not the CI Server release. Left alone.

This also sharpens a caveat that was previously stated wrongly. The
EQP-E-DUP_ITEM rejection - an item import fails if two items share an
IO_ADDRESS - was observed on 2026-08-14 on the DEVELOPMENT machine, which
ran R1.03. Production runs R1.05, where it has never been tested. The
design still works around it by publishing level and speed in % only, and
that workaround costs nothing; but anyone wanting a second unit for a
measurement should try it on R1.05 before assuming they need a second PLC
register to carry it.
2026-09-02 17:34:58 +10:00
..
MIGRATION.md feat(env): hosts, access, ports and the PLC container 2026-09-02 17:24:09 +10:00
openplc-compose.yml feat(env): hosts, access, ports and the PLC container 2026-09-02 17:24:09 +10:00
openplc-container.md feat(env): hosts, access, ports and the PLC container 2026-09-02 17:24:09 +10:00
README.md fix: CI Server on cicore1 is R1.05, not R1.03 2026-09-02 17:34:58 +10:00
secrets.local.md.template feat(env): hosts, access, ports and the PLC container 2026-09-02 17:24:09 +10:00
YAU_Linux_Host_Onboarding.md feat(env): hosts, access, ports and the PLC container 2026-09-02 17:24:09 +10:00

02-environment — where this runs and how to reach it

Two machines. One runs the PLC, the other runs the SCADA. Both sit on the 10.0.0.0/24 PoC network.

Role Hostname LAN Notes
SCADA — Yokogawa CI Server R1.05 yau-poc-cicore1 10.0.0.21 Windows. Polls the PLC over Modbus TCP.
PLC — OpenPLC Runtime v4 in Docker yau-sls-poc-lin001 10.0.0.17 Ubuntu 22.04 on Azure, public IP 20.211.144.151. Shared, live host — see below.

Also on the network: an Active Directory domain controller at 10.0.0.5 (yau.poc), and roughly a dozen other Windows hosts.

⚠️ The Linux host is shared, live, and not ours

yau-sls-poc-lin001 is the YAU Innovation Team's general-purpose Docker host and VPN gateway. It runs ~28 containers for several unrelated projects — Grafana, InfluxDB, Node-RED, Forgejo, Authelia, Portainer and more — behind a Caddy reverse proxy with AD + Duo MFA. It serves customer-facing demos.

openplc-runtime is one container among many, and this project owns only that one. Rules that follow from it:

  • Never restart Caddy or Authelia — they interrupt every other service.
  • Never put growing data on the root disk (/ is 62 GB). Use /datadisk.
  • Never publish a container port on 0.0.0.0. The host has a public IP.
  • Everyone shares the azureuser login, so there is no per-person audit trail — announce disruptive work.

YAU_Linux_Host_Onboarding.md is the host's own brief, written by its owner (Daniel Watson) and current as of 2026-09-01. Read it before changing anything on that machine. Its §10 is a list of rules, each of which exists because breaking it already caused an outage.

Access

The Linux host — SSH

ssh -i ~/.ssh/yau-sls-poc-lin001_key.pem azureuser@20.211.144.151

An SSH config alias makes this shorter. The working copy used during the audit:

Host lin001
    HostName 20.211.144.151
    User azureuser
    IdentityFile ~/.ssh/yau-sls-poc-lin001_key.pem
    IdentitiesOnly yes

10.0.0.17 is only routable from inside the VNet or over the WireGuard VPN — from outside, use the public IP.

The CI Server host

No remote access route is recorded. It was reached interactively during development. If you need one, ask.

What you need from the host owner

Item What it is
yau-sls-poc-lin001_key.pem SSH private key — chmod 600 it or SSH refuses to use it
AD account in HTTPS_UserAccess required for every web UI on the host
Duo enrolment second factor for those UIs
A WireGuard peer optional, but it is what makes 10.0.0.x reachable directly

Ports

Service Host Port Bound to Notes
OpenPLC Modbus TCP server 10.0.0.17 502 10.0.0.17 only The PLC is the Modbus slave. CI Server polls it.
OpenPLC REST API (HTTPS) 10.0.0.17 8443 10.0.0.17 only Control channel — upload, start/stop. JWT auth. No browser UI.
CI Server Modbus client 10.0.0.21 outbound

Important

The bind address is the security control. Modbus has no authentication or encryption, and 8443 is the control channel with only JWT in front of it. The host has a public IP, so binding these to 10.0.0.17 rather than 0.0.0.0 is the only thing keeping them off the internet. Never widen it.

There is no host firewall. ufw is inactive on yau-sls-poc-lin001; inbound filtering is entirely the Azure Network Security Group. Opening a port means editing the NSG in the Azure portal, not the host.

Secrets

Live in secrets.local.md, which is git-ignored and must never be committed. secrets.local.md.template shows the shape — copy it, fill it in, keep it local.

It holds the OpenPLC runtime admin password and CI Server credentials. The SSH key is a file, not a line in that document, and is likewise never committed.

Host-level credentials (service admin passwords, API tokens for Grafana, Influx, Authelia and so on) are not this project's — they live in the host owner's Linux Machine Config.txt. Ask; do not copy them here.

Files here

File What
YAU_Linux_Host_Onboarding.md The Linux host's own brief — the stack, the auth model, the deployment pattern, and the rules. Written and owned by the host owner, not by this project. Current 2026-09-01.
openplc-container.md How the PLC container is configured, as read from the running host
openplc-compose.yml Verbatim copy of the live ~/openplc-compose.yml
MIGRATION.md Moving the PLC container to another host — the as-built record of the 2026-08-19 move, kept as a repeatable runbook
secrets.local.md.template The shape of the git-ignored secrets file

Not kept here: the host's full operations manual (Host_Documentation.md, ~400 lines covering ChirpStack, Forgejo, EQP licensing, the Telegraf fleet and the rest of the platform). None of it is WRPS, it is owned elsewhere, and a stale copy in this repo would be worse than a pointer. Ask the host owner for the current version.

Checking the environment is healthy

ssh lin001 "docker ps --filter name=openplc-runtime"
ssh lin001 "docker logs --tail 30 openplc-runtime"
ssh lin001 "df -h / /datadisk"          # both disks - / is only 62 GB

From a machine that can route to 10.0.0.17 (VNet or VPN):

python ../05-tests/verify_modbus.py --host 10.0.0.17 --port 502 --unit 1

From anywhere else, poll from a throwaway container on the host's own network:

ssh lin001 "docker run --rm --network openplc-net python:3.12-alpine \
  sh -c 'pip install -q pymodbus && python -c \"...\"'"

Known issues

Issue Detail
PLC scan overruns The 100 ms task overran ~100 times between 2026-08-19 and 2026-08-28 — roughly one per 45 days. Logged as a warning; the task runs at a reduced rate and the demo continues. Not investigated; the host is shared, so contention is a candidate.
Migration artefacts left on the host ~/openplc-migration/ still holds openplc-image.tar.gz (354 MB) and openplc-vol.tar.gz. MIGRATION.md Part G says to delete them, and the volume tarball contains the runtime's JWT secret.
The runtime image cannot be re-pulled It was produced by docker commit and exists in no registry. Deleting it loses the compiled PLC program. See 03-plc/as-built/.
No deployment toolchain The OpenPLC Editor lived only on the retired dev-ubuntu host. See 03-plc/DEPLOY.md §0.