Nabd
v…
connecting…One small container for your home lab — GPU & local-AI, Docker containers, systemd services and host health, all on one page. Everything is discovered automatically; nothing is hardcoded.
Fleet
—Launchpad
Burn Rate
›hubServer Load
›ShowingEvent & Insight Feed
What's Costing You
›hub🎮 GPU right now
🎮 Per-GPU
Live per-card utilisation, VRAM, power and temperature. The cards above pool VRAM and power across all GPUs.
📊 All cards combined
📊 VRAM by service over time
Stacked = VRAM each service holds. Dashed = capacity. Red bands = VRAM pressure; ▼ markers = out-of-memory events.
📋 Services on the GPU (selected range)
| Service | Peak | Avg | % time | Est. energy |
|---|
🩺 Card health (selected range)
| Card | Throttled | Hot | Peak temp | Peak fan | Capped |
|---|
🧮 VRAM allocation right now
💰 Power & cost
GPU power is measured (nvidia-smi); CPU/DRAM are measured via RAPL when readable. "Other" appears only if you set a baseline in Settings — wall power is never guessed.
🗓️ Busy hours — when your lab burns power
Each cell is the average total draw (GPU + CPU + DRAM) for that local day-of-week and hour, over the chosen window. Colour scales by cost-rate when a tariff is set, otherwise by power. Sparse cells are dimmed — hover for the exact figures.
🧾 Breakdown by process / container / model
| Name | Kind | Avg W | Energy | Cost |
|---|
Click a row to drill into its power & cost over time. GPU split by VRAM share; CPU split by CPU-time share of the measured package power.
Drilldown
📦 Installed models
Every model this host's recognised AI servers report — ollama's on-disk inventory (size, params, quant) plus what every other server (vLLM, llama.cpp, …) is currently serving, grouped by provider. A Loaded badge marks models resident in VRAM this moment. Read-only.
One panel per model server: its VRAM timeline (shared by the models it hosts) plus each model's own peak & average. Runs counts contiguous load sessions over the selected range and how many spilled into system RAM (didn't fully fit VRAM — the Now column shows the live VRAM + RAM split). Used by names the apps whose connections to the server overlapped the model's residency — approximate when several models share one server. A server is shown even while Idle (model unloaded / between requests), so nothing vanishes when VRAM is released. Recognised: Ollama, vLLM, SGLang, llama.cpp, LocalAI, HF TGI/TEI, LoRAX, mistral.rs, Aphrodite, koboldcpp, tabbyAPI, text-generation-webui, LM Studio, xinference, OpenLLM, LiteLLM, GPUStack, Cortex/Jan, Ramalama, Nexa, Triton, Infinity, faster-whisper/Speaches, Whisper ASR webservice/WhisperX, Wyoming (HA voice), OpenedAI-Speech, Stable Diffusion (A1111/Forge/SD.Next), InvokeAI, ComfyUI.
🧪 Runs — pushed from your notebooks & MLflow, priced with real GPU energy
| Run | Source | Status | Started | Duration | Metrics | Energy | Cost |
|---|
Run
⚡ GPU power & utilisation during this run
🔬 Auto-detected on the hub — training processes running now (no push needed)
🧰 Notebooks & tools
Auto-discovered DS/AI web tools running on the hub. A 🟡 VRAM tag means a kernel/process is holding GPU memory — often a forgotten notebook squatting on VRAM.
📈 GPU activity sessions
| Started | Duration | Peak util | Peak VRAM | Avg power | Energy | Cost |
|---|
Contiguous GPU-busy periods reconstructed from power & utilisation history — each is a training run, batch job or inference burst. Energy is integrated from GPU power; cost uses your kWh price.
📊 Benchmark Lab
Benchmarking needs a reachable ollama endpoint. Set COPILOT_OLLAMA_URL (and keep BENCH_ENABLED on), then reopen this tab.
📊 Benchmark Lab — measure what actually fits & how fast, then keep the result
Pick models and context sizes; the Lab loads each one, sweeps the context ladder and records tokens/sec, the VRAM↔RAM split, the largest context that still fits in VRAM, and the power it burned. Results are stored so you only re-run when something changes. This actively loads models and runs a short generation on your GPU.
📊 Results
Click a column to sort, a row to see its context sweep below, or tick rows to overlay them in Compare. Re-run stores a fresh row so you can track changes over time.
📈 Context sweep
🆚 Compare
— overlay runs to compare setups & models on one chartTick two or more rows in the table to overlay their tokens/sec and VRAM across context — e.g. the same model on the P2000 vs the 3090.
📊 No benchmarks yet
Select one or more models above and hit Run benchmark. Each run takes roughly a model-load plus a few seconds per context size. Results land in a sortable, filterable table you can re-run or delete.
📦 Docker containers
| Container | State | Image | Ports | Uptime | RAM | VRAM | Disk | Status | Controls |
|---|
🧩 systemd services
Push notifications when something noteworthy happens. Configured here — no env vars, no config files. Any channel (Discord, ntfy, or Telegram) can be used; all are optional. Alerts are edge-triggered (one ping per state change) so they don't spam.
https://ntfy.sh. Self-hosted ntfy works too.chat.id from getUpdates.{level, title, detail, host} — works with Teams, Gotify, n8n…Triggers: container unhealthy/exited non-zero/dead, systemd unit failed,
GPU VRAM pressure (free < PRESSURE_FREE_MB), GPU OOM events, and disks crossing the threshold above.
📋 Routing rules
Per-service rules control which channels receive which alerts.
If no rule matches, the default (all configured channels) applies.
Wildcards (*, ?) work in the pattern column.
| Kind | Pattern | Channel | Min level | On |
|---|
📰 Daily brief
A scheduled “is the lab OK?” digest — the calm counterpart to alerts. Sent once a day to one channel: email gets the full HTML report, chat channels get a compact summary with the things that need attention.
Only channels you've configured above appear here — configure one and it shows up automatically.
Settings here save automatically when you leave a field. Preview and Send test use your saved settings.
Public status page
A shareable, read-only status page for the checks you mark public no auth, no host internals leaked.
Set your electricity price so the dashboard can turn power into money on the 💰 Costs page. Don't know your rates? Pick your country for a typical, editable estimate.
Powers the 💰 Costs page and the Power & cost cards from power history. Day & Night bills each sample at the night rate inside the window (it may cross midnight) and the day rate otherwise — leave the night price blank to use the single average. Leave the price blank to hide the cost cards.
Push run/session data from Jupyter, Colab or Kaggle (or mirror MLflow) — each run comes back priced with the real GPU energy it used. Writes need the API key; the dashboard reads are open on your LAN.
| Name | Key | Created | Expires | Last used | Runs |
|---|
import homelab_run as homelab
homelab.configure(url="http://THIS-HOST:9800", key="hlm_…")
with homelab.run("my-finetune", params={"lr":2e-4}) as r:
for step, loss in enumerate(train()):
r.log_metric("loss", loss, step=step)
r.log_metric("tokens_per_sec", batch_tokens / step_seconds, step=step)
url at a Tailscale/ngrok address that reaches this hub.General system settings. Changes take effect immediately — no restart required.
How many days of metric history to keep. Older rows are pruned every ~6 minutes. Default: 180.
The hub fetches each icon once and keeps it under its data volume — your browser never talks to the icon CDN, and the icons keep working offline. Off falls back to the marks bundled in this page.
How often the GPU tab and the Overview cockpit's live numbers refresh for this hub. Lower is snappier but reads the GPU/CPU a bit more often; it never goes faster than the sample interval allows. Remote hosts are polled over SSH at the sample interval (SAMPLE_INTERVAL, 10s by default), each on its own clock — a slow host never delays the others.
Servers that aren't auto-discovered — a vLLM, llama.cpp, LM Studio or Ollama on another box, or on a non-standard port. Add one and its models appear in the AI Models tab under the host it runs on and in the installed-models registry. The hub probes it — Runs on only picks where its models show. Read-only: the monitor never pulls, loads or removes models.
💾 Backup & Restore
Export your SQLite history, events, alert settings, and host registry — or restore a snapshot after a container recreate or disk move.
SSH keys under /data/.ssh are not included; back those up separately if needed.
Restore replaces all current database contents with the uploaded file.
A safety copy of the previous database is kept alongside it as *.pre-restore-*.bak.
🌐 Hosts
Monitor your other machines from this hub — agentless, read-only, over SSH. Three quick steps: authorize the hub's key on a machine, add it here, then Test.
loading…
🖥️ System
🩺 Setup & requirements
| Requirement | Status | Detail |
|---|
🧠 Top processes
🧠 Memory map — containers & services
🖥️ CPU, RAM & load
💾 Disk I/O Throughput
Live per-device throughput, utilisation and average op-latency, with a 6h trend sparkline per device. Read-only — nothing here touches your disks.
📶 Throughput
📊 Top talkers — containers
| Container | In | Out | Total |
|---|
Total bytes each container moved over the selected range (its own network namespace).
🌐 Network
🛡️ Security
Read-only, agentless — no changes are made to any host. Items shown in grey (⚪) couldn't be read without elevated privileges on that machine.
🛰️ Uptime checks
Monitor any HTTP endpoint or TCP port from inside this container — your own services, a NAS, a remote site. No extra uptime service to self-host — it's already here. Down/recovery alerts reuse your configured channels. Targets stay private to this dashboard — they never reach the public status page.