I recently bought a UPS for my small server setup. Setting it up to automatically shutdown my system in case of a power outage wasn’t that hard. Here is how.

I’m using a PowerWalker Basic VI 850 SB (international), which can be connected via USB. Hint: vendor does not provide USB-cable (Type B needed).

I’m going to use the Network UPS Tools (NUT) to monitor the status of my UPS and - if needed - keep my server alive.

Why do I want to use a UPS?

Main motivation on this is to prevent data loss. Additionally a UPS corrects common power issues, whereas mine is line-interactive. In simple terms: it prevents under-/overvoltage to some degree.

Connected to my server, it signals when a power outage occurs, tries to keep it up until it’s battery is low and shutting it down to prevent damaged RAID-/disks.

Introduction to NUT

NUT provides tools for connecting, monitoring and communicate stats about a UPS. In short: it can be used on a SOHO setup, as well as on a multi-server farm in any 19” server rack (one UPS, many appliances connected to it). Take a look the monitoring diagrams.

NUT utilizes:

  • a driver capable to communicate with one or many UPS’s
  • upsd the server, which reads data from driver and allows network communication
  • upsmon monitoring to set some actions based on UPS’ state

A list of compatible power supplies can be found on the website.

Installation and Configuration

Installation on Fedora Server 36 is pretty easy:

dnf install nut nut-client

Setting up /etc/ups/nut.conf, since I use it as a standalone server (without any other connected to it):

MODE=standalone

Quickly scanning for connected and supported devices: nut-scanner -U (-U scans only USB). It outputs a similar data to what we need in our next step. Just append a new UPS with driver, port and a small desc(ription) to ups.conf:

# /etc/ups/ups.conf

# appending driver/port combination with a short description
# nutdev1 was a suggestion by the scanner, it could be everything instead

[nutdev1]
	driver = "usbhid-ups"
	port = "auto"
	desc = "My small office server"

Setting up the upsd daemon to allow the local upsmon to access data (next step):

# /etc/ups/upsd.conf
ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32

ACCESS grant monitor localhost
ACCESS deny all all

As well as a user (the password will be used only internally):

# /etc/ups/upsd.users
[monuser]
        password = nieNg3eeHeixis1phooz
        allowfrom = localhost
        upsmon master

Optionally: If you want to access your UPS using an admin user (for instance controlling “the beep” or testing battery), you need an additional user:

[admin]
        password = mypass
        actions = set
        instcmds = all

Finally setting up upsmon (with your monuser password):

# /etc/ups/upsmon.conf
MONITOR nutdev1@localhost 1 monuser nieNg3eeHeixis1phooz master

Testing the configuration

Running upsc nutdev1 as user nut failed, telling me no device were found. A nut-scanner -U told me access denied.

In my case a quick lsusb | grep -i UPS provided:

Bus 005 Device 002: ID 0764:0601 Cyber Power System, Inc. UPS

So I need to allow user nut to access it. Using udev it’s pretty simple:

# /etc/udev/rules.d/90-nut-ups.rules
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0764", ATTR{idProduct}=="0601", MODE="0660", GROUP="nut"
$ udevadm control --reload-rules
$ udevadm trigger

Now test again:

su nut --shell=/bin/bash
$ upsc nutdev1

# should start driver without errors, if fine, stop it (starting as systemd later).
$ upsdrvctl start 
$ upsdrvctl stop

Ready to run!

Start NUT

$ systemctl enable nut-driver nut-server nut-monitor
$ systemctl start nut-driver nut-server nut-monitor

Finally, everything runs as expected

Testing Shutdown Cycle

To see if everything might work, you can run the following command, which will only display the commands to shutdown the system:

$ upsdrvctl -t shutdown

-t tells the command, to just test and output. Running without might actually shutdown your system. Be aware of data loss, if something isn’t correctly configured (since it might force the system to halt, after a configured timespan).

You could also use this command, to issue a “shutdown for all primary nodes” (standalone is a primary). Warning: this will halt your system - forcefully if needed(!):

$ upsmon -c fsd

Testing Power Outage

The final test is to unplug the cable of the UPS to see if the upsmon reacts correctly. It gracefully shut down my server after 40min (jup, my UPS is oversized). After that, my UPS shutdown, too.

Plugging the power cable in again resulted in a reboot of my server. All set! If your server won’t start again, check BIOS settings to “restart on power loss”.

References

I used many references for this. Maybe one or two links might help you, too.

Next Steps

  • Configure a monitoring dashboard in Grafana for visualization
  • Alert me about outage (keep in mind: if there is no power, there is usually no router (and therefor no internet), too)
  • Automatically setup using Ansible (for next time)

Final Toughts

I’m really happy with my setup. It just works as expected and helps me getting good sleep at night, without worrying to loose my data ‘cause some neighbour hit the wall.

Now I need to measure the values of my UPS to store them in my metrics server for visualization later. Happily there is a simple tool for this: upsc nutdev1 output quite everything!