Every server should have a UPS to protect the system from power outage or over voltage situations and enable controlled shutdown. So do my systems as well. I have one Eaton 5P1500R and two Eaton 5P850R 1U Rack UPS systems running. I do like to monitor them and send out some notifications if any state changes on any UPS. Luckily the UPS provide an USB port to connect to and get the status from it. There is an option for a LAN card but this is more expensive. Such a price might be ok for an company but not really needed for my homelab.

The final solution involves more than just NUT and mosquitto. This part shows how to set up Network Ups Tools on a raspberry pi to monitor a ups and send a notification to a MQTT broker. In part two I show you the second part of my setup and how I use mqtt, node-red and a telegram bot to keep me up to date.

Using a Raspberry PI as NUT server

I do not cover the basic setup of the raspbian OS here. The image of the debian based raspbian distribution is located at raspberrypi.org . I recommend using the “Raspbian Buster Lite” or if you like to have a GUI the “Raspbian Buster with desktop” versions. In fact you do not need any GUI to make this work.

sudo apt-get install nut

This should install the meta package which contains at least nut-client and nut-server. If you like to have a cgi-script to access all the UPS details, you also should make sure that nut-cgi and apache2 is installed as well. The nut-cgi gives you a nice overview like the one below.

Overview all UPS devices Overview one ups device

Configure UPS utils

Below you find the configuration files for NUT I use for my setup. The passwords are not the real ones ;-)

nut.conf

I use the nut installation on the raspberry pi as a network server version. Setting it up that way enables all my servers to get the state of the connected UPS for that particular server. To configure the instance as a server, just set the mode to netserver in /etc/nut/nut.conf.

MODE=netserver

ups.conf

Next you have to configure your attached UPS devices. This also ensures that they are not assigned to a different name depending on the usb enumeration. I use the serial to make sure UPS1 is always UPS1. I also set the option sdorder which ensures that the UPS where the Pi is attached to, gets turned off as the last UPS and all others are turned off before. The shutdown starts with 0 and the last one here is 2.

[ups1]
        driver = usbhid-ups
        port = auto
        serial = G115F?????
        desc = "Eaton 5P 850VA UPS1"
        sdorder = 2

[ups2]
        driver = usbhid-ups
        port = auto
        serial = G115F?????
        desc = "Eaton 5P 850VA UPS2"
        sdorder = 0

[ups3]
        driver = usbhid-ups
        port = auto
        serial = G117F?????
        desc = "Eaton 5P 1500VA UPS3"
        sdorder = 1

upsd.conf and upsd.users

These files are documented well and it should not be difficult to adjust these for your needs. The upsd.conf does set the port and listing address including certificates and the upsd.users defines the users and their access rights. Adjust it to your personal needs.

upsmon.conf

In this configuration file I configure which UPS devices the monitoring daemon should check. As I like to get a notification for all changes on all my UPS boxes, I just enter them all. The line with the parameter NOTIFYCMD is the real interesting one. The script you configure there is the one that gets executed when a notification should be sent. But setting this alone will not be sufficient. To make upsmon call your script, you need to change the NOTIFYFLAG values and add a +EXEC to the end of the line. Also make sure that these lines are no longer comments but real assignments.

MONITOR ups1@localhost 1 upsmon yourpasswd master
MONITOR ups2@localhost 1 upsmon yourpasswd master
MONITOR ups3@localhost 1 upsmon yourpasswd master

NOTIFYCMD /etc/nut/mqttnotify/nutnotify.sh

NOTIFYFLAG ONLINE       SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT       SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT      SYSLOG+WALL+EXEC
NOTIFYFLAG FSD  SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK       SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD      SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN     SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT     SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM       SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT     SYSLOG+WALL+EXEC

nutnotify.sh and mosquitto_pub

Finally you need the script to publish a message to your mqtt broker. Before running the script the package mosquitto-clients needs to be installed. Just run sudo apt-get install mosquitto-clients to do this.

After successfully installing the needed clients, you can edit the script using sudo nano /etc/nut/mqttnotify/nutnotify.sh and use the following example as starting point.

#!/bin/bash
mosquitto_pub -h mqtt.example.com -t "/power/$UPSNAME/notify/$NOTIFYTYPE" -m "$1" -u mqttuser -P mqttpasswd --tls-version tlsv1.1 --cafile /etc/nut/mqttnotify/haefelfinger-ca.crt

As you see, there is a ssl certificate authority file defined. This is because I use a TLS connection to my broker. To make the client trust the host certificate, you may install your own ca certificate or pass it as file here.

NUT defines two environment variables you can use in your script. $UPSNAME contains the name of the UPS that triggers the notification. $NOTIFYTYPE contains the type name of the notification like ONBATT when the plug gets pulled. In $1 you find the message generated by upsmon. These messages can be customized in upsmon.conf as well. So the mqtt topic is based on the UPS name and the notification and the message content is the message generated by upsmon. This offers quite some flexibility on the consumer side.

In this example I also use a username and password to connect to the mosquitto server. Make sure that you restrict the rights on the script as well. To do this use the following commands.

sudo chown root.nut /etc/nut/mqttnotify/nutnotify.sh
sudo chmod 750 /etc/nut/mqttnotify/nutnotify.sh

This way only root and the nut group users ar able to read or execute this file.

You can test your script by running it using the following example as root or nut user.

UPSNAME=UPS1 NOTIFYTYPE=ONLINE /etc/nut/mqttnotify/nutnotify.sh "Testmessage"

This should publish a message with the content Testmessage using the topic /power/UPS1/notify/ONLINE on your mqtt broker.

Summary

At this point you have a NUT installation monitoring your ups devices and sending out some mqtt messages if any of the states change. You may continue on your own way from here on or wait for my second article where I show how to use node-red to get these notifications and pass them over to my telegram bot .