GPU monitoring dashboard for multi-server clusters, built with Next.js 14, Ant Design, and Redis. It fetches real-time GPU metrics from agents, aggregates them via a proxy API, and renders per-server and per-GPU charts with process tables.
| Light | Dark |
|---|---|
![]() |
![]() |
Features:
- Email verification login with JWT (optional, can be disabled)
- Redis-backed verification codes
- Access info logging (CSV)
- Proxy API to fetch multiple server statuses securely
- Responsive UI with dark mode support and smooth charts
- Dockerized production build (Next.js standalone)
- Node.js 18+ (dev) or Docker (prod)
- Redis (local or remote)
- SMTP account (if login is enabled)
- GPU agent running on your servers and exposing a status endpoint
Agent reference: run the agent first and configure SERVERS to point to it.
- Copy environment file
.env.exampleto.env.localfor dev and edit values - Install dependencies and run
npm install
npm run devNotes:
- Prefix
NEXT_PUBLIC_variables are exposed to the browser. - Booleans must be the string
trueorfalse. - Lists are comma-separated without spaces.
Core UI (public):
NEXT_PUBLIC_SITE_TITLE– Site title. Default: "GPU Dashboard"NEXT_PUBLIC_SITE_DESCRIPTION– Meta descriptionNEXT_PUBLIC_NO_NEED_LOGIN– Iftrue, disables login and middleware authNEXT_PUBLIC_SERVERS_ID– Comma-separated server IDs shown on homepage (e.g.,s1,s2)NEXT_PUBLIC_CUSTOM_ELEMENTS– JSON array for custom top-of-page elements. See CUSTOM_ELEMENTS_GUIDE.md for details.NEXT_PUBLIC_CHART_DATA_LENGTH– Samples kept in charts (default 200)
Authentication:
JWT_SECRET– Secret for signing/verifying JWT tokensTOKEN– Optional simple token. If cookieauth_tokenequals this value, middleware bypasses JWT verification (useful for reverse-proxy auth)DEVOPS– Contact shown in error messagesALLOWED_EMAILS– Allowlist emails (comma-separated). Empty means all emails allowed
Server configuration:
SERVERS– JSON string mapping server IDs to{ url, token }. Example (single line):{"s1":{"url":"http://s1.example.com/status?process=C","token":"123456"},"s2":{"url":"http://s2.example.com/status?process=C","token":"abcdef"}}The token is sent asAuthorizationheader if provided.
Email (SMTP) for verification codes:
SMTP_HOST,SMTP_PORT(587 or 465),SMTP_SECURE(false for 587, true for 465)SMTP_USER,SMTP_PASSIfNEXT_PUBLIC_NO_NEED_LOGIN=true, SMTP settings aren’t required.
Redis and logging:
REDIS_URL– e.g.,redis://localhost:6379orrediss://:<password>@host:portACCESS_LOG_PATH– CSV path for access logs (defaultdata/log/access.csv)TZ– Server timezone for timestamps (e.g.,Asia/Shanghai)
There are two options:
- Docker Compose (recommended)
- Edit
.envanddocker-compose.ymlif needed - Mounts
./data/logand./data/redis
docker compose up -d- Build image locally
docker build -t nvidia-smi-web-dashboard .
docker run --name gpu-dashboard -p 3000:3000 \
--env-file .env \
-e REDIS_URL=redis://host.docker.internal:6379 \
-v $(pwd)/data/log:/app/data/log \
-v /etc/localtime:/etc/localtime:ro \
nvidia-smi-web-dashboardThe provided Dockerfile uses Next.js standalone output and starts with node server.js from the .next/standalone bundle.
If you mount an executable script named pre-run.sh into the container at /app, it will be executed right before the app starts. This is useful for preparing tunnels, fetching secrets, warming caches, or any environment bootstrap you need.
- Entrypoint behavior: the container runs
sh ./pre-run.shif the file exists, then startsnode server.js. - Sample script: see
pre-run.example.shfor an example that installsopenssh-client(on Alpine) and creates SSH local port-forwarding tunnels.
Examples:
- Docker run
docker run --name gpu-dashboard -p 3000:3000 \
--env-file .env \
-e REDIS_URL=redis://host.docker.internal:6379 \
-v $(pwd)/data/log:/app/data/log \
-v $(pwd)/pre-run.sh:/app/pre-run.sh:ro \
-v $(HOME)/.ssh:/root/.ssh:ro \
-v /etc/localtime:/etc/localtime:ro \
nvidia-smi-web-dashboard- Docker Compose
services:
dashboard:
image: do1e/nvidia-smi-web-dashboard
# ...other options
volumes:
- ./pre-run.sh:/app/pre-run.sh:ro
- ~/.ssh:/root/.ssh:ro
# ...other optionsNotes:
- Ensure
pre-run.shis executable (chmod +x pre-run.sh) or invoke withshinside the file. The entrypoint usessh ./pre-run.shso an executable bit is not strictly required, but keeping it executable is a good practice. - The base image is Alpine; if your pre-run requires packages, use
apk add --no-cache <pkg>or vendor the binaries in your script. - Long-running background tasks in
pre-run.shshould be started with&so the main process can continue tonode server.js.
app/
api/
access/route.ts # Record access to CSV (JWT required unless disabled)
auth/login/route.ts # Verify email+code -> issue JWT
auth/send-code/route.ts # Send verification code via SMTP
proxy/route.ts # Server-side proxy to fetch data from agents
components/ # Per-server panels, per-GPU charts, tables, custom elements
login/page.tsx # Email code login page
page.tsx # Homepage listing servers and charts
lib/
accessLog.ts # CSV appender with timezone handling
redis.ts # Redis client and verification record helpers
middleware.ts # Route protection & auth cookie check
docker-compose.yml # Compose setup with Redis
dockerfile # Multi-stage build for production
-
POST
/api/auth/send-code- Body:
{ email: string } - Sends a 6-digit code; rate-limited by Redis record (10 min expiry, 1 min cooldown)
- Body:
-
POST
/api/auth/login- Body:
{ email: string, code: string } - Validates code, returns
{ token }(JWT, 30d expiry). Frontend stores inauth_tokencookie
- Body:
-
POST
/api/access- Headers: Cookie
auth_token - Appends a CSV line:
email,access_time,ip_address
- Headers: Cookie
-
POST
/api/proxy- Body:
{ serverId: string | string[] } - Server-side fetch from
SERVERS[serverId].urlwith optionalAuthorizationheader - Returns agent JSON or error code
- Body:
- Never commit real SMTP credentials, JWT secrets, or
SERVERS - Keep
NEXT_PUBLIC_NO_NEED_LOGIN=falseand configure SMTP &ALLOWED_EMAILSif don't want to expose publicly - Optionally set
TOKENwhen your reverse proxy injects a fixed trusted cookie value
Apache 2.0 License
Feel free to open issues or PRs for enhancements.

