wrps-demo-kit/02-environment/README.md
Clio Liu 2b8f88d01f feat(env): hosts, access, ports and the PLC container
02-environment merges the old 02-env and 03-containers - both answered the
same question, 'where does this run and how do I reach it', and were split
for no reason.

  README.md              the two hosts, access, ports, secrets, health
                         checks, known issues
  YAU_Linux_Host_Onboarding.md  the Linux host's own brief, copied with a
                         provenance banner: owned by the host owner, not
                         maintained here, and its 'save this as CLAUDE.md'
                         instruction does not apply in this repo
  openplc-container.md   the container as read from the running host
  openplc-compose.yml    verbatim copy of the live file
  MIGRATION.md           moving the container - as-built plus runbook
  secrets.local.md.template  the shape of the git-ignored secrets file

The README leads with the fact that shapes every decision on that machine:
yau-sls-poc-lin001 is a SHARED, LIVE host running ~28 containers for
several projects behind Caddy and Authelia, and this project owns exactly
one of them. Never restart Caddy or Authelia, never publish on 0.0.0.0,
never put growing data on the 62 GB root disk.

Records four known issues rather than leaving them in anyone's head: the
100 ms scan overruns, the 354 MB migration tarballs still sitting on the
host with the JWT secret inside one of them, the runtime image existing in
no registry, and the missing Editor toolchain.

Not carried across: Host_Documentation.md. ~400 lines on ChirpStack,
Forgejo, EQP licensing and the Telegraf fleet - none of it WRPS, owned
elsewhere, and a stale copy here would be worse than a pointer.
2026-09-02 17:24:09 +10:00

6.5 KiB
Raw Blame History

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.03 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.