QNAP UPS & More

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.

lsusb

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.

MODE=netserver

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:

upsc testpi@localhost

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 testpi@172.16.1.130 "TestPi"

My file looks like this:
image

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:

I_HAVE_SECURED_MY_CGI_DIRECTORY

Go to a web browser and visit the following URL (with your IP address):

http://172.16.1.97/cgi-bin/nut/upsstats.cgi

If everything worked, you should have a screen listing your UPS units. Note that I configured four servers because I have four UPS units.

NUT Client

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.

nano /etc/nut/upsmon.conf

Insert the following and change the MONITOR line to point to your Master.

RUN_AS_ROOT root

MONITOR testpi@172.16.1.130 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.

MODE=netclient

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.

upsc testpi@172.16.1.130

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/

1 Like