Files
ScadaBridge/infra
Joseph Doherty 3bf1537ea0 docs(docker)+docs(docker-env2)+infra: close P8-7 + P8-10 — LDAP doc drift + env2 gRPC port/teardown parity
P8-7: docker/README.md and docker-env2/README.md still listed the retired
scadabridge-ldap container. Verified against the running config
(central-node-*/appsettings.Central.json): both rigs actually bind to the
local redundant GLAuth pair (zb-ldap-primary :3893 + zb-ldap-backup :3894 on
host.docker.internal, source of truth scadaproj/infra/glauth-redundant), not
the shared 10.100.0.35 GLAuth the infra/docker-compose.yml retirement comment
claimed — that binding is itself stale, its serviceaccount password having
been rotated away by SEC-36. Corrected all three docs to name the actual
config each rig uses.

P8-10: docker-env2 mapped no host port for the central gRPC control plane
(docker/ maps 9013/9014->8083); added 9113/9114->8083 on both env2 centrals,
matching the free 91XX slots, plus the README port table. teardown.sh's
"preserved in node directories" data note predates the named-volume
migration; rewrote it honestly and added an explicit `docker volume rm`
recipe scoped to the env2 volume prefix, clearly labeled destructive,
mirroring docker/teardown.sh's existing pattern.

Gate: bash docker-env2/deploy.sh from this worktree — both centrals + both
site-x nodes recreated and came up with the new 9113/9114 ports open. The
simultaneous force-recreate split both pairs into independent 1-node
clusters (expected: BootstrapGuard is default-OFF on docker-env2, per
CLAUDE.md); a single restart of the b-side of each pair joined it to its
already-formed peer and both pairs converged (central: memberCount=2,
leader=central-a; site-x: node-b Welcome + singleton Younger). docker/ (the
primary rig) was not touched.
2026-08-19 16:41:04 -04:00
..

ScadaBridge Test Infrastructure

Local Docker-based test services for ScadaBridge development.

Quick Start

docker compose up -d

This starts the following services:

Service Port Purpose
OPC UA (Azure IoT OPC PLC) 50000 (OPC UA), 8080 (web) Simulated OPC UA server with ScadaBridge-style tags
OPC UA 2 (Azure IoT OPC PLC) 50010 (OPC UA), 8081 (web) Second OPC UA server instance (same tags, independent state)
LDAP (GLAuth) 3893 RETIRED (2026-06-04) — no longer started by this stack. Dev/test LDAP is the shared GLAuth on 10.100.0.35:3893 (dc=zb,dc=local). Central nodes bind Ldap:Server=10.100.0.35. Source of truth + config: scadaproj/infra/glauth/.
MS SQL 2022 1433 Configuration and machine data databases
SMTP (Mailpit) 1025 (SMTP), 8025 (web) Email capture for notification testing
REST API (Flask) 5200 External REST API for Gateway and Inbound API testing

First-Time SQL Setup

The MS SQL container does not auto-run init scripts. After the first docker compose up -d, run:

docker exec -i scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \
  -S localhost -U sa -P 'ScadaBridge_Dev1#' -C \
  -i /docker-entrypoint-initdb.d/setup.sql

This creates the ScadaBridgeConfig and ScadaBridgeMachineData databases and the scadabridge_app login. Then seed the Machine Data database:

docker exec -i scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \
  -S localhost -U sa -P 'ScadaBridge_Dev1#' -C \
  -i /docker-entrypoint-initdb.d/machinedata_seed.sql

For the second environment (docker-env2/), also apply the env2 database setup:

docker exec -i scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \
  -S localhost -U sa -P 'ScadaBridge_Dev1#' -C \
  -i /docker-entrypoint-initdb.d/setup-env2.sql

This creates ScadaBridgeConfig2 and ScadaBridgeMachineData2 databases on the same MSSQL instance. The script is also invoked automatically by docker-env2/deploy.sh via docker-env2/init-db.sh, so manual application here is only needed if you want the databases ready before first env2 deploy.

Stopping & Teardown

Stop containers (data persists in SQL volume):

docker compose down

Stop a single service (leave the others running):

docker compose stop opcua      # or: opcua2, mssql, smtp, restapi  (ldap is no longer a local service)
docker compose start opcua     # bring it back without recreating

Full teardown (stop containers, delete SQL data volume, remove pulled images):

./teardown.sh

Or manually:

docker compose down -v         # stop containers + delete SQL data volume
docker compose down -v --rmi all  # also remove downloaded images

After a full teardown, the next docker compose up -d starts fresh — you'll need to re-run the SQL setup script.

CLI Tools

Python CLI tools for interacting with the test services are in tools/.

Set up a Python virtual environment (one-time):

python3 -m venv tools/.venv && source tools/.venv/bin/activate

Install dependencies (one-time, with venv active):

pip install -r tools/requirements.txt

The .venv directory is gitignored.

Quick readiness check (all five services, with venv active):

python tools/opcua_tool.py check
python tools/ldap_tool.py check
python tools/mssql_tool.py check
python tools/smtp_tool.py check
python tools/restapi_tool.py check
Tool Service Key Commands
tools/opcua_tool.py OPC UA check, browse, read, write, monitor
tools/ldap_tool.py LDAP check, bind, search, users, groups
tools/mssql_tool.py MS SQL check, setup, query, tables
tools/smtp_tool.py SMTP (Mailpit) check, send, list, read, clear
tools/restapi_tool.py REST API (Flask) check, call, methods

Each tool supports --help for full usage. See the per-service docs below for detailed examples.

Detailed Documentation

See docs/test_infra/ for per-service setup guides: