Settle the container count, and put openplc-runtime in the host brief

Counted on lin001: 28 running, none stopped. Seven are ours (ai-api,
ai-web, pg-ai, cube, cubestore, langfuse, lf-db), so 21 were already
there. Four documents gave four different numbers because they were
counting different things at different times.

BUILD-AI-CONTAINERS.md (21 pre-existing) and current-state.html (28
total) were already right and are untouched. README.md said 22 where it
meant 21. The host brief said 20 in three places while naming only 19,
and it is the one with a real gap behind it:

openplc-runtime appears NOWHERE in the 351-line host brief. Not in the
stack table, not in the data flow, not in the rules - while CLAUDE.md
calls it live control that must never be restarted, and the build spec
names it as the reason port 502 is the one exception to no-published-
ports on this host. The document a new engineer reads first to learn what
runs here omitted the only container doing live control. wireguard was
missing from the same table, though mentioned in three other sections.

Both are now in §3. §6's published-ports list was missing 502/tcp and
8443/tcp for the same reason; verified against docker ps, they bind to
10.0.0.17 rather than 0.0.0.0, and that binding is what keeps
unauthenticated Modbus off the internet, so it is recorded as a control
and not as a detail. §12's "confirm 20 containers up" no longer names a
number - that is how it went stale.

The brief's stamp moves to 2026-09-01 with a note saying what was amended
and what was left alone, so Dan's authorship of the rest stays clear.

Separately, README.md listed ai-docs-worker among the containers as
though it were running. It was never deployed: Phase 9 shipped with the
document screens served by ai-api, and the worker sits behind a
--profile worker flag. compose and current-state.html both say so
already; the README table now does too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-09-01 16:42:29 +10:00
parent c367429822
commit 0b8ff4b0c3
2 changed files with 28 additions and 7 deletions

View file

@ -161,7 +161,7 @@ ai-api ──► classifier ──► one branch per class ──► contract va
```
Everything runs on `yau-sls-poc-lin001` (`10.0.0.17`), a **shared, live** Docker
host that already runs 22 containers including `openplc-runtime` — the PLC for
host that already runs 21 containers including `openplc-runtime` — the PLC for
this demo. See [`YAU_Linux_Host_Onboarding.md`](spec/YAU_Linux_Host_Onboarding.md).
**There is no replication job and no mirror table.** `imh` is already an
@ -177,9 +177,15 @@ equipment/tag reference data.
| `ai-api` | Python 3.12 + FastAPI | `ai-internal` + `proxy` | `api.yokogawa.tech` |
| `ai-web` | Vite build → `nginx:alpine` | `proxy` | `ai.yokogawa.tech` |
| `ai-ingest` | Python 3.12, on demand | `ai-internal` | none |
| `ai-docs-worker` | same image, long-running (Phase 9) | `ai-internal` | none |
| `ai-docs-worker` | **not deployed**`--profile worker`, see below | `ai-internal` | none |
| `langfuse` + `lf-db` | official images | `ai-internal` + `proxy` | `lf.yokogawa.tech` |
**Seven of those are running.** `ai-ingest` is run on demand with `run --rm` and is not
meant to be up. `ai-docs-worker` was **never deployed**: Phase 9 shipped with the
document screens served by `ai-api` instead, and the worker sits behind a
`--profile worker` flag — see the note at `compose/ai-compose.yml:216`. Counted on the
host 2026-09-01: 28 containers, 21 of them pre-existing.
---
## Working on it

View file

@ -1,9 +1,15 @@
# YAU PoC Linux Host — Environment Brief & AI Agent Guide
> **Host:** `yau-sls-poc-lin001` · Azure Ubuntu 22.04 LTS · Public IP `20.211.144.151` · LAN `10.0.0.17`
> **Owner:** Daniel Watson (daniel.watson@yokogawa.com) · **Brief current as of:** 2026-08-12
> **Owner:** Daniel Watson (daniel.watson@yokogawa.com) · **Brief current as of:** 2026-09-01
> **Audience:** an engineer joining this environment, and the AI coding agent working alongside her.
> **Amended 2026-09-01** by the WRPS Plant Assistant project, against a `docker ps` on the
> host. Dan's brief of 2026-08-12 is unchanged apart from the container inventory, which had
> gone stale: §3 was counting 20 and naming 19, and omitted `openplc-runtime` and `wireguard`
> entirely. `openplc-runtime` is live control and appeared nowhere in this file. §3, §6
> (published ports) and §12 are corrected; nothing else was touched.
**This file is safe to share.** It contains no passwords, tokens, or keys — only their *locations*.
Everything you need to actually authenticate comes from Dan over a secure channel (see §2).
@ -19,7 +25,7 @@ already caused one outage here.
A **secure, general-purpose Docker host and network gateway** for the YAU Innovation Team. Two roles:
1. **A multi-service platform.** Many containerised services for different sales/PoC engagements,
added and removed as needed. The current 20 containers are a snapshot, not a fixed design.
added and removed as needed. The container list in §3 is a snapshot, not a fixed design.
Publishing a new service under HTTPS with SSO is a ~5-minute, well-worn pattern (§7).
2. **A secure gateway** into the `10.0.0.0/24` PoC environment, which also holds Windows hosts
(a Domain Controller at `10.0.0.5`, a CI Server, ~13 machines total). Devices and remote users
@ -56,7 +62,10 @@ directly. Ask Dan to add one (§6).
## 3. The stack at a glance
20 containers, all `restart: unless-stopped`, all with log rotation (10 MB × 3).
**21 containers**, all `restart: unless-stopped`, all with log rotation (10 MB × 3).
`docker ps` shows **28** today: these 21, plus seven added by the WRPS Plant Assistant
project (`ai-api`, `ai-web`, `pg-ai`, `cube`, `cubestore`, `langfuse`, `lf-db`) — those
are described in that project's own repository, not here. Counted 2026-09-01.
| Service | URL | Auth | Notes |
|---------|-----|------|-------|
@ -74,6 +83,8 @@ directly. Ask Dan to add one (§6).
| **Telegraf** | — | — | Host + container metrics → Influx `telemetry` bucket (30-day retention) |
| **Watchtower** | — | — | Auto-updates a **safe subset only**, Sundays 04:00 AEST |
| **ChirpStack** ⚠️ | `chirpstack.yokogawa.tech` | MFA | LoRaWAN (AU915) — **future capability, running but NOT configured**. Safe to ignore or stop |
| **WireGuard** | — (host port 443/udp) | peer keys | The VPN into `10.0.0.0/24`. Adding peers: §6 |
| **OpenPLC Runtime** ⚠️⚠️ | — (host ports **502/tcp, 8443/tcp**, bound to `10.0.0.17`) | ⚠️ **none** | **LIVE CONTROL.** The soft PLC for the Waterloo Road Pump Station demo, polled over Modbus TCP by CI Server on `cicore1`. **Never restart, update or reconfigure it as a side effect of other work**, and never change the `10.0.0.17` binding to `0.0.0.0` — that binding is the only thing keeping unauthenticated Modbus off the internet. Not in Watchtower's update list, and must not be added |
Plus `chirpstack-postgres`/`-redis`/`-mqtt`/`-gateway-bridge` (all ChirpStack support) and
`authelia-portal` (nginx that brands the login page).
@ -166,7 +177,10 @@ Understand this before you deploy anything.
`docker compose -f ~/wg-compose.yml up -d --force-recreate` (existing peers are preserved), then
`docker exec wireguard /app/show-peer <name>` for the config/QR code.
- **Published host ports:** 80/443 tcp (Caddy), 443/udp (WireGuard), 1883/tcp (MQTT),
1700/udp (LoRaWAN packet forwarder).
1700/udp (LoRaWAN packet forwarder), and **502/tcp + 8443/tcp (OpenPLC Runtime)**
the last two bound to `10.0.0.17`, not `0.0.0.0`. That binding is a security control:
Modbus has no authentication or encryption, so the bind plus the NSG is all that keeps
it off the internet. Do not change it.
- **Firewall:** host `ufw` is **inactive** — inbound filtering is entirely the **Azure NSG**.
Opening a port means editing the NSG in the Azure portal, not the host.
- **Azure hairpin gotcha:** LAN hosts cannot reach the VM's *public* IP from inside the VNet.
@ -325,7 +339,8 @@ These live in the same project folder as this brief (ask Dan — several contain
## 12. Suggested first day
1. Get the SSH key, AD account in `HTTPS_UserAccess`, and Duo enrolment from Dan (§2).
2. SSH in; run `docker ps` and `df -h`. Confirm 20 containers up and both disks healthy.
2. SSH in; run `docker ps` and `df -h`. Confirm every container is up and both disks are
healthy. Don't check against a fixed number — services come and go (§3).
3. Log into `grafana.yokogawa.tech` — this exercises the whole AD + Duo + SSO path in one go.
4. Open `logs.yokogawa.tech` (Dozzle) and `portainer.yokogawa.tech` to get a feel for the stack.
5. Read `Host_Documentation.md`, especially the change log — it explains the scars.