Understanding the Network UPS Tools (NUT)

Introduction

Network UPS Tools , or NUT, is a suite of software for management of power supply equipment. It often works better, and is definitely more flexible, than expensive software from the UPS vendor. I use it myself, both at home and on the job. In the process of understanding it, and then explaining that to others, I have developed some documentation, and can share that, along with my configuration files.

Click/tap an image to open it in full resolution.

Terminology

UPS
Uninterruptible Power Supply. A piece of equipment that sits between the wall outlet and the computer, and keeps the computer running even when the lights go out. Also called a "battery backup". Since the batteries have limited capacity, in an extended outage, most UPS models can signal the computer to save and shut down gracefully before the batteries die. That's where NUT comes in.
daemon
A process (running software) that sits in the background and provides services to the user or other software. "daemon" is the Unix term; Microsoft uses the more boring term "service".
IPC
Inter-Process Communication. Generically, this refers to one piece of running software talking to another in some way. This can be over a network, or locally. There are various standards and protocols for this. NUT uses several different processes, so it depends heavily on IPC-the-concept. (This document does not use "IPC" to refer to "System V IPC".)
UPS Cable
The diagrams that follow show a "UPS Cable". This cable is used for communications/signaling between the UPS and the computer. Traditionally, this would be an RS-232 serial cable. More recently, it is often USB. It can even be a network connection with SNMP.

NUT Architecture

NUT is designed to be as modular and flexible as possible. As a result there are a lot of components — daemons (service processes), config files, utility commands, etc.

Processes

The following diagram illustrates the major daemons in a typical NUT deployment. Most of them are optional. While this diagram shows a single computer, the daemons can be distributed across multiple computers, with multiple instances of some daemons as approximate.

NUT Process Architecture diagram
Process Description
Svc Mgr Service manager. The daemon that starts other daemons. Not part of NUT; provided by OS. In my case, systemd. Could also be init, /etc/rc.net, etc. On Microsoft Windows, this would be the Service Control Manager (SCM).
upsd Master daemon for NUT. Handles IPC and access control between other NUT daemons, starts UPS drivers. Provides no events/logging by itself.
UPS Driver An interface driver lets upsd talk to each type of UPS. There are different drivers for various product lines from different manufacturers, along with generic drivers for things like USB and SNMP.
upsmon Monitors UPSes. Basic event response: Logging, user alerts, system shutdown on low battery. Limited flexibility. Can call upssched to do more.
upssched Optional. Started by upsmon. Provides timers and custom event response.
CMDSCRIPT Called by upssched in response to events and/or timers. The actual name of the script, and the contents, are supplied by the person configuring NUT. See upssched below for more.
upslog Optional. Logs statistics (UPS data, like load and battery level). See Collecting UPS Statistics below for more.

Control

NUT allows you to have multiple computers being powered by one UPS (or set of UPSes) all receive UPS status information and events. Several utility commands are also provided to query daemon and UPS status, issue commands, and write UPS settings (when supported).

NUT Control Architecture diagram

The above diagram illustrates a UPS powering three computers, each with a monitoring daemon for automatic shutdown. In a single-computer installation, the concept is the same, without the secondaries.

In the above diagram, note how while several utility command provide logical access to the UPS, all communications are actually routed through the upsd daemon.

Utility Commands

Command Description
upsdrvctl Manual start/stop/restart/etc of UPS interface drivers
upsc Query parameters and operating data for a UPS.
upscmd Tell the UPS to do something, such as run self test, or shutdown the power output. Not all UPS models support this.
upsrw Read (query) or write (set) operating parameters. For example, the battery level or runtime remaining for the low battery alarm. Not all UPS models support this, either.

Files

NUT uses a number of different configuration files — roughly one for each daemon.

Traditionally, config files live in /etc/ on nix systems. Depending on how NUT was built, they may instead be in /usr/local/etc/ or /opt/nut/etc/ or whatever the local convention is. On Windows, C:\Program Files\NUT\ups\etc\ is the default.

NUT Files diagram
File Description
upsd.conf Configures the master daemon. IPC parameters, file locations, networking, certificates.
upsd.users Usernames and passwords for NUT IPC. Security-sensitive.
ups.conf Configures the specific UPS in use, and how to communicate with it (port, etc.). Used by upsd to learn what drivers to start. The drivers use it to obtain UPS details.
upsmon.conf UPS(es) to monitor, with username/password. Action flags for each event type.
upssched.conf Action names for each event type, timers, and actions names for each timer.
nut.conf (Not shown in diagram) Configures daemon startup scripts on various Unix/Linux flavors.

upssched

The optional upssched daemon allows one to define custom actions in response to UPS events, such as power-failure or low-battery.

The upssched.conf file lists events and the action to take. Actions here are limited to executing the command script, starting a timer, or stopping a timer.

One defines the path to the CMDSCRIPT to run. There can be only one script defined, but different arguments can be passed to it from upssched based on the event and/or timer. For example, the following says to execute the CMDSCRIPT with an argument of foo when any UPS switches to battery:

AT ONBATT * EXECUTE foo

When starting a timer from upssched.conf, you give it an arbitrary name, along with a delay in seconds. Stopping the same name cancels the timer. If the timer expires without being stopped, the CMDSCRIPT is called with the name of the timer as an argument.

Since any event or timer leads to a single CMDSCRIPT, all but the simplest of designs will use logic within the script to switch based on the event/timer argument passed from upssched.

For an example, see My Home Config below, where the CMDSCRIPT is called upsevent.

My Home Config

As a concrete example, I present the NUT config I've got set-up at home. The UPS powers my main desktop PC, as well as my home router and cable modem.

Note that while NUT itself is cross-platform — running on Linux, Unix, Windows, Mac, toasters, etc. — my upsevent script is nix-specific, being a shell script that uses wall(1) and signals.

Diagram

The following diagram shows how all the pieces fit together for me. It is roughly the union of the previous three diagrams, except that generic placeholders for the UPS driver and such have been filled-in with the things I'm using.

Diagram of my NUT configuration at home

Collecting UPS statistics with upslog

Startup and run

Debian provided no in-the-box facility to start or configure the upslog daemon, so I put these together:

File Description
upslog.rc Wrapper script to start the upslog daemon with parameters as specified in upslog.conf.
upslog.conf Read by upslog.rc to specify command-line arguments to the upslog daemon. Using a separate file keeps configuration segregated from the script itself.
nut-logger.service Debian being a systemd-based distribution, we also need a unit file to run the upslog daemon.

Log data format

upslog outputs a simple text file. I customized the log format to include all the data my UPS provides, and put the variable status field at the end. A sample log file follows below. I manually prepended a header line to this example. Again, the header and field names are my own creation (although there isn't much room for creativity here).

YYYY-MM-DD HH:MM:SS Vin   Fin   QQ Vbat  chrg% run  Tups  load% Vout  status
2022-09-22 00:00:37 120.2 60.00 FF 27.60 100.0 1080 023.4 015.6 120.2 OL RB

The fields in my log format are:

Symbol Description
Vin Input voltage. Volts the UPS is getting from the wall outlet.
Fin Input frequency. Hertz the UPS is getting from the wall outlet.
QQ Power Quality. I've only ever seen "FF", and what it means isn't clear. Possibly my UPS is reporting a bogus value.
Vbat Battery voltage.
chrg% Percent charge. An estimate on the present charge, vs nominal maximum capacity of the battery. Generally derived from the battery voltage.
run Runtime remaining, in minutes. Many UPS models, mine included, rather badly overestimate their runtime.
Tups UPS temperature.
load% Percent load. Present current (amperage) being demanded by load equipment, vs nominal maximum capacity of the UPS. Some models give an absolute value in amps or watts; mine does not.
Vout Output voltage. Volts the UPS is giving to my equipment. This is generally either 120 or zero.
status A series of flags that indicate status of the UPS and system. The sample log line shows my UPS is on-line (OL, running from wall current) and needs the battery replaced (RB).

Status flags

Status flags that can appear in upslog apparently include:

Flag Description
OL Online. Power is provided by the wall outlet (line).
OB On Battery. Power is provided by the UPS battery and inverter.
LB Low Battery. The estimated charge capacity of the battery, and thus the estimated runtime, are below a threshold. This can occur when on-line or on-battery. When also on-battery, a LB condition generally causes NUT to initiate shutdown.
HB High Battery. The battery voltage is above a threshold. This is a relatively unusual problem. Typically it would indicate a bad battery or a malfunctioning UPS.
RB Replace Battery. The UPS has decided the battery is no-good. This may be based on time in service, number of charge cycles, the results of a self-test, or anything else.
CHRG Battery Charging. The battery is not fully charged, so the UPS is charging it. My UPS never indicates this to NUT.
DISCHRG Battery Discharging. Self-explanatory, but I don't know the difference between this and "OB". My UPS never indicates this to NUT.
BYPASS Bypass Active. The power protection (inverter, regulators, etc.) in the UPS has been bypassed, and the load is electrically connected directly to the wall outlet. Typically occurs if the UPS detects an internal fault. Most small UPSes, mine included, lack bypass capability.
ALARM The UPS is indicating a trouble condition, not further specified. This could be low or bad battery, high temperature, an internal fault, UPS on fire, etc.
TEST Self Test. Most UPSes can perform a brief self-test, periodically and/or on command. This indicates such a test is in progress.
CAL Runtime Calibration. Some UPSes can deliberately run the battery from full charge down to low, in order to get a better idea of the full charge point and runtime capacity.
OFF Offline. The UPS is not providing power to the connected equipment load, for whatever reason.
OVER Overloaded. Connected equipment load is drawing more current (amps) than the UPS is designed to provide. A small and brief overload may be tolerable. A prolonged or large overload typically results in the UPS output being turned off.
TRIM Trimming Voltage. Input voltage is somewhat higher than nominal; the UPS is correcting for it. Not all UPSes can do this; those that do not can only switch to battery.
BOOST Boosting Voltage. Input voltage is somewhat lower than nominal (brownout); the UPS is correcting for it. Not all UPSes can do this; those that do not can only switch to battery.
FSD Forced Shutdown. The UPS has turned off output power in response to softgware command (typically from NUT).
NOCOMM No Communications. NUT is not receiving status information from the UPS. This may mean the UPS signal cable is disconnected, the wrong UPS parameters are configured, the UPS is faulty, a network problem (for SNMP), etc.
WAIT Waiting. This has appeared when the daemons were just started; I presume it means the communications channels are still being initialized, so status is not available yet.

Some of these status indications will only be logged by NUT if the NUT monitoring computer has a separate power source from the UPS indicating them. For example, in my case, "OFFLINE" would result in my desktop immediately losing power, taking NUT with it.

Visualizing with gnuplot

I used space-separated fields in the log file. One benefit is this makes it easily parsed by gnuplot. My ups.gnuplot file generates this graph:

Graph of UPS statistics with gnuplot

Event response with upssched

NUT includes built-in facilities to notify users that a UPS is on battery, as well as to initiate a graceful shutdown in the event of low battery. It also provides the upssched daemon, which allows one to customize event response. I used this to achieve multiple features:

To do this, in addition to the standard upssched.conf, I created the following files:

File Description
upsevent This is my CMDSCRIPT (as explained in "upssched" above). It's a Unix shell script, and contains a giant case block to switch based on the argument.
noearly A command I can run to suppresses early shutdown.

Immediate logging

I have upslog logging UPS statistics (line voltage, battery level, etc.) once a minute. However, when an event occurs (particularly switching to or from battery), it's often useful to know what the values are at that moment. For example, if a brownout lasts less than a minute, I would likely never see the low line voltage value.

To address this, I have most UPS events declared to execute in upssched.conf. For all of those events, upsevent sends SIGUSR1 to the upslog daemon, which causes it to immediately log current values (independently of the regular log interval).

Deferred warnings

For me, most of my power transients are momentary. Power will blink out for a second or two, then come back on and be fine. I don't want all my terminals filled with wall(1) messages every time that happens.

Thus, I have upsmon configured not to send alerts on transition to battery. Instead, I have upssched start a 15 second timer on transition to battery. On transition back to line, I stop the timer. If the timer expires, it means we've been on battery for more than 15 seconds, and then upsevent sends the wall(1) message.

Early shutdown

I have both my home network equipment and my desktop PC on the same UPS. The desktop uses a lot more power than the tiny router. I can keep the network up for the better part of an hour if the desktop isn't on. With the desktop involved, I get less than 10 minutes.

To get the best of both worlds, I have a timer set up in upssched.conf to fire after a minute on battery. If it fires, upsevent first checks for the existence of /etc/nut/noearly. If that file exists, upsevent does nothing; otherwise, it initiates shutdown.

I also created a tiny script that does "sudo touch /etc/nut/noearly". My /etc/sudoers allows that command to be run without a password. Thus, if I get the warning that the system is on battery power, I can simply type noearly [ENTER] and keep working to the limit of battery power. If I'm not around to do that, or elect not to, the desktop will shutdown to save the battery for the network.

Download

My NUT configuration files

These include everything discussed above (except the binaries). Passwords have been replaced with placeholders. The files are well-commented. You will need to read and customize them regardless.

Names used: I named my UPS "bessie", as it is old and tired but generally reliable, like "Ol' Bessie" the farmer's cow in popular lore. My desktop is named "blackfire".