Network UPS Tools (NUT) talks to an uninterruptible power supply, reports its battery and load, and shuts your servers down cleanly before the battery runs out. In this tutorial you will install NUT on Ubuntu 24.04, configure a USB-connected UPS, set up automatic shutdown on low battery, and then let other servers on the same LAN follow the same UPS over the network.

Prerequisites

To follow this guide you need:

  • A physical server running Ubuntu 24.04 LTS with a UPS connected over USB. Most APC, Eaton, CyberPower and Tripp Lite models work with the generic usbhid-ups driver; check the NUT hardware compatibility list for your model.
  • A non-root user with sudo privileges.
  • For the network part (Step 6): one or more additional Ubuntu 24.04 servers powered by the same UPS, on the same LAN.

NUT has three components, all installed by the nut package:

ComponentRole
Driver (usbhid-ups, snmp-ups...)Talks to the UPS hardware
upsdServes UPS data to clients on TCP port 3493
upsmonWatches the UPS status and runs the shutdown

Step 1 - Installing NUT and detecting the UPS

Install NUT from the Ubuntu repositories:

sudo apt update
sudo apt install nut

Check that the system sees the UPS on the USB bus:

lsusb

Look for your UPS vendor in the list, for example:

Bus 001 Device 003: ID 051d:0002 American Power Conversion Uninterruptible Power Supply

Now let nut-scanner suggest a driver configuration:

sudo nut-scanner -U
[nutdev1]
	driver = "usbhid-ups"
	port = "auto"
	vendorid = "051D"
	productid = "0002"
	product = "Back-UPS ES 700G FW:871.O4 .I USB FW:O4"
	vendor = "American Power Conversion"
	bus = "001"

Keep this output: you will copy the driver and port values in the next step.

Step 2 - Configuring the UPS driver

NUT ships with MODE=none, which keeps every service stopped. Open /etc/nut/nut.conf:

sudo nano /etc/nut/nut.conf

Set the mode to standalone, which means one server, one UPS, everything local:

MODE=standalone

Next, define the UPS. Open /etc/nut/ups.conf:

sudo nano /etc/nut/ups.conf

Add a section at the end of the file. The name in brackets (myups) is how you will refer to the UPS everywhere else:

[myups]
    driver = usbhid-ups
    port = auto
    desc = "Rack UPS"
    override.battery.charge.low = 30
    override.battery.runtime.low = 300

The two override lines make the driver raise the low battery (LB) flag at 30% charge or 5 minutes of estimated runtime, whichever comes first, instead of the UPS's own and often very late threshold. Choose values that leave enough time for your slowest service to stop.

On Ubuntu 24.04, systemd starts one nut-driver@<name> unit per UPS section. Regenerate those units and start the server:

sudo systemctl restart nut-driver-enumerator.service
sudo systemctl restart nut-server.service

Check that the driver is running:

systemctl status [email protected] --no-pager

The unit should be active (running). If it fails, see the Troubleshooting section.

Step 3 - Configuring upsd and its users

By default upsd listens only on localhost, which is what you want in standalone mode. Confirm or set it in /etc/nut/upsd.conf:

sudo nano /etc/nut/upsd.conf
LISTEN 127.0.0.1 3493
LISTEN ::1 3493

upsmon needs an account on upsd. Open /etc/nut/upsd.users:

sudo nano /etc/nut/upsd.users

Add a user for the local monitor. Replace your_monitor_password with a strong password of your own:

[upsmon_local]
    password = your_monitor_password
    upsmon primary

primary means this system is directly connected to the UPS and is responsible for telling the UPS to power off at the end of the shutdown. Restart upsd and query the UPS:

sudo systemctl restart nut-server.service
upsc myups

You should see a list of variables. The most useful ones are:

battery.charge: 100
battery.charge.low: 30
battery.runtime: 1650
battery.runtime.low: 300
input.voltage: 230.0
ups.load: 18
ups.status: OL

ups.status is OL on mains power, OB on battery, and gains LB when the battery is low. CHRG means the battery is charging.

Step 4 - Configuring upsmon for automatic shutdown

upsmon polls the UPS and starts the shutdown when it sees OB LB (on battery and low battery). Open /etc/nut/upsmon.conf:

sudo nano /etc/nut/upsmon.conf

Add or adjust these lines, using the same password as in upsd.users:

MONITOR myups@localhost 1 upsmon_local your_monitor_password primary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
FINALDELAY 5

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

The number 1 after the UPS name is how many power supplies of this server that UPS feeds. MINSUPPLIES 1 means the server needs at least one working supply to keep running. The NOTIFYFLAG lines send every power event to the system log and to logged-in users.

The file contains a password, so make sure only root and the nut group can read it (this is the Ubuntu default, but check it):

sudo chown root:nut /etc/nut/upsmon.conf /etc/nut/upsd.users
sudo chmod 640 /etc/nut/upsmon.conf /etc/nut/upsd.users

Start the monitor and make sure it is enabled at boot:

sudo systemctl enable --now nut-monitor.service
sudo systemctl restart nut-monitor.service

Verify that it logged in to upsd:

sudo journalctl -u nut-monitor -n 20 --no-pager
upsc -c myups

upsc -c lists the clients connected to the UPS; 127.0.0.1 or ::1 must appear.

Step 5 - Testing a power failure

Test before you need it. First, pull the UPS power plug from the wall (or switch off its breaker) for a few seconds while watching the status:

watch -n 2 'upsc myups ups.status; upsc myups battery.charge'

The status should change from OL to OB and a broadcast message should appear in your terminal. Restore power and it returns to OL. The events are also in the journal:

sudo journalctl -u nut-monitor --since "10 minutes ago" --no-pager

To test the full shutdown path without draining the battery, tell upsmon to act as if the battery were exhausted. This really shuts the server down and, depending on the UPS, powers the UPS outlets off, so only run it during a maintenance window:

sudo upsmon -c fsd

Step 6 - Sharing the UPS with other servers (optional)

When several servers share one UPS, only one of them can be connected to it over USB. That server becomes the NUT server (netserver) and the others run upsmon as clients (netclient). On power loss the primary waits for all secondaries to shut down before it powers itself and the UPS off.

On the server connected to the UPS

Change the mode in /etc/nut/nut.conf:

MODE=netserver

Make upsd listen on the LAN address as well. Replace your_server_ip with the server's private IP in /etc/nut/upsd.conf:

LISTEN 127.0.0.1 3493
LISTEN ::1 3493
LISTEN your_server_ip 3493

Add an account for the remote monitors to /etc/nut/upsd.users, with its own password:

[upsmon_remote]
    password = your_remote_password
    upsmon secondary

Allow the LAN to reach port 3493 and restart the services. Replace 192.168.1.0/24 with your subnet:

sudo ufw allow from 192.168.1.0/24 to any port 3493 proto tcp
sudo systemctl restart nut-server.service nut-monitor.service

On each client server

Install NUT on the client:

sudo apt install nut-client

Set the mode in /etc/nut/nut.conf:

MODE=netclient

In /etc/nut/upsmon.conf, point MONITOR at the NUT server and use the secondary role:

MONITOR myups@your_server_ip 1 upsmon_remote your_remote_password secondary
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"

Enable the monitor and verify the client can read the UPS:

sudo systemctl enable --now nut-monitor.service
sudo systemctl restart nut-monitor.service
upsc myups@your_server_ip ups.status
OL

On the NUT server, upsc -c myups should now list the client's IP address.

Step 7 - Sending email alerts (optional)

upsmon can run a command for each event. This example sends an email, so it assumes the server can already send mail with the mail command (package mailutils plus a configured MTA or relay). Create the script:

sudo nano /usr/local/bin/ups-notify
#!/usr/bin/env bash
set -euo pipefail

# upsmon passes the message as $1 and sets NOTIFYTYPE and UPSNAME.
recipient="admin@your_domain"
printf '%s\n\nHost: %s\nEvent: %s\n' "$1" "$(hostname -f)" "${NOTIFYTYPE:-unknown}" \
  | mail -s "UPS ${UPSNAME:-ups}: ${NOTIFYTYPE:-event} on $(hostname -s)" "$recipient"

Make it executable:

sudo chmod 755 /usr/local/bin/ups-notify

In /etc/nut/upsmon.conf, add the NOTIFYCMD line and add +EXEC to the events you want by email:

NOTIFYCMD /usr/local/bin/ups-notify
NOTIFYFLAG ONBATT   SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE   SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT  SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC

Keep only one NOTIFYFLAG line per event in the file, then restart the monitor and repeat the unplug test from Step 5:

sudo systemctl restart nut-monitor.service

Troubleshooting

nut-driver@myups fails with a USB permission or "no matching device" error. The nut package installs udev rules for supported UPS models, but they only apply to devices plugged in afterwards. Unplug and replug the USB cable, or reload the rules, then restart the driver:

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=usb
sudo systemctl restart [email protected]

upsc returns "Driver not connected". upsd is running but the driver is not. Check the driver log with sudo journalctl -u nut-driver@myups -n 50. Also make sure the section name in ups.conf matches the name you query.

upsmon logs "Login on UPS failed - got [ACCESS-DENIED]". The user name or password in the MONITOR line does not match upsd.users, or upsd was not restarted after editing that file.

Services do not start at all. Check that MODE in /etc/nut/nut.conf is not still none.

Conclusion

Your server now reads its UPS through NUT, logs every power event, and shuts down cleanly when the battery reaches the threshold you chose, with other servers on the LAN following the same signal. As next steps, schedule a periodic real power cut test, graph battery.charge and ups.load in your monitoring system, and review battery.runtime after each battery replacement so your low battery thresholds stay realistic.