Uninterruptible Power Systems (UPS) are very valuable to ride through small power outages. UPS are particularly critical with Network Attached Storage (NAS) servers which may have many open files and multiple file systems that do not take kindly to a sudden loss of power. This presentation focuses on how to use the Network UPS Utility (NUT) to manage and control systems connected to a UPS.
The NUT Project considers the system directly connected to an UPS to be a Master (Server) and systems that are on the network without a direct UPS connection are considered to be Slaves (Clients). In this video, we explore the configuration of a QNAP NAS UPS attachment and also we show how to configure and monitor other Linux systems that can be both Master and Slave NUT devices.
On your QNAP NAS, here is where to find the UPS settings.
In my example above, the system enters auto protection mode and reboots after power is restored.
In the first example of configuring a server other than a QNAP, we configured a Raspberry Pi 3B as a NUT Server and connected its USB port to a CyberPower UPS. First, to establish that our UPS is connected to the system, execute the following command at a terminal prompt.
You should be able to see the UPS unit in the listing. Next, we install all of the NUT Project components:
sudo apt install nut nut-client nut-server
Use the following command to list information on your UPS.
sudo nut-scanner -U
Select the output from the above command and edit this file:
sudo nano /etc/nut/ups.conf
Clear the contents of the file and paste in your data along with the pollinterval and maxretry lines. Rename the UPS name within the brackets to suit you.
pollinterval = 1 maxretry = 3 [testpi] driver = "usbhid-ups" port = "auto" desc = "Office UPS" pollinterval = 15 vendorid = "0764" productid = "0501" product = "UPS CP1000AVRLCD" vendor = "CPS" bus = "005"
Edit the user file and add user accounts as needed.
sudo nano /etc/nut/upsd.users
Place input in the file. An example follows:
[admin] password = 123456 admin master
Edit the monitor file.
sudo nano /etc/nut/upsmon.conf
An example of the contents follows:
RUN_AS_USER root MONIITOR testpi@localhost 1 admin 123456 master DEADTIME 25 MAXAGE 25
Edit the daemon listener file:
sudo nano /etc/nut/upsd.conf
Put the following contents in the daemon file so that anyone on the network is allowed to connect to this NUT server.
LISTEN 0.0.0.0 3493 LISTEN ::0 3493
Edit the NUT configuration file:
sudo nano /etc/nut/nut.conf
Enter the following into it.
Change all of the NUT files to be owned by the NUT user and restart the server.
sudo chown nut /etc/nut/* /etc/init.d/nut-server restart
Test your configuration with the UPS name you used in the ups.conf file:
NUT Web Server
The next thing we want to is configure a Web Server to run nut-cgi (upsstats) to monitor one or more UPS units. In the video, I created a LXD container that I bridged to the main network using QNAP Container Station. You can create a LXD container or a Virtual Machine on any system as your NUT Web Server.
On this server install the packages.
sudo apt install apache2 nut-cgi
Edit the following file:
sudo nano /etc/nut/hosts.conf
Insert a line for each UPS that you want to monitor. NOTE: You would have had to install the NUT server for each system attached to each UPS. You need to use the correct UPS name you set on the server and the address of the server. As an example:
MONITOR firstname.lastname@example.org "TestPi"
Enable the cgi module in the apache webserver and restart apache:
sudo a2enmod cgi sudo systemctl restart apache2
Edit this file:
sudo nano /etc/nut/upsset.conf
Uncomment the following line in the file:
Go to a web browser and visit the following URL (with your IP address):
If everything worked, you should have a screen listing your UPS units. Note that I configured four servers because I have four UPS units.
A NUT Slave (client) follows the status of a NUT Master (server). So, a NUT client can shutdown a system not connected to the UPS USB port just by following the status of the NUT Master.
In my example, I installed the NUT Client on a virtual machine.
sudo apt install nut-client
Edit the monitor file.
Insert the following and change the MONITOR line to point to your Master.
RUN_AS_ROOT root MONITOR email@example.com 1 admin 123456 slave MINSUPPLIES 1 SHUTDOWNCMD "/sbin/shutdown -h" NOTIFYCMD /usr/sbin/upssched POLLFREQ 2 POLLFREQALERT 1 HOSTSYNC 15 DEADTIME 15 POWERDOWNFLAG /etc/killpower NOTIFYMSG ONLINE "UPS %s is on utility power" NOTIFYMSG ONBATT "UPS %s is on battery power" NOTIFYMSG LOWBATT "UPS %s remaining battery is low" NOTIFYMSG FSD "UPS %s forced shutdown is in progress" NOTIFYMSG COMMOK "Communications with UPS %s established" NOTIFYMSG COMMBAD "Communications with UPS %s lost" NOTIFYMSG SHUTDOWN "Auto logout and shutdown is proceeding" NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" NOTIFYMSG NOCOMM "UPS %s is unavailable" NOTIFYMSG NOPARENT "upsmon parent process not running - shutdown not possible" NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC NOTIFYFLAG FSD SYSLOG+WALL+EXEC NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC NOTIFYFLAG NOPARENT SYSLOG+WALL+EXEC NOTIFYFLAG LOWBATT SYSLOG+WALL NOTIFYFLAG REPLBATT SYSLOG+WALL RBWARNTIME 43200 NOCOMMWARNTIME 600 FINALDELAY 5
Edit the config file:
sudo nano /etc/nut/nut.conf
Insert the following to set it as a client.
Create the scheduling configuration file.
sudo nano /etc/nut/upssched.conf
Insert the following data:
CMDSCRIPT /etc/nut/upssched-cmd PIPEFN /etc/nut/upssched.pipe LOCKFN /etc/nut/upssched.lock AT ONBATT * START-TIMER onbatt 30 AT ONLINE * CANCEL-TIMER onbatt online AT ONBATT * START-TIMER earlyshutdown 30 AT LOWBATT * EXECUTE onbatt AT COMMBAD * START-TIMER commbad 30 AT COMMOK * CANCEL-TIMER commbad commok AT NOCOMM * EXECUTE commbad AT SHUTDOWN * EXECUTE powerdown
Create the scheduling script:
sudo nano /etc/nut/upssched-cmd
Insert the following into it:
#!/bin/sh case $1 in onbatt) logger -t upssched-cmd "The UPS is on battery" ;; earlyshutdown) logger -t upssched-cmd "UPS on battery for too long, forcing shutdown" /usr/sbin/upsmon -c fsd ;; shutdowncritical) logger -t upssched-cmd "UPS on battery critical, forcing shutdown" /usr/sbin/upsmon -c fsd ;; upsgone) logger -t upssched-cmd "The UPS has been gone for awhile, no communication" ;; *) logger -t upssched-cmd "Unrecognized command: $1" ;; esac
Finally, change the permission to execute on the script and restart the client.
sudo chmod +x /etc/nut/upssched-cmd sudo systemctl restart nut-client
To test to make sure that the slave (client) can reach the master (server) use the following command with the name of your UPS you created and its IP address.
The ultimate test is to unplug the UPS from the wall socket and then see if your client initiates a shutdown on low battery on the UPS connected to the server.
I have this working, but in the video, the invertor on my test UPS died just as I was about to demo this. After you unplug the UPS, the client should almost immediately see a console message saying the the Master UPS is on battery.
For detailed documentation about the Open Source NUT Project, visit: https://networkupstools.org/