Live VPS host telemetry, oscilloscope UI (bunko.me/vps)
- JavaScript 47.6%
- HTML 31.7%
- Python 20%
- Dockerfile 0.7%
|
|
||
|---|---|---|
| app | ||
| .gitignore | ||
| docker-compose.yml | ||
| README.md | ||
Halo
Live host telemetry for the bunko.me VPS, served from inside a container. SSO-gated at https://bunko.me/vps.
"Oscilloscope" look: two-channel phosphor scope traces (CPU + network) with load / memory / disk vitals and a live Docker container roster, streamed over SSE.
Reading the HOST from inside a container
Halo stays on the shared web network (so Caddy routes to it by name) yet every
reading reflects the host, not the container:
- CPU / memory / load / uptime — psutil pointed at the bind-mounted host procfs
(
PROCFS_PATH=/host/proc); these files aren't network-namespaced. - Network throughput — read from
/host/proc/1/net/dev, i.e. PID 1's network namespace = the host root netns./proc/netis namespaced, so a bridge-networked container's own/proc/net/devonly shows its veth; PID 1 sees the real NICs. - Disk — statvfs on the bind-mounted host rootfs (
/host/root). - Containers — the Docker socket (read-only), reachable because the app user is
added to the host docker gid via
group_add.
Stack
FastAPI + psutil + docker SDK (server) · vanilla-JS canvas oscilloscope fed by SSE
(client) · Docker, behind the shared Caddy proxy on the web network.
Config (environment)
| var | default | meaning |
|---|---|---|
BASE_PATH |
/vps |
URL prefix the proxy strips |
HOST_PROC |
/host/proc |
bind-mounted host procfs |
HOST_ROOT |
/host/root |
bind-mounted host rootfs (for disk) |
HOSTNAME_LABEL |
HALO |
name shown in the UI |
NET_IFACES |
eth0 |
interface(s) summed for throughput |
Endpoints
GET /— the dashboardGET /api/stream— SSE: one full sample every ~2sGET /api/stats— latest snapshotGET /api/history— rolling ~5-min window (scope backfill)GET /health
Run
docker compose up -d --build
Requires the bind mounts + group_add in docker-compose.yml.