Skip to content

About

A production-ready, single-server telemetry platform for monitoring GPU rigs running AI/ML workloads.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,268 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🖥️ GPU Rig Monitoring Platform

Python Django PostgreSQL HTMX License Build Status

A production-ready, single-server telemetry platform for monitoring GPU rigs running AI/ML workloads. Collects hardware metrics from remote agents and displays them in a real-time, server-rendered web dashboard with zero JavaScript frameworks.

image image image

🎯 Overview

Metric Value
Architecture Single VPS (Django + Gunicorn + Nginx + PostgreSQL)
Agents Linux (cron) & Windows (Task Scheduler)
Agent version v1.9.1 (Linux) / v1.9.1-win (Windows) — schema 1.14
Collection Interval 60 seconds
Scale Target 1,000+ rigs
Data Retention 31 days (3-tier compaction: 1m → 15m → 1h)
Storage/rig (31d) ~28 MB (94% compression)

✨ Key Features

📊 Live Dashboard

  • Fleet Overview — All rigs at a glance with per-GPU summaries, tag filtering, status badges
  • Live Metrics — Auto-refreshing cards (30s HTMX polling): CPU, Memory, GPU, Storage, Network, Docker, Errors, Top Processes
  • Historical Charts — 15+ multi-series time-range charts (24h/7d/30d): GPU temp/util/memory/power/clocks, CPU temp/util/freq, Storage, Network, Error frequency

🖥️ Hardware Coverage

Category Metrics Linux Windows
CPU Model, cores, load avg, temp, utilization %, frequency ✅ ✅
Memory Total, used, free, cached, swap ✅ ✅
GPU Model, VRAM (used/free/total), util %, temp, power, fan, PCIe, clocks ✅ ✅
GPU Processes Name, type (C/G/C+G), memory ✅ ✅
Storage Capacity, usage %, SMART, NVMe logs, temp, read/write bytes/IOPS, utilization ✅ ✅
Network Per-interface IPv4, speed, RX/TX bytes, errors ✅ ✅
Docker Count, names, images, status, container ID, uptime ✅ ✅
Top Processes Top 20 by CPU/memory (pid, name, cpu%, mem%, user, cmdline) ✅ ✅
Errors System errors with deduplication (1000-entry rolling buffer) ✅ ✅

🔐 Security & Operations

  • Per-rig rate limiting — 2 req/min per rig_uuid (burst=5)
  • Timestamp validation — Rejects payloads >5 min future or >1 hour past
  • Dual authentication — X-API-Key (user) + X-Rig-UUID (rig identification)
  • Agent isolation — API keys scoped to user; no cross-user rig access
  • API Key Management — Create, revoke, reactivate, delete, transfer between users (admin)

📈 Reports & Identity Tracking

  • Report Card (htmx_report) — 24h/7d/30d GPU metrics with identity change tracking (current UUID from LatestSnapshot.gpu_uuids_json, not historical raw scan). Detects GPU replacement per gpu_index.
  • GPU Identity Changes — Audit subsection: before/after UUID/model transition cards (BEFORE/AFTER grid), full UUID comparison expandable (<details>), change timestamp with timesince, change count badge.
  • Compaction Defense (W001/W004/0052): gpumetric.gpu_uuid preserved through tiers (static_fields); bool max uses CAST(... AS INTEGER); grouping test verifies identity preservation.

🏗️ Architecture

┌────────────────────────────────────────────────────────────────────────────────────┐
│                           RIG FLEET (Untrusted, N rigs)                            │
│                                                                                    │
│  ┌──────────────────────────────────────────────────────────────────────────────┐  │
│  │  METRICS INGESTION PATH (cron ~60s)                                          │  │
│  │                                                                              │  │
│  │  ┌────────────────────┐         ┌────────────────────┐                       │  │
│  │  │ Linux Agent        │         │ Windows Agent      │                       │  │
│  │  │ agent/run.py       │         │ agent_windows/     │                       │  │
│  │  │ v1.9.1, schema 1.14│         │ run.py v1.9.1-win  │                       │  │
│  │  └─────────┬──────────┘         └─────────┬──────────┘                       │  │
│  │            │                              │                                  │  │
│  │            │ HTTPS POST                   │ HTTPS POST                       │  │
│  │            │ /api/v1/ingest/              │ /api/v1/ingest/                  │  │
│  │            │ X-API-Key, X-Rig-UUID        │ X-API-Key, X-Rig-UUID            │  │
│  │            └──────────────┬───────────────┘                                  │  │
│  │                           │                                                  │  │
│  │                           ▼                                                  │  │
│  │                    ┌──────────────┐                                          │  │
│  │                    │   Nginx      │                                          │  │
│  │                    │   (Server)   │                                          │  │
│  │                    └──────────────┘                                          │  │
│  └──────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                    │
│  ┌──────────────────────────────────────────────────────────────────────────────┐  │
│  │  UPDATE CHECK (cron ~daily, independent)                                     │  │
│  │  ┌────────────────────────────────────────────────────────────────────────┐  │  │
│  │  │ check_update.py                                                        │  │  │
│  │  │ • Queries monitoring server for latest agent version                   │  │  │
│  │  │   {server_endpoint}/agent/run.py                                       │  │  │
│  │  │ • Triggers self-update if newer version available                      │  │  │
│  │  │ • Completely outbound, NOT in ingest path                              │  │  │
│  │  └────────────────────────────────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                    │
│                              ┌────────────────────┐                                │
│                              │  Monitoring Server │                                │
│                              │   (nginx :80/443)  │                                │
│                              └────────────────────┘                                │
│                                    ▲                                               │
│                                    │ HTTPS GET (outbound)                          │
│                                    │ check_update.py → Server                      │
│                                                                                    │
└────────────────────────────────────────────────────────────────────────────────────┘
                                            │
                                            │ HTTPS :443 (TLS terminated)
                                            │ Rate limits: zone=rig burst=3, zone=ip burst=50
                                            │ client_max_body_size: 2m
                                            │ /static/ → staticfiles
                                            ▼
┌────────────────────────────────────────────────────────────────────────────────────────┐
│                        SINGLE UBUNTU VPS (Trusted, /opt/gpu_monitor)                   │
│                                                                                        │
│  ┌──────────────────────────────────────────────────────────────────────────────────┐  │
│  │                              NGINX (Reverse Proxy)                               │  │
│  │  • TLS termination (:80 → :443 redirect)                                         │  │
│  │  • Rate limiting per rig + per IP                                                │  │
│  │  • Static file serving                                                           │  │
│  └──────────────────────────────────────────────────────────────────────────────────┘  │
│                                      │                                                 │
│                                      │ proxy_pass http://127.0.0.1:8000                │
│                                      ▼                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │                         DJANGO + DRF (Gunicorn 4w, systemd)                     │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ INGESTION LAYER                                                          │   │   │
│  │  │ • IngestView POST /api/v1/ingest/                                        │   │   │
│  │  │   - X-API-Key auth + IngestRateThrottle (2/min/rig)                      │   │   │
│  │  │   - Timestamp sanity: ±5min future / 1h past                             │   │   │
│  │  │   - Auto-enrolls unknown rigs                                            │   │   │
│  │  │ • serializers.process_ingest() [transaction.atomic()]                    │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ READ APIs (SessionAuth, rate-limited)                                    │   │   │
│  │  │ • ChartDataView GET /api/v1/rigs/{uuid}/chart-data/                      │   │   │
│  │  │   - 120/min/user, 55s cache                                              │   │   │
│  │  │ • GET /api/v1/rigs/{uuid}/metrics/                                       │   │   │
│  │  │ • GET /api/v1/health/ (open, no auth)                                    │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ HTMX DASHBOARD (@login_required + per-user rate_limit)                   │   │   │
│  │  │ • rig_list, rig_detail                                                   │   │   │
│  │  │ • htmx_metrics, htmx_status, htmx_report                                 │   │   │
│  │  │ • 30s polling via HTMX                                                   │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ ACCOUNTS & SECURITY                                                      │   │   │
│  │  │ • register/login/profile                                                 │   │   │
│  │  │ • ApiKey create/revoke/transfer                                          │   │   │
│  │  │ • electricity_rate_kwh configuration                                     │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ AUDIT & MAINTENANCE                                                      │   │   │
│  │  │ • Audit middleware + AuditLog feed                                       │   │   │
│  │  │ • Management commands:                                                   │   │   │
│  │  │   compact_data, cleanup_old_data, backfill_historical_data,              │   │   │
│  │  │   daily_maintenance, update_rig_status, cleanup_audit_log                │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│           │                          │                          │                      │
│           │ TCP/5432                 │ TCP/5432                 │ TCP/5432             │
│           ▼                          ▼                          ▼                      │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │                         POSTGRESQL 16 (db: gpu_monitor)                         │   │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │  │
│  │  │ TIMESERIES TABLES (high write volume, 31d retention)                     │   │  │
│  │  │ • MetricSnapshot  • GPUMetric       • StorageMetric                      │   │  │
│  │  │ • NetworkMetric   • RigStatusEvent                                       │   │  │
│  │  │   (GPUProcessMetric removed in migration 0047 — denormalized             │   │  │
│  │  │    into LatestSnapshot.gpu_processes_json)                                 │   │  │
│  │  │   (PowerReading removed in migration 0048 — power data lives in          │   │  │
│  │  │    MetricSnapshot.cpu_power_w/total_system_power_w + GPUMetric.power_draw_w)│   │  │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │  │
│  │                                                                                 │   │  │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │  │
│  │  │ LATEST STATE (1 row/rig, denormalized)                                   │   │  │
│  │  │ • LatestSnapshot (~77 JSON-array fields — incl. power, GPU processes)    │   │  │
│  │  │ • LatestDockerContainer                                                  │   │  │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │  │
│  │                                                                                 │   │
│  │  ┌──────────────────────────────────────────────────────────────────────────┐   │   │
│  │  │ CORE TABLES (relational, low churn)                                      │   │   │
│  │  │ • Rig • RigTag • User • ApiKey • AuditLog                                │   │   │
│  │  └──────────────────────────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                        │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │                              CRON (server-side)                                 │   │
│  │                                                                                 │   │
│  │  ┌────────────────────────────────┐    ┌────────────────────────────────────┐   │   │
│  │  │ */2 min:                       │    │ 03:00 daily:                       │   │   │
│  │  │ update_rig_status.sh           │    │ data_retention.sh                  │   │   │
│  │  │ → stale >2min, offline >10min  │    │ → compact_data                     │   │   │
│  │  │ → calls update_rig_status cmd  │    │ → cleanup_old_data(31d)            │   │   │
│  │  └────────────────────────────────┘    │ → VACUUM ANALYZE ×6 tables         │   │   │
│  │                                        │ → cleanup_audit_log(90d)           │   │   │
│  │                                        └────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                        │
└────────────────────────────────────────────────────────────────────────────────────────┘
                                            ▲
                                            │ HTTPS GET/POST + HTMX polling (30s)
                                            │ SessionAuth, per-user rate limits
                                            │
                              ┌─────────────┴─────────────┐
                              │      USER BROWSER         │
                              │  (authenticated session)  │
                              └───────────────────────────┘
flowchart LR
    subgraph Rigs["Rig machines (N rigs)"]
        A1["agent/run.py (Linux) v1.9.1 / schema 1.14"]
        A2["agent_windows/run.py v1.9.1-win / schema 1.14"]
        A3["check_update.py<br/>cron ~daily<br/>fetches run.py from server<br/>self-update if newer version"]
    end

    subgraph Edge["Server edge"]
        NG["Nginx :80/443<br/>client_max_body_size 2m<br/>limit_req zone=rig burst=3 / zone=ip burst=50<br/>/static/ from staticfiles<br/>/agent/run.py, /agent/check_update.py<br/>/agent_windows/run.py, /agent_windows/check_update.py"]
    end

    subgraph App["Django app (Gunicorn systemd, /opt/gpu_monitor)"]
        ING["metrics_app.IngestView<br/>POST /api/v1/ingest/<br/>X-API-Key auth + IngestRateThrottle 2/min/rig<br/>timestamp sanity ±5min future / 1h past<br/>auto-enrolls unknown rigs"]
        SER["serializers.process_ingest()<br/>transaction.atomic()"]
        CH["ChartDataView<br/>GET /api/v1/rigs/{uuid}/chart-data/<br/>SessionAuth, 120/min/user, 55s cache"]
        MET["GET /api/v1/rigs/{uuid}/metrics/"]
        HLTH["GET /api/v1/health/ (open)"]
        DASH["dashboard views (HTMX)<br/>rig_list / rig_detail / htmx_metrics / htmx_status / htmx_report<br/>@login_required + per-user rate_limit decorator"]
        ACC["accounts<br/>register/login/profile<br/>ApiKey create/revoke/transfer<br/>electricity_rate_kwh"]
        AUD["audit middleware + AuditLog feed"]
        CMD["mgmt commands<br/>compact_data · cleanup_old_data · backfill_historical_data<br/>daily_maintenance · update_rig_status · cleanup_audit_log"]
    end

    subgraph Data["PostgreSQL (db gpu_monitor)"]
        TS[("Timeseries<br/>MetricSnapshot · GPUMetric · StorageMetric<br/>NetworkMetric · RigStatusEvent<br/>(GPUProcessMetric + PowerReading removed in migrations 0047/0048)")]
        LS[("LatestSnapshot<br/>1 row/rig, ~77 JSON-array fields — incl. power, GPU processes")]
        LD[("LatestDockerContainer")]
        RG[("Rig · RigTag · User · ApiKey · AuditLog")]
    end

    subgraph Ops["Cron (server)"]
            C1["*/2 min<br/>update_rig_status.sh<br/>→ stale >2min, offline >10min<br/>→ calls update_rig_status cmd"]
            C2["03:00<br/>data_retention.sh<br/>compact_data → cleanup_old_data(31d)<br/>→ VACUUM ANALYZE ×6 tables<br/>→ cleanup_audit_log(90d)"]
        end

        A1 -->|"HTTPS POST /api/v1/ingest/<br/>X-API-Key, X-Rig-UUID"| NG
        A2 -->|"HTTPS POST /api/v1/ingest/<br/>X-API-Key, X-Rig-UUID"| NG
        A3 -.->|"HTTPS GET (outbound)<br/>fetch latest run.py from server"| NG
    
    NG --> ING --> SER
    SER --> TS
    SER --> LS
    SER --> LD
    SER --> RG
    NG --> CH --> TS
    NG --> MET --> LS
    NG --> DASH --> LS
    DASH --> RG
    ACC --> RG
    AUD --> RG
    C1 --> CMD
    C2 --> CMD
    CMD --> TS
Loading

Stack: Django 6.x + DRF · PostgreSQL 16 · Gunicorn (4 workers) · Nginx (TLS 1.3, rate limiting) · HTMX 1.9 (server-rendered, no SPA)


Quick Start

GPU Rig Monitoring Platform collects hardware telemetry from GPU rigs and displays live metrics, historical charts, rig status, and system errors in a web dashboard.

Choose the deployment option that matches your goal:

Deployment Best for Requirements
Production VPS Monitoring remote GPU rigs over the internet Ubuntu VPS, domain name, SSH access, HTTPS
Local deployment Testing the platform on a local Ubuntu machine or VM Ubuntu 24.04 LTS recommended; no public domain required

For production deployments, follow the full Production Deployment Guide. For local testing, follow the Local Deployment Guide.

1. How It Works

  1. The server receives telemetry from each rig through an authenticated HTTP API.
  2. PostgreSQL stores the collected metrics.
  3. The Django application serves the dashboard and API.
  4. Nginx handles incoming web requests and, in production, HTTPS.
  5. Each rig runs an agent that collects hardware metrics and submits them approximately every 60 seconds.
GPU Rig(s)
    │
    │ Monitoring agent — HTTPS in production
    ▼
Nginx → Django REST API → PostgreSQL
             │
             ▼
       Web Dashboard
             │
             ▼
       Your Browser

2. Production Deployment (Recommended)

Use this option if you want to monitor remote rigs through a public domain.

Prerequisites

  • An Ubuntu 22.04 or 24.04 LTS VPS with root SSH access for initial installation.
  • A domain name or subdomain, such as monitor.example.com.
  • An A record pointing the hostname to your VPS public IPv4 address.
  • Cloud firewall rules allowing inbound SSH, HTTP (port 80), and HTTPS (port 443).
  • The project source code on the VPS.

The deployment guide recommends a baseline of 4–8 vCPUs, 16–32 GB RAM, and NVMe storage. Actual requirements depend on the number of rigs, the volume of collected metrics, and your retention policy.

Install the server

Clone the public repository on the VPS:

git clone --depth 1 \
    https://github.com/dawmro/GPU-Rig-Monitoring-Platform.git \
    /tmp/GPU-Rig-Monitoring-Platform

Before installing, configure DNS and verify that the hostname resolves to the VPS. Make sure ports 80 and 443 are reachable through both the provider's cloud firewall and the server firewall.

Follow the Server Deployment section of the Production Deployment Guide for the exact file placement and installation commands. The included server installation script configures the core services, PostgreSQL, Gunicorn, Nginx, firewall rules, and Let's Encrypt TLS certificates.

After installation:

  1. Save the generated database credentials securely.
  2. Create an administrator account.
  3. Open https://monitor.example.com/ in your browser, replacing the example hostname with your own.
  4. Log in and create an API key for each rig or group of rigs according to your key-management policy.

Using Cloudflare: Cloudflare DNS and proxying can be used with a custom domain. Configure the origin TLS certificate and Cloudflare SSL/TLS mode consistently; Full (strict) is recommended when the origin has a valid certificate. Keep the origin firewall and proxy configuration aligned with your intended access model. See the production guide for certificate, firewall, and security details.

Verify the server

Replace the example hostname with your domain:

systemctl is-active gunicorn postgresql nginx

curl -s https://monitor.example.com/api/v1/health/

A successful health check should report a healthy application and a working database connection. If the check fails, consult the production guide's troubleshooting section before installing agents.

3. Install a GPU Rig Agent

Once the server is working, install an agent on each rig you want to monitor.

Requirements

  • Linux rig with Python 3.10 or newer.
  • NVIDIA driver and nvidia-smi available for NVIDIA GPU telemetry.
  • Network access to the monitoring server.
  • Administrator privileges for installation and required hardware-monitoring permissions.

Configure the agent

  1. Log in to the dashboard.
  2. Open API Keys and create a key.
  3. Copy the key immediately; it may only be displayed once.
  4. Install the agent by following the Agent README and the agent deployment section of the Production Deployment Guide.
  5. Edit /etc/monitoring-agent/config.yaml on the rig.

Example configuration:

rig_uuid: "auto"
rig_name: ""
api_key: "PASTE_YOUR_API_KEY_HERE"
server_endpoint: "https://monitor.example.com"
expected_gpu_count: 0
collection_timeout_s: 35
retry_attempts: 3
debug_mode: false

Replace the API key and server URL with your own values. Keep the API key secret and restrict access to the configuration file. Set expected_gpu_count to 0 for automatic detection or specify the expected number of GPUs.

Test the agent using the command from the agent deployment guide. A successful run should show that the payload was accepted by the server.

Verify telemetry

Open the fleet dashboard:

https://monitor.example.com/dashboard/rigs/

The rig should appear after its first successful report. Depending on the agent schedule, allow approximately two minutes for it to show up. The dashboard provides live metrics, historical charts, rig status, and system-error information.

Important: Configure the rig-status scheduled task on the server. Without it, rigs that stop reporting may continue to appear online. The production guide also covers data retention, log rotation, database backups, and certificate renewal.

4. Local Deployment (Testing)

To test the platform without a public domain or production TLS setup, use an Ubuntu machine or VM.

Start with the Local Deployment Guide, which covers:

  • Installing PostgreSQL and the required system packages.
  • Creating the database and configuring the Django environment.
  • Running migrations and collecting static files.
  • Configuring Gunicorn and Nginx for local access.
  • Creating an administrator account.
  • Installing an agent and sending test telemetry.

After completing the guide, open:

http://localhost/

Local testing is not a production security configuration. Do not expose a debug-enabled development deployment to the public internet. For a public service, use the production guide and its HTTPS, secret-management, permissions, and firewall configuration.

5. Troubleshooting

Symptom What to check
Dashboard is unavailable Check gunicorn, nginx, and postgresql service status.
502 Bad Gateway Inspect the Gunicorn error log and confirm the application can connect to PostgreSQL.
Health endpoint fails Check the application environment, database credentials, and server logs.
Agent reports 401 Unauthorized Confirm that the API key is correct and active.
Agent cannot connect Check the server URL, DNS, network connectivity, firewall rules, and TLS certificate.
Rig does not appear Check agent logs and confirm that the ingest request succeeded.
Rig remains online after stopping Check that the rig-status scheduled task is installed and running.

See the Production Deployment Guide and Local Deployment Guide for diagnostic commands and detailed fixes.

6. Documentation


📁 Repository Structure

GPU-Rig-Monitoring-Platform/
├── agent/                      # Linux monitoring agent
├── agent_windows/              # Windows monitoring agent
├── gpu_monitor/                # Django project
│   ├── deploy/                 # Production artifacts (nginx, systemd, cron)
│   ├── metrics_app/            # Ingestion API, timeseries models
│   ├── dashboard/              # HTMX views, templates, tab tags
│   ├── rigs/                   # Rig inventory + status state machine
│   ├── accounts/               # Auth, API keys, audit
│   ├── audit/                  # Activity feed
│   └── templates/              # Django templates
├── scripts/                    # Dev helpers (NOT deployed)
└── docs/                       # Architecture, deployment guides

Key distinction: gpu_monitor/deploy/ = production artifacts (cron, systemd, nginx). scripts/ = local dev helpers only (never deployed).


📚 Documentation

Guide Description
docs/DEPLOYMENT_GUIDE.md Production VPS deployment with TLS, domain, firewall
docs/LOCAL_DEPLOYMENT_GUIDE.md Local testing (no domain, HTTP only)
docs/GPU_Rig_Monitoring_Architecture.md Full architecture reference (1500+ lines)
agent/README.md Linux agent installation & config
agent_windows/README.md Windows agent setup

🛠️ Development Workflow

# 1. Make changes in workspace
# 2. Sync to /opt for testing
bash scripts/sync_to_opt.sh          # Full: rsync + migrate + restart
bash scripts/sync_to_opt.sh --no-migrate  # Fast: skip migrations

# 3. Verify, commit to feature branch
# 4. Push and create PR for review

📊 Data Retention (3-Tier Compaction)

Tier Age Bucket Rows/Day Savings
Raw 0–1 day 1-min 1,440 —
Tier 2 1–7 days 15-min 96 15×
Tier 3 7–31 days 1-hour 24 4×
Deleted 31+ days — 0 100%

Result: ~94% storage reduction (487 GB → 28 GB for 1000 rigs/month)


📋 Database Design Notes

The data model separates historical measurements from the latest known rig state and core application records.

Data group Purpose
MetricSnapshot Historical system-level measurements
GPUMetric Historical per-GPU measurements
StorageMetric Historical storage measurements
NetworkMetric Historical network measurements
RigStatusEvent Rig status history
LatestSnapshot Latest known rig state, including denormalized data
LatestDockerContainer Latest known Docker container state
Rig, RigTag Rig inventory and organization
User, ApiKey Authentication and access control
AuditLog Auditable application activity

Some high-frequency or cumulative values are stored in the latest-state representation rather than duplicated in historical tables. Consult the Django models and migrations for the authoritative schema.


📈 Charts and Dashboard Implementation

The dashboard uses server-rendered templates, HTMX requests, and JavaScript chart loaders.

Area Implementation focus
GPU charts Multi-GPU time series, GPU-index grouping, identity-aware labels
CPU load Load-average history
Memory and swap Memory and swap utilization over time
Network Traffic counters and error series
Storage Per-device capacity, I/O, and utilization
Job status Historical active-job state
Report card Historical summaries and GPU identity-change information

Implementation details, including loader names and data-compaction safeguards, may change as the dashboard evolves. Refer to the current chart-loader code and architecture documentation when extending these components.


🔧 Tech Stack

Layer Technology
Server Django 6.x + Django REST Framework
Database PostgreSQL 16 (plain, no TimescaleDB)
App Server Gunicorn (WSGI, 4 workers)
Web Server Nginx (reverse proxy, TLS 1.3)
Frontend Django Templates + HTMX 1.9 (no SPA)
Auth Email/password + API keys + sessions
Agents Python 3.10+, psutil, pynvml, WMI (Windows)
Scheduler Linux: cron · Windows: Task Scheduler

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/amazing-feature)
  3. Make changes, run sync_to_opt.sh to test
  4. Commit with conventional messages (feat:, fix:, docs:)
  5. Push and open a Pull Request

📄 License

MIT License — see LICENSE for details.


🙏 Acknowledgments

  • HTMX — making server-rendered apps feel alive
  • Django — the web framework for perfectionists
  • psutil — cross-platform system monitoring
  • pynvml — NVIDIA GPU monitoring

Built for GPU farmers, ML engineers, and anyone who needs to know what their rigs are doing.

About

A production-ready, single-server telemetry platform for monitoring GPU rigs running AI/ML workloads.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages