Skip to content
jagbhandalPublic

About

Live homelab dashboard: real Prometheus & cAdvisor metrics + 42 service integrations on a drag-and-resize grid. Self-hosted, Docker, MIT — not just bookmarks.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

751 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JagHelm

JagHelm

Live data, not just links.
A self-hosted homelab dashboard that reads real Prometheus & cAdvisor metrics, service health, and
42 app integrations that call your services — behind a layout you drag and resize yourself.

License Node React Docker GHCR

JagHelm — live homelab dashboard with real Prometheus metrics and 42 service integrations on a drag-and-resize grid

Try it in 10 seconds — no Prometheus needed

JagHelm ships a self-contained read-only demo (canned data, every write refused — no backend, no config). Kick the tyres before wiring up your stack:

docker run --rm -e DEMO_MODE=true -p 3099:3099 ghcr.io/jagbhandal/jaghelm:latest

Then open http://localhost:3099, drag a panel around, flip a theme. Like it? ⭐ Star the repo and point it at your real stack.

Built in the open · MIT · signed container images · 1,000+ automated tests · 0 direct-dependency vulnerabilities.

Why JagHelm

Most self-hosted dashboards are link launchers — a grid of bookmarks with a status dot. JagHelm starts from the other end: it pulls live numbers off your existing monitoring stack and the apps themselves, then lets you arrange that data however you like.

  • Real metrics, not pings. CPU, RAM, disk, temperature and uptime per node come straight from Prometheus + node_exporter; per-container CPU/MEM/network comes from cAdvisor. These are the same time-series your Grafana reads — not a reachability check.
  • 42 integrations that call your services. AdGuard queries blocked, Sonarr queue, Proxmox node load, NPM proxy count, and 38 more — each preset knows the endpoint, auth shape, and formatting, so a card shows the actual number, not a link to go find it.
  • A grid you actually arrange. A custom drag-resize layout engine (HelmGrid) — panels snap, auto-grow to fit content, and push each other on overlap.

JagHelm vs Homepage vs Dashy

A rough comparison of where JagHelm sits. Homepage and Dashy are excellent, more mature projects with bigger communities — if JagHelm doesn't fit, one of them probably will. The point of this table is positioning, not a scoreboard.

JagHelm Homepage Dashy
Primary model Live infra metrics + integrations Links + widgets Links + status
Node metrics (CPU/RAM/disk/temp) ✅ via Prometheus + node_exporter Partial (widgets) ❌
Per-container stats (cAdvisor) ✅ ❌ ❌
App integrations 42 presets + custom builder Many widgets Status checks + some widgets
Layout Drag-resize grid (snap/auto-grow) Config-defined columns Config-defined sections
Config UI and YAML/JSON on disk YAML files YAML / UI editor
Auth Single-user (built-in or proxy) Proxy-oriented Multiple options
Maturity Single-maintainer hobby project Large, mature Large, mature

JagHelm's trade-off is explicit: it leans on a Prometheus stack you already run (a real dependency, see KNOWN-ISSUES.md) in exchange for genuinely live data rather than bookmarks.

What it is

JagHelm is a single-page dashboard you point at your homelab. It reads metrics from Prometheus, container stats from cAdvisor, and health checks from Uptime Kuma, then renders them as draggable cards in a layout you arrange yourself. Settings live in the UI — themes, layouts, integrations, secrets — backed by YAML on disk so nothing gets lost on a container rebuild.

It started as a personal project and is shared in the hope that other homelab folks will find it useful. The core flow: install once, point at your existing monitoring stack, drag panels around until you like them, walk away.

There's also a native Android app (Capacitor): the same board on your phone over your tailnet, plus push notifications the moment a service, host, UPS, or cron job changes state — so you hear about an outage without a tab open.

What it isn't

  • Not a bookmark launcher. There is a Quick Launch section, but the focus is live data, not links.
  • Not a monitoring backend. Prometheus and Uptime Kuma do that work; JagHelm visualises what they collect.
  • Not multi-tenant. Single-user authentication, single-user config. Designed for an individual homelab, not a team.

Quick start

For a longer walkthrough — including standing up Prometheus and cAdvisor if you don't already run them — see docs/GET-STARTED.md.

Requirements

  • Docker + docker compose
  • Prometheus reachable on the network, with node_exporter on each node you want to monitor
  • (Optional but recommended) cAdvisor for container-level CPU/RAM/network stats
  • (Optional) Uptime Kuma for service health
  • (Optional) NUT exporter if you want UPS panels

1. Create .env

mkdir -p /opt/stacks/jaghelm && cd /opt/stacks/jaghelm
# ── JagHelm Configuration ──
# Required: where to read metrics from
PROMETHEUS_URL=http://your-prometheus:9090
KUMA_URL=http://your-kuma:3001

# Optional: Uptime Kuma API key — reads all monitors + uptime from Kuma's
# authenticated /metrics endpoint (needs Kuma >= 2.1.0). Blank = public status page.
KUMA_API_KEY=
 
# Required: encryption key for stored credentials
# Generate once: openssl rand -hex 32
DASH_SECRET=replace-with-output-of-openssl-rand-hex-32
 
# Optional: leave DASH_PASS empty to disable login entirely
DASH_USER=admin
DASH_PASS=
 
# Optional: reverse proxy IPs to trust X-Forwarded-For from
# Comma-separated. Leave blank if exposing JagHelm directly.
TRUST_PROXY=
 
# Optional: shared secret for cron-job report endpoint
# Generate once: openssl rand -hex 32
JAGHELM_CRON_SECRET=

2. Create compose.yaml

services:
  jaghelm:
    image: ghcr.io/jagbhandal/jaghelm:latest
    container_name: jaghelm
    restart: unless-stopped
    network_mode: host        # binds 3099 on the host; reaches LAN services directly
    env_file:
      - .env
    volumes:
      - ./data:/app/data        # config + encrypted secrets
      - ./uploads:/app/uploads  # logo + background images
    environment:
      - NODE_ENV=production

This is the shipped default: network_mode: host lets JagHelm reach your exporters and LAN apps directly. Prefer an isolated bridge network? Drop network_mode: host and publish the port instead:

    # ports:
    #   - 3099:3099

3. Pull and start

docker compose up -d

Open http://your-host:3099. JagHelm will discover nodes from Prometheus on first boot and render an initial layout. Settings → Integrations to wire up app-specific cards.

Configuration

Most things are configurable from the Settings UI (sidebar nav, 13 sections). For people who prefer files, everything is on disk too:

data/
├── services.yaml          # nodes, services, integrations
├── display-config.json    # theme, layout, sections, links
├── secrets.json           # AES-256-GCM encrypted credentials
├── auth.json              # password hash (if changed via UI)
├── cron-jobs.json         # cron job execution history
└── todos.json             # checklist data

services.yaml is hot-reloaded — edit it on disk and JagHelm picks up the change without restarting.

Environment variables

The .env example above covers the required + commonly used vars. There's also a power-user escape hatch — every preset integration can be configured via env vars instead of the UI:

# Prefixed with JAGHELM_ to avoid colliding with service env vars in
# shared Docker networks. UI/yaml config is overridden when set.
JAGHELM_ADGUARD_URL=http://192.168.x.x:8085
JAGHELM_ADGUARD_USER=admin
JAGHELM_ADGUARD_PASS=secret
 
JAGHELM_NPM_URL=http://192.168.x.x:81
JAGHELM_GITEA_TOKEN=...

See env.example for the full list.

Cron job reporting

Jobs report with POST /api/cron/report. secret must match JAGHELM_CRON_SECRET; node, job and status (success or failure) are required; duration_seconds, schedule and error are optional. expected_every_seconds is also optional: an integer from 60 to 2678400, or a digit string. Anything else returns 400 and the report is rejected.

{ "secret": "...", "node": "nas", "job": "backup", "status": "success", "expected_every_seconds": 86400 }

GET /api/cron/status reports overdue and seconds_since_report for every job (seconds_since_report is null if a run has no timestamp), and expected_every_seconds only for jobs that declared one. A job is overdue when it has not reported within the interval plus max(25% of the interval, 10 minutes). DELETE /api/cron/jobs/:node/:job (session auth, URL-encode both segments) removes a job and its history.

Features

Multi-node infrastructure monitoring

Real-time CPU, RAM, disk, temperature, and uptime per node, pulled from Prometheus. Nodes auto-discovered from labels on first boot — no manual config to add a new host.

Per-container resource stats

CPU, memory, network RX/TX for every Docker container via cAdvisor. Service cards show running/down state, ping latency, and 24-hour uptime alongside the resource numbers.

42 integration presets + a custom builder

Connect AdGuard, Plex, Sonarr, Proxmox, Cloudflare, Vaultwarden, and 36 others through the Settings → Integrations gallery. Each preset has known endpoints, auth shape, and field formatting baked in. Test-before-save catches misconfiguration before credentials hit disk. Custom integrations available for anything not in the gallery — point it at a JSON endpoint, pick paths to extract, save.

Credentials are encrypted with AES-256-GCM (PBKDF2-derived key from DASH_SECRET) before being written to secrets.json.

Embedded service tabs

Add your existing monitoring tools as iframe tabs in the top nav — Grafana, Uptime Kuma, Portainer, Proxmox, anything web-accessible. They render inside JagHelm rather than opening new browser tabs. Configurable per tab from Settings.

HelmGrid layout engine

Custom drag-resize grid built for this app. Panels auto-grow to fit content, snap to grid on drag, push each other down on overlap. Column count is configurable (6–24); panels reposition when you change density. Resize handles on SE and SW corners. Mobile breakpoint stacks everything into a single column.

Themes and typography

Ten themes (six dark, four light) inspired by common editor schemes — One Dark Pro, Dracula, GitHub Dark, Catppuccin, Solarized, etc. Five font family presets and eight independent size sliders so you can tune readability for whatever screen JagHelm lives on.

PWA installable

manifest.json and a service worker make JagHelm installable to a phone or tablet home screen. Useful if you have a wall-mounted dashboard or just want it as a "real app" on mobile.

UPS power monitoring

If you run NUT with the Prometheus exporter, JagHelm shows battery percentage, runtime, and load in a dedicated panel.

UI configuration with file escape hatch

Settings UI handles the day-to-day work — themes, layouts, integration setup, password change, links, tabs. For the things you'd rather automate or template, everything lives in YAML/JSON on disk.

Android app

The Android app is a signed APK attached to each Android release. On first launch it asks for your JagHelm server's address (a LAN address, a Tailscale address, or an https:// domain) and your JagHelm login, and stores them on the device; it is not tied to any particular server.

Push notifications are tied to the Firebase project an APK is built with. The published APK receives notifications only from servers that hold that project's credentials, so against your own server it works as a dashboard without notifications. To get notifications from your own server, build the APK with your own Firebase project: fork the repository, add the signing and Firebase secrets, and tag a release (see docs/mobile/PUSH-SETUP.md and docs/mobile/KEYSTORE.md).

Architecture

┌─────────────────────────────────────────────────────┐
│                  Settings UI / Dashboard             │
│   General · Appearance · Layout · Integrations · …   │
└────────────────────────┬────────────────────────────┘
                         │
┌────────────────────────▼────────────────────────────┐
│                   Express Server                     │
│                                                      │
│  ┌──────────┐  ┌───────────┐  ┌──────────────────┐  │
│  │ Config   │  │ Discovery │  │ Integration      │  │
│  │ services.│  │ Prometheus│  │ 42 presets +     │  │
│  │ yaml     │  │ cAdvisor  │  │ custom builder   │  │
│  └──────────┘  │ Kuma      │  │                  │  │
│                └───────────┘  └──────────────────┘  │
│  ┌──────────────────────────────────────────────┐    │
│  │   Secrets (AES-256-GCM via DASH_SECRET)      │    │
│  └──────────────────────────────────────────────┘    │
└────────┬─────────────┬──────────────┬───────────────┘
         │             │              │
   ┌──────────┐  ┌───────────┐  ┌──────────────┐
   │Prometheus│  │Uptime Kuma│  │ App APIs     │
   │+exporters│  │ monitors  │  │ AdGuard, NPM,│
   │          │  │           │  │ Sonarr, …    │
   └──────────┘  └───────────┘  └──────────────┘

Stack

  • Frontend: React 19, Vite 8 (Rolldown), HelmGrid (custom layout engine), @dnd-kit, react-colorful
  • Backend: Express, undici, helmet, multer, js-yaml, dotenv
  • Container: Node 22 Alpine, runs as non-root, healthcheck via native fetch
  • Encryption: AES-256-GCM with PBKDF2 (100k iterations); scrypt for password hashing
  • Monitoring sources: Prometheus, cAdvisor, node_exporter, NUT exporter, Uptime Kuma For deeper architecture detail (server module structure, refresh pipeline, integration lifecycle), see docs/ARCHITECTURE.md.

Releases

Server releases are published as signed container images (ghcr.io/jagbhandal/jaghelm:<version>) and Android releases as signed APKs, both on the GitHub Releases page. Release notes come from CHANGELOG.md and mobile/CHANGELOG.md. How releases are cut is described in docs/RELEASING.md.

Status

This is a single-maintainer hobby project, used daily for my own homelab. No SLA, no roadmap commitments. Issues and PRs are welcome but I respond when I have time. Known gaps and intentional deferrals are tracked in KNOWN-ISSUES.md.

If you're considering using JagHelm in a production-adjacent context — sharing a dashboard with non-technical users, exposing it on the public internet, etc. — read KNOWN-ISSUES first.

Acknowledgments

JagHelm leans on a number of well-maintained open-source projects.

Core dependencies

Package Author(s) Used for License
React Meta UI framework MIT
Vite Evan You & contributors Build tool & dev server MIT
Express TJ Holowaychuk & community API server MIT
undici Node.js team HTTP client + per-request TLS dispatch MIT
helmet Adam Baldwin et al. HTTP security headers MIT
@dnd-kit Claudéric Demers Service card drag-and-drop MIT
react-colorful Vlad Shilov Color picker in settings MIT
js-yaml Nodeca YAML config parsing MIT
multer Express community File upload handling MIT
dotenv Scott Motte .env loading BSD-2-Clause

Icons

Searchable picker draws from three community-maintained collections:

Collection Maintainers License
Dashboard Icons walkxcode & contributors MIT
selfh.st icons Ethan Ham (selfh.st) MIT
Simple Icons Simple Icons collective CC0 1.0

Inspiration

The self-hosted dashboard space has a lot of good options — Homepage, Homarr, Glance, Heimdall, Dashy — and JagHelm took ideas from several of them. If JagHelm doesn't fit your needs, one of those probably will.

License

MIT.

About

Live homelab dashboard: real Prometheus & cAdvisor metrics + 42 service integrations on a drag-and-resize grid. Self-hosted, Docker, MIT — not just bookmarks.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages