< back to notes

NUT Setup on a Raspberry Pi

Overview

I want to monitor my 2 APC UPSes in my rack that are not network based, I have taken the units out of service that had NMC cards, but these UPSes have USB ports on them.

Setting up NUT

I put a Raspberry Pi running Ubuntu Server in the rack on a shelf, directly connected to the data ports on the UPSes and installed NUT:

sudo apt install nut -y

I can scan for connected UPSes via nut-scanner:

sudo nut-scanner
...
Scanning USB bus.
No IP range(s) requested, skipping NUT bus (old libupsclient connect method)
Scanning NUT simulation devices.
[nutdev-usb1]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "051D"
        productid = "0002"
        product = "Back-UPS NS 1500M2 FW:957.e5 .D USB FW:e5"
        serial = "0BXXXXXXXXXX"
        vendor = "American Power Conversion"
        # bus = "001"
        # device = "004"
        # busport = "004"
[nutdev-usb2]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "051D"
        productid = "0002"
        product = "Back-UPS NS 1500M2 FW:957.e5 .D USB FW:e5"
        serial = "0BXXXXXXXXXX"
        vendor = "American Power Conversion"
        # bus = "001"
        # device = "003"
        # busport = "003"

I copied device stanzas listed from nut-scanner directly into /etc/nut/ups.conf

I had to create a udev rule so the driver could access the device at /etc/udev/rules.d/50-nut-ups.rules:

SUBSYSTEM=="usb", ATTR{idVendor}=="051D", ATTR{idProduct}=="0002", MODE="664", GROUP="nut"

And applied them:

sudo udevadm control --reload-rules
sudo udevadm trigger

Now I could query the UPSes:

sudo upsc nutdev-usb1
Init SSL without certificate database
battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 50
battery.date: 2001/09/25
battery.mfr.date: 2025/12/06
battery.runtime: 990
battery.runtime.low: 120
battery.type: PbAc
battery.voltage: 27.4
battery.voltage.nominal: 24.0
device.mfr: American Power Conversion
device.model: Back-UPS NS 1500M2
device.serial: 0BXXXXXXXXXX  
device.type: ups
driver.debug: 0
driver.flag.allow_killpower: 0
driver.name: usbhid-ups
driver.parameter.interrupt_pipe_no_events_tolerance: -1
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.product: Back-UPS NS 1500M2 FW:957.e5 .D USB FW:e5
driver.parameter.productid: 0002
driver.parameter.serial: 0BXXXXXXXXXX
driver.parameter.synchronous: auto
driver.parameter.vendor: American Power Conversion
driver.parameter.vendorid: 051D
driver.state: quiet
driver.version: 2.8.4
driver.version.data: APC HID 0.100
driver.version.internal: 0.67
driver.version.usb: libusb-1.0.29 (API: 0x0100010B)
input.sensitivity: medium
input.transfer.high: 142
input.transfer.low: 88
input.transfer.reason: input voltage out of range
input.voltage: 123.0
input.voltage.nominal: 120
ups.beeper.status: enabled
ups.delay.shutdown: 20
ups.firmware: 957.e5 .D
ups.firmware.aux: e5     
ups.load: 36
ups.mfr: American Power Conversion
ups.mfr.date: 2025/12/06
ups.model: Back-UPS NS 1500M2
ups.productid: 0002
ups.realpower.nominal: 900
ups.serial: 0B2549L39063  
ups.status: OL
ups.test.result: No test initiated
ups.timer.reboot: 0
ups.timer.shutdown: -1
ups.vendorid: 051d

Notifications

I want to be notified as soon as NUT detects a change in power delivery. I have a self-hosted Ntfy.sh instance, which my phone receives.

I created a script at /bin/ups-script.sh:

!/bin/bash
case $1 in
    on-battery)
        curl \
            -H "Priority: 5" \
            -H "Title: 🪫 A UPS is on Battery [NUT]" \
            -u user:pass \
            -d "A UPS is on Battery Power." \
            https://myntfyhost/alerts-networkinfra
            ;;
    online)
        curl \
            -H "Priority: 5" \
            -H "Title: 🔋 A UPS is no longer on Battery [NUT]" \
            -u user:pass \
            -d "A UPS is no longer on battery power." \
            https://myntfyhost/alerts-networkinfra
            ;;
esac

Testing the script:

sudo chmod +x /bin/ups-script.sh 

ups-script.sh online
{"id":"a7f8b6h7E7dr","time":1789693523,"expires":1789736723,"event":"message","topic":"alerts-networkinfra","title":"🔋 A UPS is no longer on Battery [NUT]","message":"A UPS is no longer on battery power.","priority":5}

ups-script.sh on-battery
{"id":"PyD6rHSKrBps","time":1789693623,"expires":1789736823,"event":"message","topic":"alerts-networkinfra","title":"🪫 A UPS is on Battery [NUT]","message":"A UPS is on Battery Power.","priority":5}

“ntfy”

Added the following to /etc/nut/upssched.conf:

PIPEFN /var/run/nut/upssched.pipe
LOCKFN /var/run/nut/upssched.lock
CMDSCRIPT /bin/ups-script.sh
AT ONBATT * EXECUTE on-battery
AT ONLINE * EXECUTE online

I’ve mostly taken inspiration from this Stack Exchange reply for the script.

Created a upsd user in /etc/nut/upsd.users:

[monitor]
    password = secretPassword123
    upsmon master

Added monitor lines to /etc/nut/ups.conf:

NOTIFYCMD /usr/sbin/upssched
NOTIFYFLAG ONLINE       SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT       SYSLOG+WALL+EXEC
MONITOR nutdev-usb1@localhost 1 monitor secretPassword123 master
MONITOR nutdev-usb2@localhost 1 monitor secretPassword123 master

Restarted the NUT services:

sudo systemctl restart nut-server nut-monitor

Testing notifications:

sudo UPSNAME=nutdev-usb1@localhost NOTIFYTYPE=ONBATT upssched ONBATT
{"id":"2H7EQZ4vROES","time":1789694704,"expires":1789737904,"event":"message","topic":"alerts-networkinfra","title":"🪫 A UPS is on Battery [NUT]","message":"A UPS is on Battery Power.","priority":5}

sudo UPSNAME=nutdev-usb1@localhost NOTIFYTYPE=ONLINE upssched ONLINE
{"id":"cJcUjjMs4S2f","time":1789694810,"expires":1789738010,"event":"message","topic":"alerts-networkinfra","title":"🔋 A UPS is no longer on Battery [NUT]","message":"A UPS is no longer on battery power.","priority":5}

The notifications came through.

Testing manually by disconnecting and reconnecting the UPS from grid power did trip both notifications.

Automatic shutdown

I won’t be doing automatic shutdown yet. I am going to improve the script to pass some more info through the notification before I do any sort of remote shutdown of equipment.