I bought an “Eaton 3S” uninterruptible power supply (UPS) some time ago. It is supposed to support my servers with power in case of a power loss. I also wanted to get notified about those “power down” events, so I looked for an open-source software to monitor the UPS hardware. I found the “Network UPS Tools” (NUT). In this article, I describe some of the pitfalls I came across.
The UPS can be connected via USB cable (see Fig. 1) to the computer to be monitored by NUT. With the NUT-daemons installed and configured, you can handle UPS-events like “ON BATTERY” and “ONLINE”. This requires functioning detection of the UPS by the NUT-drivers. Unfortunately, I was unable to build a working setup on my “Alpine Linux” servers with the existing software packages, while an older “Debian” server had no problems at all. The NUT-drivers on my “Alpine Server” could not detect the UPS. This was the beginning of a series of some longer nights to fix the problem.
There are several software components (see Fig. 2) relevant for this article. The description below is based on information from the “NUT user manuals”.
-
UPS drivers provide a common interface between the physical UPS and the
upsd
-server. The driver translates the native protocol of the UPS to a common format. -
upsd
connects to each UPS driver to serve data from the drivers to the clients.
Requisites for readers
This article is written for people with a basic understanding in “Linux” operating systems and containers. Writing this article, I assume the reader does not have “Alpine Linux” (Alpine) running on her/his workstation. The instructions given here should work for most Linux distributions. In this article, I also assume you’ve got an Alpine diskless setup.
I added tags to clarify which commands have to be executed on which of your systems (see Fig. 3):
- Workstation: Your local desktop computer or laptop which you use to run the container.
- Server: The server where NUT will be set up.
To make this article easier to read, I do not prefix commands run as root
with sudo
. Instead, I use the following syntax for the commands in this
article. But for your daily business, I definitively recommend using the
sudo
-command.
$ command
: Running the command as a normal or admin user# command
: Running the command asroot
Reasons for my problems
Alpine uses mdev
instead of (e)udev
by default to set up
“USB”-devices. Currently, mdev
is unable to set up permissions correctly for NUT. Additionally, the NUT-package was missing some required package dependencies — see this
merge request for the required changes to the
nut
-package. It was merged on 05/09/2021.
Install monitoring software
-
Server Connect the UPS to the server
Please connect your UPS via USB cable to your server.
-
Workstation Connect to your server via SSH from your local computer
Please start a new shell on your local system and run the following command.
$ ssh root@<IP address of your server>
-
Server Add repository
To make your UPS device work with Alpine, you need to set up
eudev
andnut
. First, you need to make theedge/testing
-repository available to your system.vi /etc/apk/repositories
@edge-testing http://mirror1.hs-esslingen.de/pub/Mirrors/alpine/edge/testing
-
Server Install packages
After that, you can install the required packages.
# apk update # apk add nut@edge-testing
-
Server Attach the UPS via USB cable to your computer
-
Server Verify setup
As of the time writing this article, this failed for no obvious reason.
# upsdrvctl start Network UPS Tools - UPS driver controller 20210212-471-g17c662d69e Network UPS Tools - Generic HID driver 0.41 (20210212-471-g17c662d69e) USB communication driver 0.33 No matching HID UPS found
Setup troubleshooting
-
Server Monitor the kernel ring buffer
You need to install and use
dmesg
to get some more information.# dmesg -w
-
Server Re-attach the UPS to your computer
-
Server Monitor the kernel ring buffer
Upon having the UPS connected to my computer, I saw the following logs. Everything looked fine. The device was detected by the kernel.
# dmesg -w 2021-07-07T06:25:44.679088+02:00 host-xy kernel: [ 4.420351] usb 1-1: New USB device found, idVendor=0463, idProduct= ffff, bcdDevice= 1.00 2021-07-07T06:25:44.679089+02:00 host-xy kernel: [ 4.420360] usb 1-1: New USB device strings: Mfr=1, Product=2, Seria lNumber=4 2021-07-07T06:25:44.679090+02:00 host-xy kernel: [ 4.420365] usb 1-1: Product: Eaton 3S 2021-07-07T06:25:44.679091+02:00 host-xy kernel: [ 4.420369] usb 1-1: Manufacturer: EATON 2021-07-07T06:25:44.679092+02:00 host-xy kernel: [ 4.420373] usb 1-1: SerialNumber: 000000000
-
Server Check the visibility of the device with
lsusb
I was disappointed to see, that there’s no UPS-device when I ran
lsusb
.# lsusb Bus 001 Device 003: ID 0781:5583 SanDisk Corp. Ultra Fit Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
If you run
lsusb -t
, it will print the whole USB device tree. With this parameter given,lsusb
prints out an entry for the UPS-device.# lsusb -t : Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/7p, 5000M : Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/9p, 480M |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 4: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 480M
-
Server Install the
hidapi
-packageMaking USB devices available in Alpine requires some extra software. Without the required package, you won’t see your device with
lsusb
.# apk add hidapi
After installing the
hidapi
-package, I could see the UPS in the output oflsusb
.# lsusb Bus 001 Device 002: ID 0463:ffff MGE UPS Systems UPS
-
Fix
udev
-setupPlease install all required packages. For Alpine, the
eudev
-package provides a similar functionality as the normaludev
-package provided bysystemd
.# apk add eudev udev-init-scripts-openrc
Next, disable the
mdev
- and enable theudev
-service.# rc-update rm mdev sysinit # rc-update add udev sysinit
Start the
udev
-service.# rc-service udev start
We need to fix the wrong file path for the
udev
-rule file –/usr/lib/udev/rules.d/rules.d/
. The/lib/udev/rules.d
-directory would the correct place for the new rules. Unfortunately, this directory is not part of the defaultlbu
-configuration of an Alpine diskless setup. Instead, move the file to/etc/udev/rules.d/
.# mv /usr/lib/udev/rules.d/rules.d/* /etc/udev/rules.d/
Reload and apply
udev
-rules before starting the NUT-drivers. Please add the following line, right afterMODE=xxx
. This is just a hack to work around the missing integration ofudevadm
intoinitramfs
. There’s a merge request to fix this permanently.# /etc/nut/nut.conf # MODE=xxx udevadm control --reload-rules && udevadm trigger
-
Reload and apply
udev
-rulesReload and apply
udev
-rules to check if the USB device nodes were correctly created. Check if the correct group for the device node is set. The group needs to benut
.# udevadm control --reload-rules && udevadm trigger
$ ls -al /dev/bus/usb/*/* crw-rw-r-- 1 root nut 189, 1 Jul 13 23:44 /dev/bus/usb/001/002
-
Server Start NUT-driver
Please start the NUT-driver again.
# upsdrvctl start Network UPS Tools - UPS driver controller 20210212-471-g17c662d69e Network UPS Tools - Generic HID driver 0.41 (20210212-471-g17c662d69e) USB communication driver 0.33 Using subdriver: MGE HID 1.39
-
Server Add services to default runlevel
To make the services start on each but, activate the following NUT-services.
# rc-update add nut-upsd # rc-update add nut-upsmon
-
Server Commit changes with
lbu
This step is required for diskless setups – otherwise all configuration files are lost with the next reboot.
# lbu commit
-
Server Start
upsd
-# rc-service nut-upsd start
In the logfile
/var/log/messages
you should see something similar to the following output.2021-07-14T00:20:07.997234+02:00 host1 usbhid-ups[19178]: Startup successful 2021-07-14T00:20:08.004792+02:00 host1 upsd[19181]: listening on 127.0.0.1 port 3493 2021-07-14T00:20:08.005220+02:00 host1 upsd[19181]: Connected to UPS [myups]: usbhid-ups-myups 2021-07-14T00:20:08.007036+02:00 host1 upsd[19181]: allowfrom in upsd.users is no longer used 2021-07-14T00:20:08.007441+02:00 host1 upsd[19182]: Startup successful 2021-07-14T00:20:08.084491+02:00 host1 upsmon[19229]: Startup successful 2021-07-14T00:20:08.085015+02:00 host1 upsmon[19230]: Init SSL without certificate database
Find some more documentation
Some more information can be found in the libusb FAQs and in the hidapi README.
Conclusion
Now I have got a UPS device, which can be monitored with NUT.