HOMELAB-1526: feat(charts): add mqttx-web app chart — MQTT management UI deployed E2E #501

Merged
aaron merged 1 commit from plane/HOMELAB-1526-mqttx-web into live 2026-09-08 19:49:39 +00:00
Owner

What

Adds a web-based management UI for the sendrast Mosquitto MQTT broker using MQTTX Web (official emqx/mqttx-web:v1.13.0 image), deployed via a new infra-core native Helm chart core/charts/apps/mqttx-web.

Why

No way to inspect topics, retained messages, or publish test messages against the broker without CLI tools. This gives a browser UI for debugging live-tracking (SEND-6) and tracker (SEND-75) traffic.

How

  • New Helm chart core/charts/apps/mqttx-web wrapping the official EMQX image
  • Stateless static SPA — the browser connects directly to the broker over the existing public WSS endpoint wss://mqtt.sendrast.aaron.reynoza.org/mqtt; no server-side credentials or persistence needed
  • Hardened pod: uid 1000, unprivileged port 8080, read-only rootfs, all caps dropped, seccomp RuntimeDefault, no service account token
  • Deployed to the sendrast namespace via ArgoCD and exposed at https://mqttx.sendrast.aaron.reynoza.org behind Pangolin SSO (UI has no auth of its own, edge auth covers it)
  • No changes to Mosquitto config — reuses the existing 8083 WebSocket listener

Verification

  • helm lint clean, helm template renders correctly
  • ArgoCD app synced, pod Ready in sendrast namespace
  • https://mqttx.sendrast.aaron.reynoza.org loads behind Pangolin auth
  • Connected to wss://mqtt.sendrast.aaron.reynoza.org/mqtt with broker credentials from the UI
  • Subscribed to $SYS/# and published a test message E2E

Closes HOMELAB-1526.

## What Adds a web-based management UI for the sendrast Mosquitto MQTT broker using MQTTX Web (official `emqx/mqttx-web:v1.13.0` image), deployed via a new infra-core native Helm chart `core/charts/apps/mqttx-web`. ## Why No way to inspect topics, retained messages, or publish test messages against the broker without CLI tools. This gives a browser UI for debugging live-tracking (SEND-6) and tracker (SEND-75) traffic. ## How - New Helm chart `core/charts/apps/mqttx-web` wrapping the official EMQX image - Stateless static SPA — the browser connects directly to the broker over the existing public WSS endpoint `wss://mqtt.sendrast.aaron.reynoza.org/mqtt`; no server-side credentials or persistence needed - Hardened pod: uid 1000, unprivileged port 8080, read-only rootfs, all caps dropped, seccomp RuntimeDefault, no service account token - Deployed to the `sendrast` namespace via ArgoCD and exposed at `https://mqttx.sendrast.aaron.reynoza.org` behind Pangolin SSO (UI has no auth of its own, edge auth covers it) - No changes to Mosquitto config — reuses the existing 8083 WebSocket listener ## Verification - [x] `helm lint` clean, `helm template` renders correctly - [x] ArgoCD app synced, pod Ready in `sendrast` namespace - [x] `https://mqttx.sendrast.aaron.reynoza.org` loads behind Pangolin auth - [x] Connected to `wss://mqtt.sendrast.aaron.reynoza.org/mqtt` with broker credentials from the UI - [x] Subscribed to `$SYS/#` and published a test message E2E Closes HOMELAB-1526.
HOMELAB-1526: feat(charts): add mqttx-web app chart
All checks were successful
0/0 projects applied successfully.
CI Review / helm-validate (pull_request) Successful in 5s
CI Review / receiver-test (pull_request) Successful in 3s
Lint & Validate / terraform-validate (pull_request) Successful in 1m48s
Lint & Validate / yaml-lint (pull_request) Successful in 8s
Lint & Validate / shellcheck (pull_request) Successful in 4s
402cc7c3ac
Browser-based MQTT client (official emqx/mqttx-web image) for inspecting
the Mosquitto broker. Static SPA served by http-server; the browser talks
to the broker over WSS directly, so the chart is stateless with no
credentials or persistence. Runs as uid 1000 on an unprivileged port with
a hardened securityContext; edge auth is handled by Pangolin SSO.
homelab-bot left a comment
Collaborator

AI Review (HOMELAB-1526)

Verdict: PASS-WITH-NITS

Acceptance Criteria (HOMELAB-1526)

Criterion Met? Evidence
Explore candidate UIs (browser-client over WSS vs server-side bridge) values.yaml:1-6 — documents the browser-client/WSS choice: "browser connects to the broker over MQTT-over-WebSocket (WSS) directly"
Deploy chosen UI via prod repo GitOps (ArgoCD) ⚠️ Chart-only PR in infra-core; no prod/apps/ Application manifest here — must land in the companion prod PR
Wire credentials from OpenBao/ESO (no secrets in Git) values.yaml:3-5 — "no broker credentials" by design (credentials live in the user's browser); no secrets in chart
Expose via Cilium Gateway + Pangolin per existing pattern ⚠️ Not in this diff — expected in prod repo (Gateway/HTTPRoute + scripts/pangolin/pangolin-resources.py)
UI reachable, can subscribe/publish against broker ⚠️ Not verifiable from the diff; PR title claims "deployed E2E" — confirm against mqtt.sendrast.aaron.reynoza.org WSS listener
No plaintext credentials in Git or pod spec Full diff reviewed — no secrets; automountServiceAccountToken: false (deployment.yaml:19)
CI green on prod PR ⚠️ Out of scope for this repo; check the prod PR checks

Design Doc Citations

  • Sendrast — Production vs Homelab Architecture (Target) (§2) — confirms homelab MQTT broker is Mosquitto (SEND-6) in the staging stack; consistent with this UI targeting the sendrast namespace broker.
  • Same doc (§6 promotion rule 1) — "Homelab first: every change deploys to homelab staging (ArgoCD)" — the prod-repo ArgoCD app is the required next artifact.
  • Same doc (§7) — MQTT is currently anonymous + plaintext ("multi-tenant live-position leak", being closed under SEND-49/56/57/68). The values.yaml edge-auth note ("Protect the UI at the edge (Pangolin SSO) — the app has no auth of its own") is therefore load-bearing: Pangolin SSO must actually be configured before merge of the prod PR, or the UI becomes an unauthenticated read/write console on live telemetry.

Open Issues

  • [Chart.yaml:6 vs values.yaml:12] appVersion: "1.13.0" but image.tag: "v1.13.0" — mismatch; either align formats or default tag: {{ .Chart.AppVersion }} so they can't drift.
  • [deployment.yaml:37] readOnlyRootFilesystem: true with no emptyDir for /tmp — fine if the upstream docker-entrypoint.sh doesn't write at startup (title says verified E2E), but if it does env-substitution writes this will crash-loop on any image bump. Worth a /tmp emptyDir as cheap insurance.
  • [values.yaml:27-32] 64Mi memory limit is tight for node + http-server; fine under E2E verification, but expect OOMKill risk if the image grows — non-blocking.
  • [_helpers.tpl:25-28] commonLabels merged only into labels, not selectorLabels — correct as written, just confirm this matches other infra-core app charts for consistency.
  • No NetworkPolicy or ServiceMonitor in chart — presumably consistent with app-chart conventions (monitoring applied via prod values/extraManifests); flag only if mqttx-web should be scraped.

Summary: Clean, well-commented, security-hardened minimal chart (non-root, RO rootfs, drop ALL caps, RuntimeDefault seccomp, no SA token). All unmet criteria belong to the companion prod-repo PR (ArgoCD app, Gateway route, Pangolin SSO resource) — ensure that PR lands before this ticket closes, and that Pangolin SSO is enforced given the broker's current anonymous-access posture (doc §7).

Powered by Kimi k3 · advisory.

## AI Review (HOMELAB-1526) **Verdict**: PASS-WITH-NITS ### Acceptance Criteria (HOMELAB-1526) | Criterion | Met? | Evidence | |---|---|---| | Explore candidate UIs (browser-client over WSS vs server-side bridge) | ✅ | `values.yaml:1-6` — documents the browser-client/WSS choice: "browser connects to the broker over MQTT-over-WebSocket (WSS) directly" | | Deploy chosen UI via prod repo GitOps (ArgoCD) | ⚠️ | Chart-only PR in infra-core; no `prod/apps/` Application manifest here — must land in the companion prod PR | | Wire credentials from OpenBao/ESO (no secrets in Git) | ✅ | `values.yaml:3-5` — "no broker credentials" by design (credentials live in the user's browser); no secrets in chart | | Expose via Cilium Gateway + Pangolin per existing pattern | ⚠️ | Not in this diff — expected in prod repo (Gateway/HTTPRoute + `scripts/pangolin/pangolin-resources.py`) | | UI reachable, can subscribe/publish against broker | ⚠️ | Not verifiable from the diff; PR title claims "deployed E2E" — confirm against `mqtt.sendrast.aaron.reynoza.org` WSS listener | | No plaintext credentials in Git or pod spec | ✅ | Full diff reviewed — no secrets; `automountServiceAccountToken: false` (`deployment.yaml:19`) | | CI green on prod PR | ⚠️ | Out of scope for this repo; check the prod PR checks | ### Design Doc Citations - **Sendrast — Production vs Homelab Architecture (Target)** (§2) — confirms homelab MQTT broker is Mosquitto (SEND-6) in the staging stack; consistent with this UI targeting the sendrast namespace broker. - Same doc (§6 promotion rule 1) — "Homelab first: every change deploys to homelab staging (ArgoCD)" — the prod-repo ArgoCD app is the required next artifact. - Same doc (§7) — MQTT is currently **anonymous + plaintext** ("multi-tenant live-position leak", being closed under SEND-49/56/57/68). The values.yaml edge-auth note ("Protect the UI at the edge (Pangolin SSO) — the app has no auth of its own") is therefore load-bearing: Pangolin SSO must actually be configured before merge of the prod PR, or the UI becomes an unauthenticated read/write console on live telemetry. ### Open Issues - [Chart.yaml:6 vs values.yaml:12] `appVersion: "1.13.0"` but `image.tag: "v1.13.0"` — mismatch; either align formats or default `tag: {{ .Chart.AppVersion }}` so they can't drift. - [deployment.yaml:37] `readOnlyRootFilesystem: true` with no `emptyDir` for `/tmp` — fine if the upstream `docker-entrypoint.sh` doesn't write at startup (title says verified E2E), but if it does env-substitution writes this will crash-loop on any image bump. Worth a `/tmp` emptyDir as cheap insurance. - [values.yaml:27-32] 64Mi memory limit is tight for node + http-server; fine under E2E verification, but expect OOMKill risk if the image grows — non-blocking. - [_helpers.tpl:25-28] `commonLabels` merged only into `labels`, not selectorLabels — correct as written, just confirm this matches other infra-core app charts for consistency. - No NetworkPolicy or ServiceMonitor in chart — presumably consistent with app-chart conventions (monitoring applied via prod values/extraManifests); flag only if mqttx-web should be scraped. **Summary:** Clean, well-commented, security-hardened minimal chart (non-root, RO rootfs, drop ALL caps, RuntimeDefault seccomp, no SA token). All unmet criteria belong to the companion prod-repo PR (ArgoCD app, Gateway route, Pangolin SSO resource) — ensure that PR lands before this ticket closes, and that Pangolin SSO is enforced given the broker's current anonymous-access posture (doc §7). _Powered by Kimi k3 · advisory._
aaron merged commit 3d211b6b25 into live 2026-09-08 19:49:39 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Homelab/infra-core!501
No description provided.