Files
Ryan 71ef622b4f
Test and deploy MQTT backend / test (push) Successful in 2m8s
Test and deploy MQTT backend / deploy (push) Successful in 18s
Deploy MQTT test backend with private viewer and Gitea CI/CD
2026-10-08 14:48:53 +03:30

9.4 KiB

Sprint 2 — Server broker deployment package

Status: COMPLETE. Artifacts, server-container runtime and external TLS/plaintext connection checks passed on 2026-10-06. Read the plan, sprint index and shared rules, and README.

Goal and scope

Prepare an independent server-deployable Mosquitto Compose package for the user to deploy. Include TLS and an optional authenticated plaintext listener per the user's updated request. Validate artifacts locally; defer runtime checks to the deployed server.

Deliverables and likely files

  • deploy/compose.yaml, broker configuration/ACL templates and health-check helper.
  • Local-only certificate/credential provisioning helper; generated secrets ignored.
  • docs/DEPLOYMENT.md server setup and verification instructions.

Tasks

  1. Verify Mosquitto 2.1.2-alpine image/platform availability and pin its digest; validate version-specific password/ACL plugin configuration.
  2. Publish TLS in the base server Compose file and plaintext only with an explicit override; both remain authenticated with identical ACLs. Enable persistence, bounded queues/packets/logs, and correct container ownership/modes.
  3. Generate a dedicated local test CA and server certificate with matching server hostname/IP and localhost SANs. Keep keys and generated credentials outside tracked files.
  4. Provision separate backend, device and health users. Restrict each device to its own topics; deny production/cross-device access.
  5. Add authenticated TLS subscribe/publish/receive health checking with a deadline and dedicated topic. Keep secrets out of arguments/output.
  6. Document start/stop/inspect, certificate trust, persistence cleanup, backup, update and rollback. Destructive reset remains explicit and test-instance-only.

Dependencies and required inputs

Sprint 1; available Docker/Compose and registry access. If unavailable, report the blocker and propose an isolated native alternative. Remote server access is not needed.

Acceptance criteria

  • Deployed server broker starts and passes an actual authenticated MQTT health exchange.
  • Anonymous access, bad credentials, bad CA/hostname and forbidden topics fail as expected.
  • Per-device ACLs prevent cross-device publishing/subscription. Commands cannot reach production namespaces.
  • Graceful restart preserves selected retained/session state; evidence identifies graceful restart rather than crash durability.
  • Configuration and examples contain no real credentials; plaintext host access is enabled only through the explicit override and remains authenticated.

Automated checks

Compose validation, broker config/startup validation using the pinned image, health exchange, positive/negative TLS/auth/ACL smoke checks. Do not print resolved secret-bearing Compose configuration.

Manual verification

Inspect port binding, mounts, ownership, bounded logs and restart behavior. Verify server hostname trust and localhost health checking with the generated CA.

Risks and unresolved decisions

Host container permissions, plugin paths in the exact image, architecture support, port conflicts. Remote OS/DNS/certificate policy remains deferred.

Mandatory end-of-sprint testing and completion gate

After implementing this sprint, run its automated checks and manual verification above. Inspect the final changes for correctness, scope, secret exposure, and compatibility with completed sprints. Fix failures and rerun affected checks before declaring completion.

Record the exact commands/checks, actual outcomes, verification environment, and each acceptance criterion as PASS, FAIL, or BLOCKED. Include applicable regression checks for previously completed behavior. A skipped/unavailable required check is BLOCKED, never PASS; do not claim full sprint completion while required checks fail or remain blocked. Do not run unrelated or production-project tests.

Report the results and remaining limitations to the user. Wait for authorization before the next sprint unless continued execution was explicitly authorized. Even with permission to continue, do not bypass this verification gate.

Copy-ready implementation prompt

Implement Sprint 2 only in /home/ryan/Media/Code/Code/robot-market/test-mqtt-5 after authorization. Read applicable AGENTS.md, /home/ryan/.codex/RTK.md, README.md, docs/PLAN.md and docs/sprints/02-local-broker.md. Prefix shell commands with rtk. Existing projects and production brokers are read-only. Do not deploy remotely.

Build/maintain the separate server Mosquitto deployment package, using verified 2.1.2-alpine and its platform-compatible immutable digest. The user will deploy it and provide endpoint/credential-file details. Check exact 2.1 password/ACL plugin syntax and image paths. Publish TLS in the base Compose file and optional authenticated plaintext in a separate override; do not weaken TLS certificate verification. Disable anonymous access. Add dedicated local test certificate generation, ignored secrets, separate backend/device/health identities, least-privilege per-device ACLs, persistence, bounded broker queues/logs and correct file ownership. Implement an authenticated TLS MQTT subscribe/publish/receive health check with safe secret handling. Document server start/stop/inspect, backup/update/rollback and remote prerequisites.

Verify real health exchange, invalid credentials/CA/hostname, forbidden/cross-device topics and graceful broker restart persistence. If container tooling is unavailable, report it and propose a native isolated alternative rather than claiming tests passed. Do not implement the Go MQTT application or viewer. Report acceptance results and remaining inputs, then wait.

ESP32 reference: read docs/PLAN.md section 6.1 for the supplied Esp32MqttConfig. It is connection configuration, not a payload schema or a blocker for Go implementation. Preserve the proposed Go test contracts. Device-specific MQTT 5 selection depends on the actual C library/build/init; inspect TLS/CA handling, role-specific credentials and single publish_topic limitations during device integration. Do not modify existing C projects. Separate MQTT 3.1.1 payload interoperability from native MQTT 5 feature evidence.

Mandatory completion gate: after implementing this sprint, run its listed automated and manual checks plus relevant regression checks, inspect the final changes for correctness/scope/secrets/compatibility, fix failures and rerun affected checks. Report exact checks, real outcomes, environment, and every acceptance criterion as PASS/FAIL/BLOCKED. Missing required checks are BLOCKED, never a pass. Do not mark the sprint complete with unresolved failures/blockers or bypass verification when continuing to another sprint.

Completion evidence and remaining server checks

User steering: deploy the broker on the server; provide a Compose package for operator deployment; support plaintext alongside TLS for testing. No server changes or permanent local broker were performed.

Acceptance criterion Status Evidence / remaining action
Deployable pinned broker config PASS for artifacts Verified official multi-platform digest; Mosquitto 2.1.2 --test-config exits 0 in a network-disabled disposable container
Health MQTT exchange PASS User ran the verifier on the deployed server: authenticated TLS exchange passed
Bad credentials / CA / hostname rejected PASS Deployed verifier rejected anonymous access, invalid credentials, untrusted CA and wrong hostname
Per-device ACL isolation / production topic denial PASS Deployed verifier confirmed cross-device publish/read blocking and production topic denial
Graceful retained/session persistence PASS Deployed verifier confirmed retained status and offline session recovery after graceful restart; crash durability not tested
No tracked credentials; optional plaintext explicit PASS Generated secrets confined to /tmp for validation; ignored server paths; merged Compose ports/auth configuration checked

Checks actually run locally:

  • docker buildx imagetools inspect: 2.1.2-alpine digest verified; bare 2.1.2 tag was absent and corrected.
  • docker compose config --quiet for TLS-only and TLS+plaintext: PASS.
  • Compose JSON assertions: ports, non-root runtime, read-only mounts/filesystem, immutable image and log limits PASS; no credential environment values.
  • Python AST/helper --help and sh -n healthcheck: PASS.
  • prepare.py with throwaway /tmp output and owner 1000:1000: PASS, real OpenSSL generation and container-based password hashing.
  • Generated hashed passwords/secret modes/CA-key isolation: PASS without displaying values.
  • OpenSSL chain, configured hostname, localhost and 127.0.0.1 checks: PASS; wrong hostname rejected.
  • Repeat setup refuses overwrite; invalid hostname inputs rejected: PASS.
  • Exact pinned image --test-config with temporary mounts and --network none: PASS. No listening broker started.

On 2026-10-06 the user ran the corrected verify.py --insecure --restart on 109.122.252.129. All server-container checks passed, including optional authenticated plaintext reception. The initial cross-device failure was a verifier exit-code bug; the corrected verifier requires MQTT PUBACK Not authorized (135). Server runtime acceptance is complete. External authenticated MQTT 5 device telemetry publication/backend reception passed from the development computer on TLS 8884 with CA/hostname verification and plaintext 1884, using unique non-retained probes. Physical hardware remains NOT VERIFIED. See DEPLOYMENT.md for operator commands.