Connecting a UPS to Home Assistant using Network UPS Tools (NUT)
Anyone who has set up a homelab knows the importance of an uninterruptible power supply (UPS). Unfortunately extracting and acting upon data from the UPS is usually quite difficult. If you're lucky the manufacturer provides software to access it but odds are that software is bloated, difficulty to install, and not able to integrate with anything else.
Thankfully there is an open-source project called Network UPS Tools (NUT) that can communicate with a wide variety of UPS and expose its information to clients that request it.
These are the steps I took to install NUT on a spare Raspberry Pi and connect it to Home Assistant where all of the data from the UPS can be easily viewed and stored.
Big thanks to this YouTube video from Techno Tim that gives a fantastic overview of NUT and how it can be configured.
I also found this other video that gets right down to the brass tacks of installing a UPS and connecting it to NUT.
Verify that your UPS is compatible
If your UPS is able to connect via USB there is a very good chance that NUT will support it. But double check their hardware compatibility list to be absolutely sure you aren't wasting your time.
Set up a headless Raspberry Pi
I recommend following my instructions on how to configure a headless Raspberry Pi quickly and securely.
Install NUT
Thankfully you can easily install NUT by running sudo apt-get install nut
. You shouldn't need to explicitly install nut-server
or nut-client
as they are automatically included as dependencies but double check to be certain.
Connect your UPS
It is now time to connect your UPS to your Raspberry Pi. You can then run the nut-scanner
command which will detect and display information about the attached UPS. Its output should look similar to:
[nutdev1]
driver = "usbhid-ups"
port = "auto"
vendorid = "6666"
productid = "FFFF"
product = "Some Name"
serial = "XXXYYYZZZ"
vendor = "EATON"
bus = "001"
The fields you want to pay most attention to are driver, port, vendorid, and productid as they will be required in the next step.
Configure ups.config
Armed with information about the connected UPS we can configure NUT to communicate with it directly. The first step is to update the /etc/nut/ups.conf
file with some variant of:
[ups-name]
driver = usbhid-ups
port = auto
desc = "User Friendly Description"
vendorid = 6666
productid = FFFF
This is how NUT understands how to talk to your UPS. The driver, port, vendorid, and productid will be the same data outputted by nut-scanner
. ups-name is what we will use to refer to the UPS when using any of NUT's tools. I would recommend you name it after either the UPS model or what it is protecting.
Based on what I have read the usbhid-ups
driver is most likely what you will be using if you are connecting your UPS via USB. NUT's documentation on the usbhid-ups driver goes into detail as to what information is required to connect to specific UPS brands.
Configure nut.conf
We have told NUT how to talk to our UPS but we haven't actually turned NUT on yet. To do this we need to modify /etc/nut/nut.conf
. This file has very thorough documentation but all we care about is the value of the MODE field.
none
Indicates that NUT should not get started automatically, possibly because it is not configured or that an Integrated Power Management or some external system, is used to startup the NUT components.
standalone
Addresses a local only configuration, with 1 UPS protecting the local system. This implies to start the 3 NUT layers (driver, upsd and upsmon), with the related configuration files. This mode can also address UPS redundancy.
netserver
Like the standalone configuration, but also possibly need one or more specific LISTEN directive(s) in upsd.conf. Since this MODE is open to the network, a special care should be applied to security concerns.
By changing MODE=none
to MODE=netserver
and restarting our device using sudo shutdown -r now
we will have enabled NUT. After reconnecting to the Raspberry Pi we can run the command upsc ups-name
to get a detailed breakdown of the connected UPS.
Configure upsd.conf
Currently NUT server is only listening for local requests so we need to update /etc/nut/upsd.conf
to tell NUT to listen to all requests from the network. We do this by adding a single line to the end, LISTEN 0.0.0.0 3493
, which allows all IP addresses to communicate with NUT on port 3493.
If you previously followed my guide on how to set up a headless Raspberry Pi you need to update Uncomplicated Firewall (ufw) to allow TCP traffic on port 3493.
sudo ufw allow 3493/tcp
Configure upsd.users
At this point you may notice that NUT is discoverable by Home Assistant but if you try to add it you're prompted for a username and password. We can create these credentials by appending them to the end of the /etc/nut/upsd.users
file.
The documentation for Home Assistant's NUT integration tells you exactly how this user should be configured. I typically go with:
[home-assistant]
password = XXX
actions = SET
instcmds = ALL
which creates a user named home-assistant, with a password of XXX, that is allowed to activate all commands.
Add NUT integration in Home Assistant
Restart your Raspberry Pi one final time and you should see a notification in Home Assistant for a discovered "Network UPS Tools (NUT)" device. Click "Add", enter the username and password you created, and you should have successfully connected your NUT server to Home Assistant.
What next?
What we've just done in this article is effectively the most basic thing you can do with NUT. While it could be cool to visualize the data, unless your area has a lot of issues with power failures you're it's probably going to be fairly static.
What most people use NUT for is to broadcast when the UPS has switched over to battery backup. Then any clients listening can react and automatically shut themselves down. The most common examples are file servers and network-attached storage which could corrupt data if they suddenly lose power when the battery drains completely.
I would like to do something like this with my homelab in the future and if I do I'll make sure to write a follow-up article to document my experience.