Linux UPS Without Tears

Creating this solution began as an exercise in self-interest. I own a Belkin 6C550AVR UPS, and until a few months ago, I ran it with Belkin Sentry Bulldog for Linux. Unfortunately, when I upgraded to Fedora Core 6, I found that not only did Bulldog cease to function, but also there was no upgrade. What's more, I found that Belkin no longer supports Linux. And judging from Belkin's non-response to my inquiries, it seems they have no plans to change that policy.

So without UPS software, what I have is a functional but dumb UPS. That is, something that will not handle an automatic, safe shutdown in the event of a power outage. I had to find a replacement.

That replacement is called NUT, short for Network UPS Tool. In this Recipe, I'll explain how to install NUT and set it up. While this recipe is based on a Debian distribution, installation on rpm-based (Fedora, RHEL, etc.) distributions should work by using the automated installer packaged with your distro.

This Recipe is oriented toward UPS systems connected via USB. Setup for the old-style serial units is far easier and more predictable. If you choose that way, simply go to this MGE How-To page, and follow the instructions.

Sponsored post

Also, while NUT can be used in an enterprise-class setup running many UPS systems and servers with automatic restoral of computer service, my ambition for this article is more limited. I simply cover workstation setup.


NUT interfaces with your UPS through a driver. If you want to use a UPS with Linux—and no NUT driver exists for your UPS—you have to either find one that is supported or find someone to write a driver. You can use a UPS without a driver in "dumb mode"—you simply need to shut down the system when you know it's going to be unattended.

An online listing of NUT UPS drivers can be found here. There's also a list within the package (which is probably the most current list), but you can't access that list until after you install it.

Matching USB ID Codes: This is the final authority on what NUT will and won't run. But you can't do this until after you've downloaded and unpacked the source. You don't need to do that unless it not only fails from hotplug/udev, but won't even run as root (that is, you have troubleshooting to do). How to do this is described in the Udev section below.


I now run the Debian Etch (testing) distribution of Linux. Debian has three official versions: stable, testing, and unstable. Stable (nicknamed Sarge) has been around long enough to be almost completely debugged. Testing is something of a work in progress, but is more likely to support the most current hardware. Finally, unstable (called Sid) is leading/bleeding edge. Etch is what the current "testing" distro is called, but soon it will be called "stable." Then, the "unstable" will become "testing."

Installing NUT is supported directly by the automated installation tool apt-get. It comes with several different front-ends; the one I use is called aptitude. If you can't use automated installation, I recommend downloading binaries from one of the Debian repositories for your version. You can find them here.

For other distributions, install the three apps in the in the command line below via automated installer for your distro, when possible. Otherwise, you can get NUT from source or packages for several distributions here and KNutClient here. (KNutClient is a display application for NUT, showing things like analog charge percentage meters, input voltage, etc.) Nut-usb is generated by the build script in a source build, so you don't have to get it separately. (Nut-usb is the software package that handles USB I/O, which is required if your UPS has a USB I/O.)

In this Recipe, the dollar sign ($) refers to any command you should run as user, and the hash mark (#) refers to any command you should run as root.

# aptitude install nut nut-usb knutclient

You can find the application package internal file list with the installed locations for any Debian dpkg-installed package (including apt-get) at /var/lib/dpkg/info/packagename.list. I'm not sure where it is for rpms, but if all else fails and you can't find where the rpm installation package put the executable files, do this:

# updatedb

Take a coffee break, as this will require a few minutes.

# locate filename

The updatedb command tells the computer to run the indexing program that the locate command uses to read the location of files from the database.

AUTOMATED NUT SETUP: KNutSetting not # aptitude install knutsetting # dpkg -i knutsetting NUT PRECONDITIONS: # ls /usr/lib/libusb* /usr/include/usb.h /usr/lib/libusb.a /usr/lib/ /usr/lib/ /usr/lib/ # aptitude install lib-usb

and tell aptitude to install everything lib-usb . HOW TO FIND AND INSTALL NUT CONFIGURATION FILES:

There are no default NUT configuration files in directory locations where NUT can actually use them. Here's how to move example files that can be manually edited to provide a usable NUT configuration:

cp /usr/share/doc/nut/examples/* /usr/nut

The minimum set of files you must configure to run NUT is:

ups.conf upsd.conf upsmon.conf

Then configure them as follows: You can use your favorite GUI text editor instead of the nano. command-line text editor. Just make sure you've opened it as root; otherwise, some of the files won't save, because the text editor running in userspace won't have write access:

nano /usr/nut/ups.conf [belkin-ups] driver = newhidups port = auto

The word in brackets is the name by which your system will identify the UPS. It should be a single word with no spaces. Here, the driver is newhidups. The port name "auto" means "anything the driver can identify as a UPS." In the commands for the rest of this Recipe, where the belkin-ups UPS device is invoked, substitute whatever you put in the brackets in place of belkin-ups.

nano /usr/nut/upsd.conf ACL all ACL localhost ACCEPT localhost REJECT all

The above format may look familiar to anyone who's manually configured an ipchains firewall. The meanings are the same: ACL means "Access Control List," and accept / reject refer to the names above in the ACL.

/usr/etc/upsd.users [admin] password = password1 allowfrom = localhost terrarium actions = SET instcmds = ALL # --- Configuring for upsmon # To add a user for your upsmon, use this example: # [user] password = password2 allowfrom = localhost upsmon master create a ups user group # addgroup ups

Join it as both user and root:

# adduser root ups # adduser username ups

Set file ownership and permissions:

# chown ups:ups -R /etc/nut # chmod 0600 -R /etc/nut

You should see this:

/etc/nut# ls -al total 64 drw------- 2 ups ups 4096 2007-02-27 18:42 . drwxr-xr-x 136 root root 12288 2007-02-27 15:26 .. -rw------- 1 ups ups 5102 2007-02-17 13:11 README.Debian.txt -rw------- 1 ups ups 3721 2007-02-21 00:50 ups.conf -rw------- 1 ups ups 1364 2007-02-27 18:34 upsd.conf -rw------- 1 ups ups 2186 2007-02-27 18:36 upsd.users -rw------- 1 ups ups 286 2007-02-27 18:40 upsmon.conf -rw------- 1 ups ups 4251 2007-02-21 00:49 upsmon.conf.gz -rw------- 1 ups ups 11259 2007-02-26 14:46 upsmon.conf-old -rw------- 1 ups ups 3893 2007-02-21 00:49 upssched.conf nano /usr/nut/upsmon.conf

Next, create the /var/state/ups directory, if it doesn't exist:

# mkdir -p /var/state/ups # chmod 0700 /var/state/ups # chown ups:ups /var/state/ups


here $ tar xzvf nut-2.0* nut* Do not install the source![path-to] [path-to]/scripts/hotplug-ng/ # cp -f nut-usbups.rules /etc/udev/rules.d/025_nut-usbups.rules HOTPLUG SETUP: cd [path-to]/nut-2.0.5/scripts/hotplug # ls libhid.usermap README # cp /etc/hotplug/usb/libhidups # cp libhid.usermap /etc/hotplug/usb/libhid.usermap # chmod 0755 /etc/hotplug/usb/libhidups # chmod 0644 /etc/hotplug/usb/libhid.usermap -rw-r—r— # ls -lR /proc/bus/usb/ /proc/bus/usb/: total 0 dr-xr-xr-x 2 root root 0 2007-02-27 15:25 001 dr-xr-xr-x 2 root root 0 2007-02-27 15:25 002 -r--r--r-- 1 root root 0 2007-02-27 15:55 devices /proc/bus/usb/001: total 0 -rw-r--r-- 1 root root 43 2007-02-27 15:25 001 /proc/bus/usb/002: total 0 -rw-r--r-- 1 root root 43 2007-02-27 15:25 001 -rw-r--r-- 1 root root 43 2007-02-27 15:25 002 -rw-r--r-- 1 root root 57 2007-02-27 15:25 004 -rw-r--r-- 1 root root 52 2007-02-27 15:55 006

There are no files in the example owned by ups. This indicates hotplug isn't working correctly. To do a workaround, run upsdrvctl, upsd, and "newhidups" as root using the -u root option as shown below, rather than as the "ups user" as this is intended to run.

For the following, if your computer is plugged into the UPS, unplug the computer's power cord from the UPS and plug it directly into AC power. That way, you can run the UPS with a dummy load. Otherwise, when you give your UPS a shutdown command with the computer plugged in, both the UPS and the computer it's powering will shut down. This could damage both the computer and your filesystem.

Quick tip: Plug a lamp into the UPS to provide the dummy load where you can see it; this will indicate whether the UPS has shut down. DRIVER TEST:

If hotplug works:

# /lib/nut/newhidups -DD -a belkin-ups

should give the same results as shown below.

# /lib/nut/newhidups -u root -DD -a belkin-ups Network UPS Tools: New USB/HID UPS driver 0.28 (2.0.4) debug level is '2' Checking device (050D/0551) (002/003) - VendorID: 050d - ProductID: 0551 - Manufacturer: Belkin - Product: UPS - Serial Number: unknown - Bus: 002 Trying to match device Device matches failed to claim USB device, trying 2 more time(s)... detaching kernel driver from USB device... trying again to claim USB device... HID descriptor retrieved (Reportlen = 424) Size read for the report descriptor: 424 Report descriptor retrieved (Reportlen = 424) Found HID device Report Descriptor size = 424 Detected a UPS: Belkin/UPS Using subdriver: Belkin HID 0.1 Path: UPS.BELKINConfig.BELKINConfigVoltage, Type: Feature, Value: . . . (many UPS variables omitted for space reasons) =>Got 1 HID Objects... find_hid_info: unknown variable: UPS.PowerSummary.RemainingCapacity upsdrv_updateinfo... Waiting for notifications...

If the text output on screen when running the driver gets this far, then the driver works. If neither hotplug nor running as -u root works, check your UPS vendor/device IDs against the list of UPS devices found in the udev rules by running the lsusb "list connected USB devices" utility:

alizard@terrarium:~$ lsusb Bus 002 Device 001: ID 0000:0000 Bus 001 Device 004: ID 050d:0551 Belkin Components Bus 001 Device 005: ID 04a9:220e Canon, Inc. CanoScan N1240U/LiDE 30 Bus 001 Device 003: ID 04a9:1094 Canon, Inc. PIXMA iP3000x Printer Bus 001 Device 002: ID 058f:9254 Alcor Micro Corp. Hub Bus 001 Device 001: ID 0000:0000

The above ID names are in vendorID + deviceID format. You should be able to figure out which one matches your UPS easily. Check this against the list of UPS devices available within


from the downloaded and unpacked source. The match between a UPS device in the utility output above and in the udev rule list in 025_nut-usbups.rules is what you'll see in a device that's workable, in the example rule below, see idVendor=050d and idProduct=0551, just as lsusb showed above. Of course, the vendor and product ID's you want are the ones that match your UPS as shown by lsusb above.

SYSFS{idVendor}=="050d", SYSFS{idProduct}=="0551", MODE="664", GROUP="@RUN_AS_USER@"

The following command should shut down UPS output power. If hotplug works:

# /lib/nut/newhidups -k belkin-ups

But if hotplug doesn't work:

# /lib/nut/newhidups -u root -k belkin-ups

will shut down the UPS.

DRIVER AND DAEMON TEST: # /sbin/upsdrvctl start belkin-ups terrarium:/etc/nut# upsdrvctl -u root start belkin-ups Network UPS Tools - UPS driver controller 2.0.4 Network UPS Tools: New USB/HID UPS driver 0.28 (2.0.4) Detected a UPS: Belkin/UPS Using subdriver: Belkin HID 0.1 # upsd -u root Network UPS Tools upsd 2.0.4 Connected to UPS [belkin-ups]: newhidups-auto Synchronizing...done upsc terrarium:/etc/nut# upsc belkin-ups@localhost battery.charge: 100 battery.charge.low: 30 battery.charge.warning: 30 battery.runtime: 120 battery.type: PbAc battery.voltage.nominal: 12 . . . ups.type: offline upscmd upscmd -l # upscmd -l belkin-ups@localhost Instant commands supported on UPS [belkin-ups@localhost]: test.battery.start.quick - Unavailable test.battery.start.deep - Unavailable test.battery.stop - Stop the battery test beeper.on - Enable the UPS beeper - Disable the UPS beeper - Turn off the load immediately terrarium:/etc/nut# upscmd # upscmd belkin-ups@localhost test.battery.start.quick # upsmon Network UPS Tools upsmon 2.0.4 UPS: belkin-ups@localhost (master) (power value 1) Warning: ignoring duplicate UPS [belkin-ups@localhost] Using power down flag file /etc/killpower KNUTCLIENT—GUI UPS MONITORING UTILITY:

Below, you'll see the setup screen for a KNutClient user configuration:

Open KNutClient. I found it in Start Menu > Lost+Found > knutclient. KDE may put it somewhere else in your system, so you may need to go through the menus until you find it.

Once KNutClient is opened, click Settings (top menu) > Configure knutclient. Once you have it open, make sure that voltage (120 or 240) and frequency (50 or 60 Hz) radio buttons are set to match your area. (In the screenshot above, they are obscured by the user-configuration screen.)

This will get you to the above open windows. Click UPS window on the left menu in the Preferences window. Then click Add (user) on the right. Next, click edit, and the bottom right window shown above will open. Enter the UPS "localhost" (or whatever matches where it really is) address, the UPS name, and either the admin or user usernames from upsc.conf .

Next, select the UPS variables you want to monitor visually from the pulldown menus. Each must match a display variable from the list output from upsc; otherwise, no gauge corresponding to live UPS data will display. You may be able to display parameters from your UPS that won't work from my UPS; what will or won't display is UPS device-specific.

Below, see the green "UPS Online" indicator and the AC input voltage, battery charge, and percentage of full load analog gauge displays, Basically, what is shown here is a UPS working properly:

Instant commands work from KNutClient, but not reliably. To access them, pull down the File menu and open Running Instant Commands. There's a pulldown menu; try commands that look interesting. "Quick battery test" is the easiest way to see if it's responding to commands. Caution: "" turns off the UPS suddenly, which is a very bad idea if the UPS is connected to a computer.

The workaround for non-working instant commands in KNutClient: upscmd belkin-ups@localhost command


If you've successfully run

upsdrvctl, upsd, upsmon

, then you're ready to have NUT come up on startup.

# nano /etc/rc.local upsdrvctl start belkin-ups upsd upsmon upsdrvctl -u root start belkin-ups upsd -u root upsmon $ /bin/ps -ef | grep ups root 2642 1 0 Mar03 ? 00:00:00 /usr/sbin/cupsd root 3082 1 0 Mar03 ? 00:00:00 /lib/nut/newhidups -a belkin-ups -u root root 3086 1 0 Mar03 ? 00:00:00 upsd -u root root 3089 1 0 Mar03 ? 00:00:00 upsmon ups 3090 3089 0 Mar03 ? 00:00:00 upsmon alizard 21405 21386 0 01:22 pts/1 00:00:00 grep ups COMPUTER SHUTDOWN: # upsmon -c fsd COMPUTER AND UPS SHUTDOWN: COMPUTER SHUTDOWN AND REBOOT: stay SIDEBAR: WHERE TO GET HELP WITH NUT AND UPS ON LINUX $ man upsd.conf

There is also the /usr/share/doc/nut/docs directory which also contain NUT documentation.

Here are some other resources:

* General NUT Information Resources: This page will direct you to a lot of the information on how to use this program for server/network installations and other topics not covered here due to space limitations.

* MGE and NUT How-To: If you're one of the increasingly rare serial UPS users, this is a good place to start.

* NUT UPS/USB Tutorial: This is a good place to start for a USB-connected UPS, which is what you're probably using.

* Nut-upsuser Mailing List: A good place to find the experts.

A. Lizard is an Internet consultant in the San Francisco Bay Area. He has written for technology magazines and Web sites since 1987.