Advertisement

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.

Physical connection between the UPS and the server

Fig. 1: Physical connection between the UPS and the server

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.

Relevant software components for the problems mentioned in this article

Fig. 2: Relevant software components for the problems mentioned in this article

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.

Connections Fig. 3: Connections

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 as root

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 and nut. First, you need to make the edge/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-package

    Making 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 of lsusb.

    # lsusb
    
    Bus 001 Device 002: ID 0463:ffff MGE UPS Systems UPS
    
  • Fix udev-setup

    Please install all required packages. For Alpine, the eudev-package provides a similar functionality as the normal udev-package provided by systemd.

    # apk add eudev udev-init-scripts-openrc
    

    Next, disable the mdev- and enable the udev-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 default lbu-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 after MODE=xxx. This is just a hack to work around the missing integration of udevadm into initramfs. 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-rules

    Reload 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 be nut.

    # 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.

Discussion

If you found a mistake in this article or would like to contribute some content to it, please file an issue in this Git Repository

Disclaimer

The contents of this article are put together to the best of the authors' knowledge, but it cannot be guaranteed that it's always accurate in any environment. It is up to the reader to make sure that all information found in this article, does not do any damage to the reader's working environment or wherever this information is applied to. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, arising from, out of or in connection with this article. Please also note the information given on the Licences' page.