# Cockpit NVIDIA GPU Dashboard > Custom Cockpit package that displays live GPU stats (model, driver, CUDA > version, temperature, utilization, memory, processes) in the web UI sidebar > on port 9090. ## When to use - User wants GPU temperature / utilization / memory visible in Cockpit - User prefers a web UI over terminal `nvidia-smi` or `nvtop` ## Two approaches `cockpit.script()` (run nvidia-smi directly) **silently fails on some Cockpit versions** (Ubuntu 26+, Cockpit ~314+). The **systemd + file-read** approach is more reliable and preferred. --- ## Approach A (recommended): systemd service + file-read Write GPU data to files periodically via a background service, then read them from the Cockpit page with `cockpit.file().read()`. Avoids all PATH and permission issues with running nvidia-smi from the Cockpit bridge. ### 1. Create the data-collection script **`/usr/local/bin/nvidia-gpu-monitor.sh`:** ```bash #!/bin/bash while true; do nvidia-smi --query-gpu=name,driver_version,temperature.gpu,utilization.gpu,memory.used,memory.total,power.draw,pstate,fan.speed --format=csv,noheader,nounits 2>/dev/null | head -1 > /run/nvidia-gpu.txt nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv,noheader,nounits 2>/dev/null > /run/nvidia-processes.txt nvidia-smi 2>/dev/null | grep "CUDA Version" | sed 's/.*CUDA Version: //' | head -1 > /run/nvidia-cuda.txt sleep 5 done ``` Make executable: `sudo chmod +x /usr/local/bin/nvidia-gpu-monitor.sh` ### 2. Create systemd service **`/etc/systemd/system/nvidia-gpu-monitor.service`:** ```ini [Unit] Description=NVIDIA GPU Monitor - writes stats to /run After=nvidia-persistenced.service [Service] Type=simple ExecStart=/usr/local/bin/nvidia-gpu-monitor.sh Restart=always RestartSec=3 [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl daemon-reload sudo systemctl enable --now nvidia-gpu-monitor ``` ### 3. Create the Cockpit package **`/usr/share/cockpit/nvidia-gpu/manifest.json`:** ```json { "version": 1, "requires": { "cockpit": "260" }, "menu": { "index": { "label": "NVIDIA GPU", "order": 90 } }, "content-security-policy": "default-src 'self'; script-src 'unsafe-inline'" } ``` **`/usr/share/cockpit/nvidia-gpu/index.html`:** The page uses `cockpit.file(path).read()` to read `/run/nvidia-gpu.txt`, `/run/nvidia-processes.txt`, and `/run/nvidia-cuda.txt`. Each file contains a single line of comma-separated values written by the systemd service. Key implementation: ```javascript function readFile(path) { return cockpit.file(path).read(); } function update() { readFile('/run/nvidia-gpu.txt').done(function(data) { if (!data || !data.trim()) { /* show error */ return; } var parts = data.trim().split(', '); // parts[0] = name, [1] = driver, [2] = temp, [3] = util, // [4] = mem_used, [5] = mem_total, [6] = power, [7] = pstate, [8] = fan // ... render cards ... }); readFile('/run/nvidia-cuda.txt').done(function(d) { /* show CUDA version */ }); readFile('/run/nvidia-processes.txt').done(function(d) { /* render process table */ }); } setInterval(update, 5000); ``` ### 4. Install and restart Cockpit ```bash sudo mkdir -p /usr/share/cockpit/nvidia-gpu # Write manifest.json and index.html (use sudo tee or sudo cp) sudo chmod 644 /usr/share/cockpit/nvidia-gpu/* sudo systemctl restart cockpit ``` ### 5. Verify 1. Open `https://:9090` in browser 2. Log in with server credentials 3. Click **NVIDIA GPU** in sidebar — live metrics refresh every 5s --- ## Approach B (fallback): cockpit.script() directly Use when Approach A isn't practical (no systemd, containerized Cockpit, etc.): ```javascript cockpit.script("/usr/bin/nvidia-smi --query-gpu=... --format=csv,noheader,nounits", null, {superuser: 'try'}) .done(function(data) { /* parse and render */ }) .fail(function(err) { /* show error */ }); ``` **Caveats (why Approach A is preferred):** - `cockpit.script()` may silently hang on Cockpit v314+ (Ubuntu 26+) - PATH may not include `/usr/bin/` in non-interactive bridge sessions - The `.fail()` handler may catch but not always fire for certain errors - Debugging is harder — the error object from Cockpit bridge is opaque If using this approach, use the full path `/usr/bin/nvidia-smi` and avoid `{superuser: 'try'}` unless nvidia-smi requires root on the target system. --- ## Troubleshooting | Symptom | Likely Cause | Fix | |---------|-------------|-----| | "No NVIDIA GPU detected" | Can't read data files or run nvidia-smi | Check `/run/nvidia-gpu.txt` exists and is populated. Restart service: `sudo systemctl restart nvidia-gpu-monitor` | | Page shows stale data | systemd service stopped or crashed | `sudo systemctl status nvidia-gpu-monitor` — restart if dead | | Power shows `[N/A]` | GTX 1050 Ti doesn't report power draw | Normal — handle gracefully in display | | Page loads blank | CSP blocking inline script | Add `'unsafe-inline'` to manifest CSP | | "No GPU processes" when Immich is processing | Jobs may be between batches | Check `nvidia-smi` directly — should show python process | | Ctrl+Shift+R needed after updates | Cockpit aggressively caches package content | Hard-refresh or open in private/incognito tab | ## Related - Install `nvtop` for terminal TUI monitor: `apt install nvtop` (or build from https://github.com/Syllo/nvtop) - GPU acceleration setup: see the parent `docker-gpu-acceleration` skill