R2D2-OPS-Kuma/README.md
Joshua Belke 767421c3b6 docs(readme): rewrite for TFX FMV console + k8s deployment
Replace the stock Uptime Kuma README with one describing the actual
app: the R2D2/Task Force X ops console, its architecture, local dev,
configuration/security model, and the standalone k8s deployment at
ops.r2d2.office.ilab.zone. Drops upstream badges/sponsors/live-demo.
2026-07-08 05:44:23 -04:00

8.8 KiB
Raw Permalink Blame History

Task Force X emblem

R2D2 Status — Task Force X FMV Console

Fleet monitoring and full-motion-video (FMV) operations console for the Task Force X (TFX) unmanned maritime program. It tracks the health of ~118 assets — video feeds, restreamer panels, NodeRed pipelines, and core R2D2 services — across the NATO maritime theatres, and gives operators a single board to see which platforms are live, watch their streams, and capture evidence.

The monitoring engine is Uptime Kuma 2.4.0 (unmodified upstream). Everything specific to TFX lives in .settings/: a seed toolchain that builds the monitor topology, and a purpose-built operator console layered on top of Kuma.

Production console: https://ops.r2d2.office.ilab.zone


What it does

  • Monitors ~118 assets grouped three levels deep — waterway → country → asset — across Central/Eastern Med, Baltic, North Sea and North Atlantic.
  • Video-aware status. A feed that answers HTTP 200 but whose projector snapshot has frozen is downgraded to pending — so "up" means live video, not just a reachable port.
  • Operator console — search/filter the whole fleet, open a native detail view with an HLS player, and record clips or snapshot sessions to disk.
  • Region-grouped public status pages (/status/r2d2, videos, panels, core, nodered) rebuilt idempotently from the seed plan.

Architecture

┌──────────────────────────────────────────────────────────────┐
│  Uptime Kuma 2.4.0 (upstream, unmodified)                     │
│  · monitoring engine · heartbeats/uptime · CSS-only status    │
│  · SQLite (PVC)                    listens :3001              │
└───────────────▲───────────────────────────────┬──────────────┘
                │ socket.io (server-side, admin) │ HTTP status pages
                │                                 ▼
┌───────────────┴──────────────────────────────────────────────┐
│  R2D2 Ops Console  (.settings/ops/serve.mjs, :4013)           │
│  · logs into Kuma once, holds a live in-memory fleet model    │
│  · SPA + JSON snapshot + SSE live stream                      │
│  · snapshot / HLS media proxy (host-allowlisted)              │
│  · liveness poller (snapshot-hash freeze detection)           │
│  · recorder (ffmpeg clip + snapshot capture)                  │
└───────────────────────────────────────────────────────────────┘

Repository layout (TFX-specific work is isolated in .settings/; the rest is stock Uptime Kuma):

Path Purpose
.settings/seed/convert.mjs Builds monitors.json from the legacy endpoint config + holovids CSV exports.
.settings/seed/monitors.json Reviewable seed plan — 21 groups · 118 monitors.
.settings/seed/seed.mjs Seeds groups, monitors, and all status pages into Kuma.
.settings/seed/statuspage.mjs Non-destructive rebuild of the status pages only.
.settings/seed/docker-compose.yml Local Kuma on host port 3011, with TFX branding applied at boot.
.settings/ops/serve.mjs Ops console server (:4013).
.settings/ops/index.html Operator SPA (search, detail, HLS player, capture controls).
.settings/ops/recorder.mjs Clip / snapshot recorder.
.settings/features/ Feature roadmap (01–11).

Local development

Prerequisites: Docker (with Compose) and Node.js 18+.

cd .settings/seed

# 1. Start a local Kuma (SQLite preselected — no setup wizard).
#    Host port 3011 (3001 is commonly taken); TFX branding is applied at boot.
docker compose up -d

# 2. (optional) Regenerate the seed plan. monitors.json is committed.
node convert.mjs

# 3. Seed groups, monitors, and status pages. First run creates the admin user.
KUMA_URL=http://localhost:3011 node seed.mjs

# 4. Rebuild only the status pages later, non-destructively.
KUMA_URL=http://localhost:3011 node statuspage.mjs

Start the operator console against that Kuma:

cd .settings/ops
KUMA_URL=http://localhost:3011 node serve.mjs
# → http://localhost:4013

Configuration

Both the seeder and the ops server are configured entirely through environment variables.

Variable Default Used by Meaning
KUMA_URL http://localhost:3011 seed, ops Kuma base URL.
ADMIN_USER / ADMIN_PASS NATO / NATO1949 seed, ops Kuma admin credentials. Override before any non-local deploy — seeding refuses the defaults against a non-localhost target unless ALLOW_DEFAULT_CREDS=1.
FORCE unset seed Allow re-seeding an already-populated instance.
OPS_PORT 4013 ops Console listen port.
OPS_BIND 127.0.0.1 ops Listen interface. Set 0.0.0.0 to expose beyond localhost.
OPS_SECRET unset ops When set, every state-changing POST must send a matching x-ops-secret header. Set this before binding beyond localhost.
REC_ROOT machine-specific recorder Root directory for captured clips/snapshots.

Security model

The Kuma admin password is used only on the server. The browser never sees a credential or a direct Kuma socket. The console is not read-only, though — it exposes mutating endpoints (delete-monitors, set-interval, record/{start,stop,config}) that act on Kuma as admin. Two controls gate them:

  • OPS_BIND defaults to localhost, so the console answers nothing on the network until you opt in.
  • OPS_SECRET, once set, requires the x-ops-secret header on every mutating request; read endpoints (feed, snapshot, HLS) stay open.

Always set OPS_SECRET before setting OPS_BIND=0.0.0.0.


Kubernetes deployment

The production console is a standalone deployment reachable at ops.r2d2.office.ilab.zone — a Kuma pod plus the ops server, with the pod joined to the mesh so it can actually probe the feeds.

Target topology:

  • Kuma container — louislam/uptime-kuma:2, listening on :3001, SQLite persisted on a Longhorn PVC so monitor config and history survive restarts.
  • Ops console container — runs .settings/ops/serve.mjs on :4013, KUMA_URL pointing at the Kuma container. OPS_BIND=0.0.0.0 with OPS_SECRET set; admin credentials injected from a Kubernetes Secret.
  • NetBird sidecar — most feeds live on the mesh and are unreachable from the cluster's default network. The sidecar puts the pod on the mesh so Kuma's probes and the ops snapshot/HLS proxies resolve real hosts. Off-mesh, feeds read as pending/down by design.
  • Ingress — TLS at ops.r2d2.office.ilab.zone, routing to the ops console (:4013), which fronts both the operator SPA and the Kuma status pages.

Deployment notes:

  • Cluster access uses .settings/kubeconfig.r2d2 — treat as sensitive.
  • Rotate ADMIN_USER / ADMIN_PASS out of the defaults; source them from the Secret, never from image or compose defaults.
  • The packaged Helm chart (Kuma + ops console + NetBird sidecar + Longhorn PVC + ingress) is the deployment vehicle and is tracked as roadmap item R-007; until it lands, deployment is applied from manifests against the topology above.

Roadmap

Feature specs live in .settings/features/ and the umbrella plan in .settings/ops/PLAN.md:

# Feature State
01 Ops Feed (search / filter) Done
02 Holovids feed enrichment Done
05 Deep probes / liveness Partial
06 Native media detail + HLS player Building
07 Live recording (clips + snapshots) Building
08 KLV telemetry discovery Discovery
09 C2 map / common operating picture Planned
10 ReductStore media archive (FIFO) Planned
11 Drone MQTT discovery & video↔node association Planned

Upstream

Built on Uptime Kuma by Louis Lam, licensed under the MIT License. The server/ and src/ trees are stock upstream and are intentionally left unmodified — all TFX customisation is confined to .settings/. See LICENSE for terms.