5.9 KiB
Running RuView with Docker (and CasaOS)
This guide covers running the RuView sensing server (the Rust + Axum service that hosts the REST API, WebSocket stream, and web dashboard) as a Docker container, and importing it into CasaOS.
It uses the prebuilt image ruvnet/wifi-densepose:latest from Docker Hub, so the
host does not need to compile the Rust workspace.
Architecture note: the published
:latesttag currently ships an amd64 layer only. On an amd64 host (e.g. an x86 mini-PC / NUC / Ryzen box) it runs as is. On arm64 (Raspberry Pi, etc.) build locally first:docker compose -f docker/docker-compose.yml build.
1. Quick start (no hardware)
cd ruview
CSI_SOURCE=simulated docker compose -f docker-compose.casaos.yml up -d
Then open the dashboard:
http://<host-ip>:3000/ui/index.html
The bare root
http://<host-ip>:3000/is only an API index (a plain list of endpoints) — the visual dashboards live under/ui/:index.html(main),observatory.html(live feed),pose-fusion.html(webcam + CSI),viz.html(3D).
CSI_SOURCE=simulated feeds the pipeline with synthetic CSI so you can explore
the dashboard, API, and vital-sign/pose visualizations without any hardware.
Stop / remove:
docker compose -f docker-compose.casaos.yml down
2. Ports
The compose file (docker-compose.casaos.yml) publishes these host ports:
| Service | Container | Host | Notes |
|---|---|---|---|
| REST API + web UI | 3000/tcp | 3000 | Dashboard lives here (/, /ui/...) |
| WebSocket sensing feed | 3001/tcp | 3001 | ws://host:3001/ws/sensing |
| ESP32 CSI ingest | 5005/udp | 5005 | ESP32-S3 nodes stream CSI frames here |
If a host port clashes on your machine, edit the published: values in
docker-compose.casaos.yml (and update port_map / webui_port in the
x-casaos block to match the new UI port). The dashboard's WebSocket URL is
derived from the page host, so keep the API and WS ports reachable from the same
hostname.
Verified endpoints (all return 200 once running):
/ /ui/index.html /ui/observatory.html
/api/v1/status /api/v1/sensing/latest /api/v1/models
3. Data source modes (CSI_SOURCE)
| Value | Behaviour |
|---|---|
auto |
(default) Probe UDP 5005 for an ESP32 node; fall back to simulated. |
esp32 |
Require real CSI frames from an ESP32-S3 node on UDP 5005. |
simulated |
Synthetic CSI — no hardware. Best for first evaluation. |
wifi |
Host Wi-Fi RSSI/scan (Windows netsh) — not available inside a Linux container. |
Set it inline (CSI_SOURCE=esp32 docker compose ... up -d) or via a .env file
next to the compose, or in the CasaOS environment-variable UI.
Models
Drop .rvf model files into ./data/models/ (mounted to /app/models); the API
exposes them under /api/v1/models. Pretrained weights:
pip install huggingface_hub
huggingface-cli download ruvnet/wifi-densepose-pretrained --local-dir data/models/wifi-densepose-pretrained
Optional API auth
Leave RUVIEW_API_TOKEN empty for LAN-only use. Set it to require
Authorization: Bearer <token> on /api/v1/*:
RUVIEW_API_TOKEN=$(openssl rand -hex 32) docker compose -f docker-compose.casaos.yml up -d
4. Importing into CasaOS
The compose file includes an x-casaos: metadata block (icon, title, category,
description, port map), so CasaOS shows it as a proper app tile.
Option A — CasaOS UI (Custom Install)
- CasaOS dashboard → App Store → Custom Install (the
+/ "Install a customized app"). - Switch to the Import / YAML view and paste the contents of
docker-compose.casaos.yml. - Install. The tile opens
http://<host-ip>:3000/ui/index.html.
Option B — CLI (CasaOS still detects the container)
cd ruview
docker compose -f docker-compose.casaos.yml up -d
Icon: the manifest points at
https://cdn.jsdelivr.net/gh/ruvnet/RuView@main/assets/ruview-icon.png(jsDelivr servesassets/ruview-icon.pngstraight from the repo). To use a different or fully local icon, replace bothicon:URLs (inlabels:andx-casaos:) with another URL or a file path served by your own host.
5. Connecting live ESP32-S3 CSI nodes
RuView's full capability set (presence through walls, breathing/heart rate, fall detection, pose) needs Channel State Information from a CSI-capable node.
- Flash the firmware from
firmware/esp32-csi-node/to an ESP32-S3 (8 MB or 4 MB). See the repoCLAUDE.md"ESP32 Firmware Build" section. - Provision Wi-Fi + the sink (this server's) IP:
Pointpython firmware/esp32-csi-node/provision.py --port /dev/ttyUSB0 \ --ssid "YourWiFi" --password "secret" --target-ip <host-ip>--target-ipat the host running this container; frames arrive on UDP 5005. - Start with
CSI_SOURCE=esp32(orauto).
Supported chips: ESP32-S3 (dual-core) and ESP32-C6. The original ESP32 and ESP32-C3 are single-core and cannot run the CSI DSP pipeline.
6. Operations
# Logs
docker logs ruview -f --tail 100
# Restart / update to the latest image
docker compose -f docker-compose.casaos.yml pull
docker compose -f docker-compose.casaos.yml up -d
# Status of the running server
curl -s http://<host-ip>:3000/api/v1/status
Troubleshooting
- Dashboard loads but no data: check the data source — with
autoand no ESP32 present it falls back tosimulated; logs printData source: .... - Multiple ESP32 nodes on Docker Desktop for Windows: multi-source UDP collapses
to one source IP at the WSL boundary. Use the host relay (see
docs/TROUBLESHOOTING.md §9). Native Linux/CasaOS hosts are unaffected. - Port clash on 3000/3001: edit
published:indocker-compose.casaos.yml.