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.
8.8 KiB
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
- Kuma dashboard: http://localhost:3011
- Public status page: http://localhost:3011/status/r2d2
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_BINDdefaults to localhost, so the console answers nothing on the network until you opt in.OPS_SECRET, once set, requires thex-ops-secretheader 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.mjson:4013,KUMA_URLpointing at the Kuma container.OPS_BIND=0.0.0.0withOPS_SECRETset; admin credentials injected from a KubernetesSecret. - 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_PASSout of the defaults; source them from theSecret, 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.