Note that these instructions use offensive master/slave
terminology because they are still necessary keywords in the NUT configuration files. There is work in progress to change this. I am going to use server
and client
whenever I can, but you can't avoid master/slave in upsd.users
or upsmon.conf
.
Given two UPS's:
And a Raspberry Pi, I'm setting up my home network and critical hardware to shutdown gracefully when the power fails.
(commands assume you are root
and in /etc/nut
going forward)
$ sudo su
$ apt-get install nut nut-client nut-server usbutils
$ cd /etc/nut/
I also normalized permissions as follows:
$ chmod 640 /etc/nut/*
$ chown root:nut /etc/nut/*
I'm certain things can and should be tightened up further; this is fine for home.
root@rpi41:/home/pi# lsusb
Bus 002 Device 001: ...
Bus 001 Device 004: ID 0764:0601 Cyber Power System, Inc. PR1500LCDRT2U UPS # <----
Bus 001 Device 003: ID 0764:0601 Cyber Power System, Inc. PR1500LCDRT2U UPS # <----
Bus 001 Device 002: ...
Bus 001 Device 001: ...
In ups.conf
:
[cp850]
driver = usbhid-ups
port = auto
desc = "CyberPower CP850PFCLCD - Network"
offdelay = 20
ondelay = 0
ignorelb
override.battery.charge.low = 20
override.battery.charge.warning = 40
pollinterval = 15
[cp1000]
driver = usbhid-ups
port = auto
desc = "CyberPower CP850PFCLCD - Office"
offdelay = 20
ondelay = 0
ignorelb
override.battery.charge.low = 20
override.battery.charge.warning = 40
pollinterval = 15
Also in that file, comment out:
maxretry = 3
at the very bottom. It doesn't seem to work with the usbhid-ups
driver.
Now restart. I don't know why this is necessary, but it is.
When you're back, become root and cd
to /etc/nut
again.
Check the nut server status with:
$ systemctl status nut-server
Output should be something like:
<date time> <host> upsd[564]: Startup successful
<date time> <host> systemd[1]: Started Network UPS Tools - power devices information server.
<date time> <host> upsd[564]: User upsserver@::1 logged into UPS [cp1000]
<date time> <host> upsd[564]: User upsserver@::1 logged into UPS [cp850]
<date time> <host> upsd[564]: Data for UPS [cp850] is stale - check driver
<date time> <host> upsd[564]: Data for UPS [cp1000] is stale - check driver
<date time> <host> upsd[564]: UPS [cp1000] data is no longer stale
<date time> <host> upsd[564]: UPS [cp850] data is no longer stale
Note that if you need to make changes you should restart with:
$ upsdrvctl stop
$ upsdrvctl start
And after stopping and starting you should see messages like this to stdout (or stderr, not sure):
Broadcast message from nut@<host> (somewhere) (<date time>):
Communications with UPS cp1000@localhost lost [or established!]
Broadcast message from nut@<host> (somewhere) (<date time>):
Communications with UPS cp850@localhost lost [or established!]
Now test the settings are correct by running upsc
, which is a small program that exists to check communications:
$ upsc cp1000@localhost
Init SSL without certificate database
battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 20
battery.mfr.date: CPS
[... it goes on]
Do the same for cp850@localhost
In nut.conf
, set :
MODE=netserver
In upsd.conf
, add:
LISTEN 127.0.0.1 3493
LISTEN 192.168.1.67 3493 # SET TO THE IP OF THIS RASPBERRY PI
LISTEN ::1 3493
In upsd.users
:
[upsserver]
password = <make up a pw>
upsmon master
[upclient]
password = <make up a different pw>
upsmon slave
Note that these are not Linux users, they're just roles in the NUT environment.
In upsmon.conf
, add:
MONITOR cp1000@localhost 1 upsserver <upsserver password> master
MONITOR cp850@localhost 1 upsserver <upsserver password> master
and find the DEADTIME
config further down and set it to DEADTIME 25
This tutorial has some alternative settings for upsmon.conf
. The timings there may need adjustment.
In upssched.conf
, make the entire contents as follows:
CMDSCRIPT /bin/upssched-cmd
# Command pipe and lock-file
PIPEFN /var/run/nut/upssched.pipe
LOCKFN /var/run/nut/upssched.lock
# Send alerts immediately on change in line power
AT ONBATT * EXECUTE onbatt
AT ONLINE * EXECUTE onpower
# (Optional) Silence the beeper after 2 minutes
AT ONBATT * START-TIMER mute_beeper 120
AT ONLINE * CANCEL-TIMER mute_beeper
# Shutdown after 20 minutes on battery (20 * 60 = 1200)
AT ONBATT * START-TIMER onbatt_shutdown 1200
# Cancel timer if power's restored
AT ONLINE * CANCEL-TIMER onbatt_shutdown
# Battery replacement indicated by cron'd quick test
AT REPLBATT * EXECUTE replace_batt
Then, in /bin/upssched-cmd
, make the contents look like this:
UPS_USERNAME="upsserver"
UPS_PASSWORD="<upserver password from upsd.users>"
CP850_LINK="cp850r@localhost"
CP1000_LINK="cp1000@localhost"
case $1 in
onbatt)
# make sure beeper is enabled
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${CP850_LINK} beeper.enable
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${CP1000_LINK} beeper.enable
# alert
message="Power outage, on battery"
logger -t upssched-cmd "$message"
;;
onpower)
message="Power restored"
logger -t upssched-cmd "$message"
;;
mute_beeper)
message="(2) minute limit exceeded, muting beeper"
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${CP850_LINK} beeper.mute
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${CP1000_LINK} beeper.mute
;;
onbatt_shutdown)
message="Triggering shutdown after (20) minutes on battery"
logger -t upssched-cmd "$message"
/sbin/upsmon -c fsd
;;
replace_batt)
message="Quick self-test indicates battery requires replacement"
logger -t upssched-cmd "$message"
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac
.. TODO
upsdrvctl stop
upsdrvctl start
systemctl status nut-server
systemctl restart nut-server
systemctl status nut-client
systemctl restart nut-client
upsc <id>@localhost
It took a lot of RTFM and about a a half dozen web tutorials to figure this all out. Even though it turned out to be quite simple in the end, inconsistences abound. No doubt your mileage will vary with my writeup as well. My two best tips are:
- When in doubt, restart
- The users in
upsd.user
are not system user accounts. They are just roles in the NUT environment. This threw me for about my first hour.
- How to Shutdown Your Servers In Case of Power Failure — UPS, NUT & Co.
- TUTORIAL - NETWORKED NUT FOR CYBERPOWER UPS
- How to Monitor UPS with Raspberry Pi
- NUT & CyberPower UPS
- https://networkupstools.org/
- IP Fire Wiki - Network UPS Tools (NUT) has useful troubleshooting advice, even though it's for a standalone config.
- IP Fire Wiki - Detailed NUT Configuration has a good explanantion of the Schedule configuration.