- JavaScript 55%
- Vue 38.4%
- HTML 4.3%
- TypeScript 0.9%
- SCSS 0.5%
- Other 0.6%
Self-contained manifests + ops image Dockerfile to run the ops console as the public entry point (ops.r2d2.office.ilab.zone / VIP 192.168.3.153) in the r2d2-status-kuma namespace on the RAID cluster, fronting an Uptime Kuma backend. - ops-server (git.office.ilab.zone/raid/r2d2-ops) serves the FMV/telemetry UI and logs into Kuma over socket.io on localhost; Service/LB/Ingress target it (4013). - Kuma (git.office.ilab.zone/raid/r2d2-status-kuma:2.4.0) is a private backend on a MariaDB sidecar. - Ordered native sidecars mariadb -> netbird -> kuma -> wait-kuma-login gate, so the DB, the mesh, and a working Kuma socket-login are all ready before ops-server starts. Fixes the boot-time login hang (timeout-less emitWithAck in serve.mjs) and the mesh EHOSTUNREACH false-downs. - Secrets (db creds, netbird setup key, admin/ops creds) live only in-cluster, referenced by secretKeyRef; nothing sensitive in the manifest. |
||
|---|---|---|
| .github | ||
| .settings | ||
| config | ||
| db | ||
| docker | ||
| extra | ||
| helm | ||
| public | ||
| server | ||
| src | ||
| test | ||
| .dockerignore | ||
| .editorconfig | ||
| .eslintrc.js | ||
| .gitignore | ||
| .npmrc | ||
| .prettierignore | ||
| .prettierrc.js | ||
| .stylelintrc | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| CNAME | ||
| CODE_OF_CONDUCT.md | ||
| compose.yaml | ||
| CONTRIBUTING.md | ||
| ecosystem.config.js | ||
| index.html | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| SECURITY.md | ||
| tsconfig-backend.json | ||
| tsconfig.json | ||
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.