wrps-demo-kit/02-environment/README.md
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

144 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```bash
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
```bash
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):
```bash
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:
```bash
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. |