Configure a UPS on Linux with NUT
Install and configure Network UPS Tools (NUT) on Linux to detect your UPS, load the right driver, and trigger a safe automatic shutdown when battery runs low.
Before you start
- ▸Root or sudo access on the target machine
- ▸UPS connected to the machine via USB or serial cable
- ▸Basic familiarity with editing files on the command line
- ▸systemd-based Linux distribution
A UPS (Uninterruptible Power Supply) protects servers and workstations from sudden power loss, but hardware alone is not enough. Without software monitoring the UPS, your system will still crash hard when the battery runs out. Network UPS Tools (NUT) is the standard open-source solution: it speaks to hundreds of UPS models, monitors battery state, and triggers a clean shutdown before the battery dies. This guide walks through a single-machine NUT setup — one host talking directly to its own UPS — the most common scenario for a home lab or small server.
Prerequisites and Terminology
NUT has three moving parts you need to understand before touching config files:
- upsd — the daemon that reads UPS data and serves it over a socket
- upsmon — monitors UPS state and triggers shutdown commands
- driver — the per-model binary that actually talks to the UPS hardware (USB, serial, SNMP, etc.)
For a single machine, all three run on the same host. The UPS connects via USB (most common for consumer and prosumer units) or a serial port.
Install NUT
Debian / Ubuntu
sudo apt update
sudo apt install nut nut-client nut-server
Fedora / RHEL 9 / Rocky Linux
sudo dnf install nut
On RHEL-family systems the package ships both server and client components together.
Arch Linux
sudo pacman -S nut
After installation NUT's config files live in /etc/nut/ on all distributions.
Detect Your UPS
Plug in the UPS via USB, then run the scanner. It probes USB and other buses and prints the driver block you need:
sudo nut-scanner -U
Output will look roughly like this (yours will differ):
[nutdev1]
driver = "usbhid-ups"
port = "auto"
vendorid = "051d"
productid = "0002"
product = "Back-UPS ES 700"
vendor = "American Power Conversion"
Copy this block — you will paste most of it into ups.conf. If nut-scanner finds nothing, check that the USB cable is data-capable (not charge-only) and that you ran the command with sudo.
Configure the Driver — ups.conf
Edit /etc/nut/ups.conf. Replace any placeholder content with your detected block, giving the UPS a short name (here, myups):
sudo nano /etc/nut/ups.conf
[myups]
driver = usbhid-ups
port = auto
desc = "APC Back-UPS ES 700"
If nut-scanner returned vendorid and productid, add them too — they prevent NUT from grabbing the wrong USB device if you ever connect multiple UPS units.
[myups]
driver = usbhid-ups
port = auto
vendorid = 051d
productid = 0002
desc = "APC Back-UPS ES 700"
Common drivers: usbhid-ups covers most USB HID-compliant units (APC, Eaton, CyberPower); blazer_usb covers many cheaper USB units from Mecer, Voltronic, and rebrands; nutdrv_qx covers Q-series protocol units. The NUT hardware compatibility list at networkupstools.org maps models to drivers.
Set the Operating Mode — nut.conf
This single file tells NUT what role this machine plays:
sudo nano /etc/nut/nut.conf
MODE=standalone
standalone means one machine, one UPS, no network slaves. Use netserver only if other machines will monitor this UPS over the network.
Configure the Server — upsd.conf and upsd.users
upsd.conf controls what interfaces upsd listens on. For a standalone setup, localhost is sufficient:
sudo nano /etc/nut/upsd.conf
LISTEN 127.0.0.1 3493
LISTEN ::1 3493
Then define at least one user in upsd.users. You need an admin-type user for upsmon to authenticate with:
sudo nano /etc/nut/upsd.users
[upsmon_local]
password = changeme_strong_password
upsmon master
Pick a real password. Even though this only listens on localhost, it is still a credential stored in a plain-text file — restrict its permissions:
sudo chmod 640 /etc/nut/upsd.users
sudo chown root:nut /etc/nut/upsd.users
Configure the Monitor — upsmon.conf
upsmon is what actually calls shutdown when the battery hits a critical level:
sudo nano /etc/nut/upsmon.conf
The critical line is MONITOR. Its format is upsname@host powervalue username password type:
MONITOR myups@localhost 1 upsmon_local changeme_strong_password master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYFLAG ONLINE SYSLOG+WALL
NOTIFYFLAG ONBATT SYSLOG+WALL
NOTIFYFLAG LOWBATT SYSLOG+WALL
NOTIFYFLAG COMMOK SYSLOG
NOTIFYFLAG COMMBAD SYSLOG
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 25
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
SHUTDOWNCMD is what runs when the battery is critically low. /sbin/shutdown -h +0 halts immediately. Adjust to shutdown -h +2 if you want a two-minute grace window. The powervalue 1 means this host needs 1 power supply from this UPS to stay alive — correct for a standard desktop or server.
Start and Enable the Services
Debian / Ubuntu / Arch
sudo systemctl enable --now nut-server nut-monitor
On Debian/Ubuntu you may also need:
sudo systemctl enable --now nut-driver@myups
Fedora / RHEL / Rocky
sudo systemctl enable --now ups nut-server nut-monitor
The RHEL family uses a ups target that groups the driver and server. If the service name differs on your release, use systemctl list-units 'nut*' to see what is available.
Verify Everything is Working
Query live UPS data with upsc:
upsc myups@localhost
You should see a wall of variables — the important ones:
ups.status: OL— Online (on mains power)battery.charge: 100— Battery fully chargedbattery.runtime: 1800— Estimated runtime in seconds
OB means on battery, LB means low battery (shutdown imminent). Check that upsmon is connected:
sudo upsc myups@localhost ups.status
sudo systemctl status nut-monitor
To test driver communication without triggering a real shutdown, briefly unplug the UPS mains cable and watch the status flip to OB in the output of a looping upsc:
watch -n 2 upsc myups@localhost ups.status
Troubleshooting
Driver fails to start — permission denied on USB device
The nut user needs access to the USB device node. On most distros the NUT package ships a udev rule at /lib/udev/rules.d/62-nut-usbups.rules that handles this. If it is missing, reload udev and replug the UPS:
sudo udevadm control --reload-rules
sudo udevadm trigger
upsc returns "Error: Driver not connected"
The driver has not started or crashed. Check its journal:
sudo journalctl -u nut-driver@myups -n 50
Common causes: wrong driver = value in ups.conf, typo in the UPS name, or a USB permission issue.
upsmon reports "COMMBAD" then does nothing
If upsd is not reachable, upsmon logs COMMBAD but will not shut down until DEADTIME seconds have elapsed. Check that nut-server is running and that the credentials in upsmon.conf match upsd.users exactly — including case.
System shuts down immediately after config
Check that MINSUPPLIES is set to 1 and that upsc myups@localhost ups.status shows OL before starting services. If NUT cannot reach the UPS at startup it may treat it as a lost supply and trigger shutdown.
Frequently asked questions
- Which NUT driver should I use for my APC UPS?
- Most modern APC units connected via USB use the 'usbhid-ups' driver. Run 'sudo nut-scanner -U' and it will tell you the correct driver automatically. Older APC units with a serial RJ45 port use the 'apcsmart' driver.
- Can I monitor the UPS from multiple machines over the network?
- Yes. Set MODE=netserver on the host connected to the UPS, add a LISTEN line in upsd.conf for the network interface, and set MODE=netclient on remote machines, pointing their upsmon.conf at the server's IP. Open port 3493 in your firewall.
- How do I know NUT will actually shut down before the battery dies?
- NUT triggers shutdown when the UPS reports the LB (low battery) flag, which is set at a manufacturer-defined threshold. You can adjust when that flag fires using the 'battery.charge.low' settable variable with upsrw, if your driver and UPS support it.
- NUT works but I get no notifications by email — how do I add that?
- Add a NOTIFYCMD line in upsmon.conf pointing to a script or tool like 'sendmail'. Set the NOTIFYFLAG lines to include EXEC alongside SYSLOG, and upsmon will call your script with the event string as an argument.
- Does NUT work with CyberPower UPS units?
- Yes. Most CyberPower units use the 'usbhid-ups' driver. Some older or cheaper models need 'blazer_usb' or 'nutdrv_qx'. Check the NUT hardware compatibility list at networkupstools.org for your exact model number.
Related guides
Configure Prometheus Alertmanager
Configure Prometheus Alertmanager with routing trees, receivers, inhibition rules, grouping, Go templates, and PagerDuty/Slack on-call integrations.
Build an Intranet Server on Linux
Set up a complete small-office intranet on one Linux box: Nginx web server, dnsmasq local DNS, Samba file sharing, and a Wiki.js team wiki.
Build an nftables Firewall Script
Build a complete nftables firewall from scratch: tables, chains, sets, default-deny input policy, service allowlisting, and persistent systemd configuration.
Caddy as a Reverse Proxy
Set up Caddy as a reverse proxy with automatic HTTPS, load balancing, WebSocket passthrough, reusable snippets, and header control — no certbot required.