# 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 ```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 4–5 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. |