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-upsdriver; check the NUT hardware compatibility list for your model. - A non-root user with
sudoprivileges. - 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:
| Component | Role |
|---|---|
Driver (usbhid-ups, snmp-ups...) | Talks to the UPS hardware |
upsd | Serves UPS data to clients on TCP port 3493 |
upsmon | Watches 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.
