You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A standalone web administration panel for NUT (Network UPS Tools), installable on a Raspberry Pi or any Linux system, with Wake on LAN support and detailed UPS monitoring.
This repository also includes vm/nut-vm.sh, a bash script to automatically create an Ubuntu 24.04 VM on Proxmox VE with NUT pre-configured in netserver mode and the NutWatch web UI installed.
Why a VM instead of LXC? NUT cannot run reliably in LXC containers due to kernel driver detachment restrictions. The VM script creates a lightweight VM specifically for NUT.
Features
Web Administration UI (NutWatch)
Dashboard — System overview with stat cards (UPS count, users, active services, system health), CPU/memory/disk resource gauges, and quick-lists for all UPS devices and NUT services; one-click system actions (restart NutWatch, reboot, shutdown) with confirmation prompts
UPS Devices — CRUD management with card-grid view showing real-time telemetry (battery charge bar, load bar, runtime, voltage), per-card driver start/stop/restart, USB scan integration, and recommended config defaults
UPS Detail Telemetry — Deep-dive view grouped by subsystem (Battery, Input, Output, UPS, Device, Driver) with color-coded charge/load bars, unit-formatted values (V, Hz, W, VA, °C, A), runtime formatting, and raw variable dump; D3 gauge visualizations for battery charge and load
Historical Data & Charts — Per-UPS time-series data collected every 60 seconds into SQLite, displayed as D3 line charts with selectable ranges (1h, 24h, 7d, 30d) and per-variable filtering; configurable poll interval and 90-day retention
NUT Users — CRUD for NUT daemon users (upsd.users) with password masking and per-user roles (master/slave/admin); distinct from dashboard Accounts (see below)
Notifications — Full upsmon.conf editor with monitor line management (add/remove/edit per UPS), global commands (MINSUPPLIES, SHUTDOWNCMD, NOTIFYCMD, POWERDOWNFLAG), timing parameters grid (POLLFREQ, POLLFREQALERT, HOSTSYNC, DEADTIME, etc.), and notification message/flag matrix for all 9 events with SYSLOG/WALL/EXEC/IGNORE checkboxes
Per-UPS Event Hooks — Fine-grained script hooks per UPS per event (ONLINE, ONBATT, LOWBATT, COMMOK, COMMBAD, SHUTDOWN, REPLBATT, NOCOMM, NOPARENT) with in-browser script editor (Tab support), status badges, and instant save/delete
Live Log Streaming — Real-time SSE log viewer tailing nut-server, nut-monitor, and nut-driver journals with pause/resume, auto-scroll, color-coded lines (error/warn/info), and configurable recent log loading
Config Files — Raw in-browser editor for ups.conf, upsd.conf, upsmon.conf, and upsd.users (read-only via this endpoint)
Wake on LAN — Manage WOL targets (MAC, broadcast, description), create event-to-target mappings for automatic wake on UPS events (ONLINE, ONBATT, etc.), manual "Wake Now" and "Wake All" buttons, and non-destructive auto-dispatch via notifycmd.sh; MAC address field shows a dropdown of hosts discovered from the ARP cache (with hostnames via reverse DNS) and auto-suggests the target name from the hostname
Service Management — One-click restart (nut-server, nut-monitor, or both) and per-UPS driver start/stop/restart with multi-fallback cleanup (upsdrvctl, systemctl, PID kill, pkill); system-level actions: restart NutWatch (with automatic page reload), reboot, and shutdown
Accounts & API Keys — Optional session login (admin/viewer roles) for the dashboard and per-user API keys (Authorization: Bearer <key>) for scripts; a key inherits its owner's role. Fully open until the first admin account is created via the first-run Setup page (or skipped, keeping the app open) or manage.py create-admin
Atomic Config Writes — All file writes use tempfile + os.replace to prevent corruption
Input Validation — Identifier regex, newline injection prevention, type checking on all inputs
Proxmox VM Automation (vm/nut-vm.sh)
One-Command VM Creation — Downloads Ubuntu 24.04 minimal cloud image (SHA-256 verified), creates a Proxmox VM with EFI boot, virtio-scsi, and QEMU Guest Agent
Offline Disk Customization — Uses virt-customize to install packages, write NUT configs, and set up NutWatch directly into the disk image before VM creation
USB UPS Detection — Scans lsusb output, cross-references known vendor IDs (APC 051d, CyberPower 0764, Eaton 0463, Tripp Lite 09ae, Liebert 10af), handles duplicate models via bus-port notation, and configures USB passthrough
First-Boot Driver Auto-Detection — nut-detect oneshot systemd service runs nut-scanner -U on first boot and rewrites ups.conf with the detected driver/vendor/product IDs
Cloud-Init — Network configuration, rootfs resize, SSH host keys, and VM password via Proxmox cloud-init
Guest Agent IP Detection — 5-minute retry loop querying network-get-interfaces; manual IP entry fallback
Interactive Configuration — Default or Advanced setup modes with whiptail prompts for VM settings (ID, hostname, storage, bridge, RAM, CPU, disk) and NUT settings (UPS name, driver, users, listen address/port)
Auto-Generated Passwords — Optional secure password generation via openssl rand with fallback to /dev/urandom
Graceful Failure Handling — NutWatch install failure inside virt-customize is non-fatal; NUT service enablement handles multiple distro systemd variants (nut-driver-enumerator, nut-driver@, nut-driver) with || true
Signal Safety — trap handlers for ERR, EXIT, SIGINT, SIGTERM with cleanup and API status reporting
Resume Support — Partial cloud image downloads use wget -c
Debian 13 Compatibility — Auto-installs dhcpcd-base when missing for virt-customize network support
Notify Script & Hook Samples
notifycmd.sh — Central notify dispatcher that logs all UPS events, executes per-UPS per-event hook scripts from /etc/nut/notify.d/<UPSNAME>_<EVENT>.sh, and then triggers WOL auto-dispatch for any matching event mappings
Hook Samples (hook-samples/):
01-test-marker.sh — Write a marker file when an event fires
02-wall-notification.sh — Broadcast a wall message to all logged-in users
03-remote-ssh-shutdown.sh — SSH-shutdown another machine when UPS goes on battery
04-webhook-alert.sh — Send Discord/Slack webhook alerts with JSON payload
CI/CD & Developer Tooling
GitHub Actions — Lint (shellcheck, shfmt), Python syntax check (py_compile), pytest, frontend tests (Vitest), and automated release workflow on tag push
build-tarball — Creates nutwatch.tar.gz for release distribution (git-ignored)
Backend Tests — Pytest suite covering parsers, service layer (UPS, users, upsmon, hooks, WOL, system), auth, route handlers, and utility functions
Frontend Tests — Vitest suite covering components (Badge, ConfirmDialog, Dashboard, ErrorBoundary, Gauge, HistoryChart, Modal, RestartPromptModal, Skeleton, theme, UpsCard, UpsDetail, WakeOnLan) and utilities (alerts, api, directives, format, logs, service)
TypeScript — Strict mode (strict: true, noUnusedLocals, noUnusedParameters) with ESLint flat config; tsc --noEmit and eslint . run as part of make check
Screenshots
Dashboard
UPS Devices
UPS Detail (Info)
UPS Charts (Input Voltage)
UPS Charts (Runtime)
Hooks
Users
Notifications
Logs
Config Files
Wake on LAN
Edit UPS
Setup (First Admin)
Accounts
Add Account
Supported UPS Vendors
Vendor
USB ID
Driver
APC
051d
usbhid-ups
CyberPower
0764
usbhid-ups
Eaton
0463
usbhid-ups
Tripp Lite
09ae
usbhid-ups
Liebert
10af
usbhid-ups
Other USB UPS devices can be configured manually.
Architecture
Proxmox Host
├── USB UPS Device
│ └── USB Passthrough ──┐
│ ▼
├── vm/nut-vm.sh VM (Ubuntu 24.04 minimal)
│ ├── Downloads │ ├── NUT Server
│ ├── virt-customize ──►│ │ ├── nut-driver (usbhid-ups)
│ ├── Creates VM │ │ ├── upsd (port 3493)
│ ├── Detects UPS │ │ ├── upsmon (with notifycmd hooks + WOL dispatch)
│ └── Configures │ ├── NutWatch (port 8081)
│ (offline disk │ └── cloud-init (network, resize)
│ modification) │
└── First boot: nut-detect scans USB,
auto-configures driver in ups.conf
NutWatch-only mode — Use --install-only on a machine that already has NUT configured:
sudo bash scripts/setup.sh --install-only
Update mode — Use --update to upgrade only the NutWatch application code in an existing installation (VM or standalone), preserving NUT configs, hooks, and the Python venv:
Writes all NUT config files (nut.conf, ups.conf, upsd.conf, upsd.users, upsmon.conf)
Scans USB for UPS devices (first-boot auto-detection service available)
Installs notifycmd.sh with per-UPS per-event hook support and WOL auto-dispatch
Installs nutwatch-wol-dispatch to /usr/local/bin/ for event-driven WOL
Installs NutWatch web UI on port 8081 with systemd service
Enables and starts all NUT services
Configures firewall (ufw) rules
Environment Variable
Default
Description
AUTO
(unset)
Set to 1 for non-interactive mode with defaults
NUT_UPS_NAME
ups
UPS identifier
NUT_UPS_DESC
My UPS
UPS description
NUT_DRIVER
usbhid-ups
NUT driver
NUT_ADMIN_USER
admin
NUT daemon admin username
NUT_ADMIN_PASS
(auto-gen)
NUT daemon admin password
NUT_MONITOR_USER
monuser
NUT monitor username
NUT_MONITOR_PASS
(auto-gen)
NUT monitor password
NUT_LISTEN_ADDR
0.0.0.0
NUT listen address
NUT_LISTEN_PORT
3493
NUT listen port
NUTWATCH_REF
v1.2.0
NutWatch release tag
NUTWATCH_URL_PREFIX
(unset)
Override tarball URL for local testing
After install, the app is fully open (no login). Create the first admin with manage.py create-admin <username> (run from the NutWatch install directory, e.g. venv/bin/python manage.py create-admin admin) to turn on session login and per-user API keys — or create it from the dashboard's first-run Setup page.
Option B — NutWatch only (existing NUT setup)
Install just the NutWatch web UI on a machine that already has NUT configured:
# Download the script
curl -fsSL https://raw.githubusercontent.com/JuanCF/nutwatch/main/vm/nut-vm.sh -o nut-vm.sh
# Or clone the repository
git clone https://github.com/JuanCF/nutwatch.git
cd nutwatch
# Run from source
bash vm/nut-vm.sh
Usage
# Run on Proxmox host as root (from cloned repo)
bash vm/nut-vm.sh
# Or if downloaded directly
bash nut-vm.sh
Environment Variables
vm/nut-vm.sh
Variable
Default
Description
VERBOSE
(unset)
Set to yes to show full command output
NUTWATCH_URL_PREFIX
(unset)
Override the GitHub Releases URL for the nutwatch tarball
make check # Full CI suite: lint + format check + Python lint + pytest + frontend tests
make lint # shellcheck only
make fmt # shfmt -d -i 2 (check only)
make fmt-fix # shfmt -w -i 2 (auto-fix)
make lint-python # py_compile check on all Python files
make test-python # pytest on src/backend/tests/
make test-frontend # Vitest on src/frontend/src/__tests__/
make build-frontend # npm ci + npm run build
make build-tarball # Create nutwatch.tar.gz for distribution
make install-tools # Install dev dependencies
Hook Samples
Place scripts in /etc/nut/notify.d/<UPSNAME>_<EVENT>.sh:
Sample
Description
01-test-marker.sh
Write a marker file to /tmp/ups-test.log
02-wall-notification.sh
Broadcast wall message and syslog alert
03-remote-ssh-shutdown.sh
SSH into another machine and shut it down
04-webhook-alert.sh
Send Discord/Slack webhook JSON payload
Each hook receives $UPSNAME and $NOTIFYTYPE environment variables from upsmon.
Verification
# Check VM status
qm list
# Verify USB passthrough
qm config <vmid>| grep usb
# Test NUT from Proxmox host
upsc ups@<VM_IP># Test from another machine
upsc ups@<VM_IP>:3493
# Check NUT services inside VM
systemctl status nut-server nut-monitor
# Access NutWatch web UI
http://<VM_IP>:8081
Security Notes
NUT passwords should be strong and unique
The netserver listens on all interfaces by default (0.0.0.0)
Consider firewall rules to restrict NUT port (3493) access
The VM password is set via Proxmox's built-in cloud-init (qm set --cipassword)
Hook scripts are owned root:nut with 750 permissions for secure upsmon execution
WOL registry files (wol.json, wol-events.json) are owned root:nut with 640 permissions
Config file writes use atomic tempfile + os.replace to prevent partial writes
Disclaimer: This script modifies your Proxmox configuration. Always review scripts before running them as root. Test in a non-production environment first.
About
Self-hosted web dashboard to monitor and manage NUT (Network UPS Tools) UPS devices