Network UPS Tools (NUT) - zbrewer/homelab GitHub Wiki
I'm using an old APC Back-UPS ES 750 to power my ISP's ONT and a few other devices outside of my server rack. This can't be monitored by any of the devices it is powering (or over the network) directly so I installed Network UPS Tools (NUT for short) on an old first-gen Raspberry Pi by following this guide. This allows me to monitor the UPS over the network and shut it down when the low battery threshold is reached.
In addition, I have an Eaton 5PX-2200RT with an Eaton Network Card-MS installed in my server rack to power everything there. I still use NUT to monitor this UPS from the servers that it protects, but this time via SNMP connection to the Eaton UPS's network card instead of direct USB. This allows each server to connect to the UPS directly instead of having to communicate with (and host) a central NUT server for this UPS. In addition, it allows me to configure the behavior for each server (such as the low battery threshold) independently, if desired.
Start by setting up Linux on whatever machine will be monitoring your UPS. This could already be done (for example, if monitoring from Proxmox or TrueNAS) but you could also create a new Linux LXC or VM somewhere.
If setting up a new Raspberry Pi for monitoring, install the Raspberry Pi OS using the latest installer from their website. Headless install mode is particularly convenient to set up the installed OS on the SD card with an SSH server, password, and IP address so that you never have to plug a monitor in.
After installing the OS, SSHing in, and ensuring that all of the packages are updated. If connecting the UPS via USB, plug it in and check that it is detected by taking a look at the output of:
$ lsusb
Alternatively, configure SNMP in the settings of the UPS's network card (ideally SNMP v3 so that there is some authentication) and test to make sure that it can be reached from the server on which NUT will be installed. This may involve configuring the firewall to allow the NUT server to reach the UPS's network card on the appropriate port (usually UDP and port 161). The connection test can be performed by installing the snmp
package and then using a command such as the following:
$ snmpwalk -v3 -l authNoPriv -u <user> -A <password> <ip_address> <base_oid>
See the man pages for more command options.
Assuming the UPS is detected/reachable, install the NUT packages from the official repositories with the following command:
$ sudo apt-get update && sudo apt-get install nut nut-client nut-server
Next, configure the UPS in NUT by editing /etc/nut/ups.conf
to contain the following at the bottom (the text in the brackets is the name of the UPS and can be whatever you like):
[apc-ups]
driver = usbhid-ups
port = auto
desc = "APC Back-UPS ES 750"
If using an Eaton UPS (or any other that supports monitoring/control over SNMP), the snmp-ups
driver should be used. This requires installing the nut-snmp
package (in addition to those listed above) and configuring NUT with the access credentials such as in the example below. The full documentation is available here.
[eaton-5px2200rt]
desc = "Server Room Eaton 5PX2200RT"
driver = snmp-ups
port = <UPS network card IP address>
mibs = auto
snmp_version = v3
secLevel = authNoPriv
secName = readuser
authPassword = <password>
Also note that, if you're planning on overriding the low battery threshold on the Eaton UPS, it won't set the low battery flag when this new threshold is reached. Instead, you'll need to configure this here in ups.conf
on the NUT server side. See the instructions below for how to do this.
Next, edit /etc/nut/upsmon.conf
to contain the following:
# MONITOR <system> <powervalue> <user> <password> ("master"|"slave")
MONITOR apc-ups@localhost 1 monuser <password> master
In this example, apc-ups
is the name configured above, upsmon
will be the monitoring user, and <password>
will be replaced with the password. Note that the username and password here can be anything and will only be used by secondary clients of this NUT server, if any (see below for instructions on how to set that UP). Next, edit /etc/nut/upsd.users
to contain the same user:
[monuser]
password = <password>
upsmon master
With that done, if this NUT server will be a primary host that other NUT servers connect to, enable the server mode by changing the last line of /etc/nut/nut.conf
to:
MODE=netserver
If, on the other hand, this NUT server will operate in standalone mode (no clients connected to it), you can make the last line of /etc/nut/nut.conf
:
MODE=standalone
Finally, if using the netserver
mode, edit /etc/nut/upsd.conf
to set the monitoring interface (see this thread). This file should contain:
LISTEN 127.0.0.1 3493
LISTEN ::1 3493
LISTEN 0.0.0.0 3493
Next, restart the server and type:
$ upsc <ups-name-from-ups.conf>@localhost
Information about the UPS should be printed out and the basic install should be complete. Remote servers can now be set up to read this data (using the username and password configured) if netserver
mode was used.
If a web server for monitoring the UPS status is also desired, the following steps can be taken.
First, install the required packages:
$ sudo apt-get install apache2 nut-cgi
Next, edit /etc/nut/hosts.conf
to contain:
MONITOR <ups-name>@localhost "Readable UPS Name"
Now, enable CGI in the web server and restart it:
$ a2enmod cgi
$ systemctl restart apache2
Finally, uncomment the following line in /etc/nut/upsset.conf
:
### I_HAVE_SECURED_MY_CGI_DIRECTORY
The web interface should now be accessible at http://<ip_address>/cgi-bin/nut/upsset.cgi
and the monitoring page will be at http://<ip_address>/cgi-bin/nut/upsstats.cgi
. The username and password required to access them are the same as configured earlier.
TrueNAS has a NUT integration built-in that can be configured via the GUI. See the instructions here for more information.
If you would like additional clients to monitor a primary NUT server (that has been set up in netserver
mode), they can be configured as NUT clients. This is useful in cases such as with the APC UPS where the UPS may have a single USB connection but you want it to be monitored by more than one server. Upon reaching a low battery state, the primary NUT server will signal each of the clients to shutdown before shutting itself down and turning off the UPS..
To do this, first install the nut
package:
$ sudo apt-get install nut
Next, edit the /etc/nut/nut.conf
file so that the mode is set as netclient
.
Finally, edit /etc/nut/upsmon.conf
to contain the appropriate line to monitor the remote server. This will be in the form:
MONITOR <ups-name@host> <powervalue> <username> <password> ("primary"|"secondary")
In the case of my Eaton UPS, this looks like:
MONITOR [email protected] 1 monuser <password> secondary
Finally, with that configured, start the nut client with the upsmon start
command. You should be able to confirm that it is communicating with the primary NUT server using the upsc ups-name@host
command (for example, upsc [email protected]
). This should print the UPS information.
By default, when a low battery threshold is reached (based on either time remaining or battery percentage, whichever happens first) the NUT server(s) connected to that UPS will begin shutting down. What exactly happens here depends on the mode that it is running in.
If the NUT server is in standalone
mode, it will shut itself down and signal the UPS to turn off when it is done.
If it is in netserver
mode, it will signal its clients (running in netclient
mode and with the secondary
designation in their MONITOR
stanza in /etc/nut/upsmon.conf
) to shut down and then wait a pre-designated amount of time for those operations to complete. It will then shut itself down and signal the UPS to turn off when it is done.
Finally, if it is in netclient
mode, it will receive the shutdown command from the primary server when the primary server determines that the low battery condition has been reached and it will shut itself down.
This behavior can be configured based on the options below:
By default, the UPS defines the low battery threshold and NUT respects this. More advanced UPSs (such as the Eaton UPS I use) allow this threshold to be configured directly on the UPS; however, it doesn't set the low battery flag to initiate server shutdown on the UPS side. Instead, this value must be set in NUT and it must be told to ignore the low battery flag from the UPS. This is also useful when using simpler UPSs (such as the APC UPS I have), where this may not be a configuration option at all. Finally, this technique is also useful if there are some clients that you would like to turn off before the UPS-defined low battery threshold has been reached (for load shedding).
In order to change the default low battery threshold, edit the configuration for the UPS in the /etc/nut/ups.conf
file. Add the ignorelb
option to ignore the UPS's low battery status and then specify a new percentage remaining with override.battery.charge.low
and/or a new time (in seconds) remaining with override.battery.runtime.low
. For example, for the APC UPS, this might look like:
[truenas-ups]
driver = usbhid-ups
port = auto
desc = "APC Back-UPS ES 750"
ignorelb
override.battery.charge.low = 60
override.battery.runtime.low = 300
Note, however, that this is only an option if NUT is running in standalone
or netserver
mode and that changes to the netserver
will affect its clients as well.
These options can be reloaded without restarting the server using the upsdrvctl start
command.
Sometimes, it may not be desirable to shut down the UPS when the server running NUT shuts down. For example, if there are many clients of an SNMP UPS with different shutdown thresholds configured, the clients that shutdown earlier shouldn't cause the UPS to power off since there are still other clients running. On the other hand, in a simple example like with the APC NUT server, shutting down the UPS might be exactly what is desired.
Direct connections likely support UPS Shutdown by default while SNMP connections with a read-only user likely won't allow this. That being said, you can test whether or not shutting down the UPS itself from a given NUT server works but using the command: upsmon -c fsd
. This will attempt to power cycle the UPS (as if power was lost and then restored). If the UPS power cycles, NUT will shut it down after the NUT server shuts off. If the UPS doesn't shut down, NUT won't be able to turn it off.
In the event that NUT is able to turn the UPS off, but you don't want it to, you can comment out the POWERDOWNFLAG
line in /etc/nut/upsmon.conf
to prevent the POWERDOWN file (flag) that is checked at shutdown from being written. Alternatively, you could remove or comment out the line (at least the /sbin/upsdrvctl shutdown
portion that actually shuts down the UPS) in the shutdown script located at /usr/lib/systemd/system-shutdown/nutshutdown
.
UPS statistics can be exported to InfluxDB using the native UPSD plugin. The documentation specifies the input plugin parameters that should be set but this mostly just amounts to setting the NUT server IP address, port, and login credentials. The Telegraf config file I use can be found here.
Telegraf can then be run on the same machine as NUT (using localhost/127.0.0.1 as the server
) or via Docker. Installing Telegraf natively can be accomplished as per the Telegraf docs. A Docker setup can be completed using the files here. In the Docker case, put the telegraf.conf
(renamed to apc-network-shelf-telegraf.conf
), docker-compose.yaml
, and env
(rename to .env
) files in a directory together. Set the username, password, and InfluxDB token in the .env
file and remove any containers from docker-compose.yaml
file that aren't needed. Start Docker with docker compose up -d
from the same directory.
These metrics can then be displayed in Grafana using the dashboard configuration here.