UPS Integration with Network UPS Tools (NUT)
A power outage that triggers a clean, automatic shutdown across every host on your network -- instead of a hard power-loss and the filesystem corruption risk that comes with it.
What you'll build and why
NUT (Network UPS Tools) monitors a UPS over USB and shares its status across your network -- so every host you run, not just the one physically plugged into the UPS, can react to a power event and shut down cleanly before the battery runs out. Without this, a power outage that outlasts the UPS's battery means every connected machine loses power mid-write, with real filesystem corruption risk on anything without a clean shutdown.
Don't build this if: you don't have a UPS at all yet and aren't planning to get one -- this guide is the software integration layer, not a case for buying a UPS in the first place (though if your homelab holds anything you actually care about, that case is easy to make on its own).
How it works
UPS -- physically connected via USB to one host
│
▼
NUT server (on that host) -- monitors UPS status
│ (battery %, on-battery
│ or on-line, runtime left)
│
│ network protocol (NUT's own, port 3493)
│
├──► NUT client on Host A -- shuts down
│ cleanly when threshold is crossed
├──► NUT client on Host B -- same
└──► NUT client on Host C -- same
The server/client split is the key design: only one host needs the physical USB connection, but every host on the network can run a lightweight NUT client that watches the server's reported status and triggers its own clean shutdown independently.
Before you start
Decision: what shutdown threshold? Too aggressive (shutting down at 90% battery) wastes UPS runtime on brief flickers that would've resolved themselves; too conservative (waiting until 5%) risks not finishing shutdown before power actually cuts. A common starting point is shutting down when either battery charge drops below ~20-30%, or when estimated runtime remaining drops below however long your slowest host actually takes to shut down cleanly -- know that number before picking a threshold.
Steps
Step 1: Install NUT on the host physically connected to the UPS
$ sudo apt install nut
Step 2: Identify your UPS and configure the driver
$ sudo nut-scanner -U
Expected output: detected UPS device info, including the driver NUT recommends (commonly usbhid-ups for most consumer USB UPS units). Add this to /etc/nut/ups.conf:
[myups]
driver = usbhid-ups
port = auto
desc = "Main homelab UPS"
Step 3: Configure NUT to run as a network server
/etc/nut/nut.conf:
MODE=netserver
/etc/nut/upsd.conf -- listen on your LAN interface, not just localhost:
LISTEN <server-host-lan-ip> 3493
/etc/nut/upsd.users -- create a monitoring account other hosts will use:
[monuser]
password = <a-real-password>
upsmon secondary
Step 4: Start NUT on the server host
$ sudo systemctl restart nut-server nut-monitor
$ upsc myups@localhost
Expected output: a list of UPS status values (battery charge, status, runtime remaining) -- confirms the server is monitoring the UPS correctly before involving any client.
Step 5: Install and configure a client on each other host
$ sudo apt install nut-client
/etc/nut/upsmon.conf:
MONITOR myups@<server-host-lan-ip> 1 monuser <the-password-from-step-3> secondary
SHUTDOWNCMD "/sbin/shutdown -h +0"
$ sudo systemctl restart nut-monitor
Repeat on every host you want protected.
Verify it works
-
upsc myups@<server-host-ip>run from a client host returns live UPS status -- confirms network connectivity and auth are both working - Unplug the UPS from wall power (with it still connected to the server host via USB) -- confirm the server's status changes to on-battery (
upscshowsOBin the status field) within seconds - Failure test (the actual point of this guide): with the UPS on battery, let it run down toward your configured shutdown threshold (or temporarily lower the threshold for testing purposes), and confirm a client host actually executes a clean shutdown -- not just that the config exists, that the full chain (USB → server → network → client → shutdown command) works end to end
- Plug power back in and confirm the server correctly reports back to on-line (
OL) status
Secure it
- What's exposed: NUT's port 3493 should be reachable only from hosts on your own network that need it -- not the internet. UPS status itself isn't highly sensitive, but the monitoring account's credentials still deserve real protection since it grants visibility into (and depending on config, some control over) your power infrastructure.
- Shutdown command trust:
SHUTDOWNCMDruns with elevated privileges on every client -- this is triggered by a network signal from the NUT server, so the NUT server itself becomes a meaningfully trusted host in your network from a "what can trigger a shutdown of everything" perspective. Keep it on a host you control tightly. - The failure that hurts most: the shutdown threshold set too conservatively, so the real outage outlasts the UPS before clients finish shutting down -- this is exactly what the failure test above is meant to catch before it happens for real.
Back it up and maintain it
What matters: /etc/nut/ configuration files across server and clients -- small, worth version-controlling (a natural fit for the Ansible guide elsewhere in this section, applying the client config consistently across every host).
Update cadence: NUT updates infrequently and isn't security-critical in the way internet-facing services are; update on a relaxed schedule.
What to monitor: UPS battery health over time (most UPS units and NUT itself can report battery age/health) -- UPS batteries degrade and eventually can't hold enough charge to cover your configured shutdown window, silently reducing your actual protection margin.
Troubleshooting
Logs: sudo journalctl -u nut-server, sudo journalctl -u nut-monitor (both server and client sides).
| Symptom | Likely cause | Diagnostic | Fix |
|---|---|---|---|
nut-scanner doesn't detect the UPS |
USB connection issue, or the UPS uses a driver other than usbhid-ups |
lsusb to confirm the OS sees the device at all; check NUT's hardware compatibility list for your specific model |
Fix the USB connection; use the correct driver for your model |
Client can't reach the server (upsc times out) |
Firewall blocking port 3493, or LISTEN in upsd.conf bound to localhost only |
Test telnet <server-ip> 3493 from the client |
Open port 3493 on the server's firewall; confirm LISTEN uses the LAN IP, not 127.0.0.1 |
| Client authenticates but never triggers shutdown when tested | MONITOR line misconfigured, or SHUTDOWNCMD itself doesn't actually work when run manually |
Run the exact SHUTDOWNCMD value manually to confirm it works outside of NUT first |
Fix the shutdown command for that host's actual init system/permissions |
| UPS status flaps between on-line and on-battery rapidly | A power-quality issue (not a NUT problem) -- the UPS itself is reacting to real fluctuations | Check the UPS's own front-panel/log history if it has one | This is a power-supply/UPS hardware finding, not a NUT misconfiguration |
| Server shows the UPS but battery charge/runtime values look wrong | Some UPS models report these values inconsistently through generic USB HID drivers | Compare against the UPS's own physical display if it has one | Check NUT's model-specific notes; some UPS units need a vendor-specific driver instead of the generic one for accurate reporting |
Undo
sudo systemctl disable --now nut-server nut-monitor on the respective hosts, then sudo apt remove nut nut-client. Unplugging the UPS's USB cable stops monitoring immediately if needed sooner.
Go further
- Wire UPS status into the Prometheus/Grafana guide elsewhere in this section (NUT exposes metrics that can be scraped) so a power event shows up in the same dashboards as everything else
- Configure different shutdown priorities across hosts (shut down less critical services first, buying more runtime for anything you want to survive longer into an outage)
- If you have more than one UPS, NUT supports monitoring multiple units from one server -- useful if different parts of your homelab are on separate UPS units
Resources
Official documentation:
- Network UPS Tools documentation -- configuration and driver reference, verified this session
- NUT hardware compatibility list -- check before buying a UPS
Source and releases:
Community:
- NUT mailing lists -- linked from official documentation
Related DaemonPress projects:
- Managing a Homelab with Docker Compose, Portainer, and Watchtower
- Metrics and Alerting with Prometheus, Grafana, and Alertmanager
Last verified: 2026-09-21, checked against official Network UPS Tools documentation.