Nut-ups: Difference between revisions

From Alpine Linux
(Add an accuracy/out-of-date note about the "Todo" section)
m (minor rewording)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Accuracy|The below "Todo" tag ''may'' be inaccurate/out-of-date. I've set up the udev rule as described in the article and no permissions (or any other) issue so far, despite a fair amount of system upgrade and reboot (on the latest stable branch).}}
This wiki page shows how to install and configure the Network UPS Tools (NUT) package to monitor and report the statistics for a USB attached Uninterruptible Power Supply (UPS) and make the UPS status available over the network, so it can be monitored and used to trigger actions in a home automation system like [https://www.home-assistant.io/ Home Assistant].


{{Todo|The udev configuration presented here does not work consistently. A recent update and/or reboot has caused the libusb ''insufficient permissions on everything'' message to reappear. Even explicitly setting group ownership and permissions does not fix the problem.}}
The UPS model used in the examples is an APC SmartUPS 1000, but any UPS on the [https://networkupstools.org/stable-hcl.html list of compatible models] should work.


== Installing and Configuring Network UPS Tools (NUT) ==
== Determine UPS USB parameters ==


This wiki page shows how to install and configure the NUT package to monitor and report the statistics for a USB attached Uninterruptible Power Supply (UPS). The UPS model used in the examples is an APC SmartUPS 1000, but any UPS on the [https://networkupstools.org/stable-hcl.html list of compatible models] should work.
The first step is to plug in the USB cable between your UPS and your Alpine host to see how it appears to the system. Information about the UPS can be seen with the {{ic|dmesg}} command. See the example below.{{Cmd|<nowiki># dmesg
 
The end goal is to make the UPS status available over the network so it can be monitored and used to trigger actions in a home automation system like [https://www.home-assistant.io/ Home Assistant].
 
=== Determining Your UPS USB Parameters ===
 
The first step is to plug in the USB cable between your UPS and your Alpine host to see how it appears to the system. Information about the UPS can be seen with the '''dmesg''' command. See the example below.
 
<nowiki>
alpine:/# dmesg
  [400269.428612] usb 1-3: new low-speed USB device number 3 using xhci_hcd
  [400269.428612] usb 1-3: new low-speed USB device number 3 using xhci_hcd
  [400269.580728] usb 1-3: New USB device found, idVendor=051d, idProduct=0002, bcdDevice= 0.06
  [400269.580728] usb 1-3: New USB device found, idVendor=051d, idProduct=0002, bcdDevice= 0.06
Line 23: Line 14:
  [400269.687883] usbcore: registered new interface driver usbhid
  [400269.687883] usbcore: registered new interface driver usbhid
  [400269.687894] usbhid: USB HID core driver
  [400269.687894] usbhid: USB HID core driver
  [400269.698356] hid-generic 0003:051D:0002.0001: hiddev96,hidraw0: USB HID v1.10 Device [American Power Conversion Smart-UPS 1000 FW:600.3.D USB FW:1.4] on usb-0000:00:15.0-3/input0</nowiki>
  [400269.698356] hid-generic 0003:051D:0002.0001: hiddev96,hidraw0: USB HID v1.10 Device [American Power Conversion Smart-UPS 1000 FW:600.3.D USB FW:1.4] on usb-0000:00:15.0-3/input0</nowiki>}}
 
From this output, we can see a Smart-UPS 1000 has been detected. We can also see two important parameters: '''idVendor=051d''' and '''idProduct=0002'''. These will be used later in the udev rules, so keep them handy.


From this output, we can see a Smart-UPS 1000 has been detected. We can also see two important parameters: ''idVendor=051d'' and ''idProduct=0002''
== Installation ==


These will be used later in the udev rules, so keep them handy.
Install the {{pkg|nut}} package:{{Cmd|# apk add nut}}


=== Installing and Configuring NUT ===
== Configuration ==  


The first step is to add the alpine package. After that, we'll rename three default configuration files and replace them with the parameters needed for our example USB attached APC Smart-UPS.
All of the configuration files delivered with the package will be in the {{Path|/etc/nut}} subdirectory.  


<nowiki>
The following commands rename three original configuration files. {{Cmd|<nowiki># mv /etc/nut/nut.conf /etc/nut/nut.bak
alpine:/# apk update && apk add nut
# mv /etc/nut/ups.conf /etc/nut/ups.bak
# mv /etc/nut/upsd.conf /etc/nut/upsd.bak</nowiki>}}
 
Proceed to create the three files with only the configuration parameters needed for our example USB attached APC Smart-UPS.
 
To instruct NUT to make the UPS status available on the network, create the {{Path|/etc/nut/nut.conf}} file with content as follows: {{Cat|/etc/nut/nut.conf|<nowiki>MODE=netserver</nowiki>}}
   
   
alpine:/# mv /etc/nut/nut.conf /etc/nut/nut.conf~
The content of {{Path|/etc/nut/ups.conf}} define the name (in square brackets), the driver used to communicate with the UPS, and the port. For USB attached UPSs, it's almost always going to be a driver of ''usbhid-ups'' and a port of ''auto''. Make and model should not make any difference here provided it is a USB attached UPS. Create the file {{Path|/etc/nut/ups.conf}} with content as follows: {{Cat|/etc/nut/nut.conf|<nowiki>[SmartUPS_1000]
    driver = usbhid-ups
    port = auto</nowiki>}}
   
   
alpine:/# cat <<EOF >/etc/nut/nut.conf
To tell NUT to make the UPS info available on all network interfaces instead of the default i.e localhost only, which is not very useful, create the {{Path|/etc/nut/upsd.conf}} file with content as follows: {{Cat|/etc/nut/upsd.conf|<nowiki>LISTEN 0.0.0.0 3493</nowiki>}}
MODE=netserver
EOF
alpine:/# mv /etc/nut/ups.conf /etc/nut/ups.conf~
alpine:/# cat <<EOF >/etc/nut/ups.conf
[SmartUPS_1000]
    driver = usbhid-ups
    port = auto
EOF
alpine:/# mv /etc/nut/upsd.conf /etc/nut/upsd.conf~
alpine:/# cat <<EOF >/etc/nut/upsd.conf
LISTEN 0.0.0.0 3493
EOF</nowiki>


The first command should be familiar. It updates the Alpine package manager database and installs the nut package. All of the configuration files delivered with the package will be in the '''/etc/nut''' subdirectory.
{{Tip| Replace 0.0.0.0 with the network address of a specific interface if all interfaces is not appropriate for your situation.}}


The next several commands will rename the original configuration file and then write a new file with only the configuration parameters needed.
=== Configure udev rules ===


* The line written to '''nut.conf''' instructs NUT to make the UPS status available on the network.
To avoid [[#Insufficient permissions on everything|permission errors]] configure udev for giving NUT access to the USB attached Smart-UPS 1000. Create the file {{Path|/etc/udev/rules.d/62-nut-usbups.rules}} as follows:{{Cat|/etc/udev/rules.d/62-nut-usbups.rules|<nowiki>ATTR{idVendor}=="051d", ATTR{idProduct}=="0002", MODE="664", GROUP="nut"
</nowiki>}}
The ''idVendor'' and ''idProduct'' in first part i.e ''ATTR{idVendor}=="051d", ATTR{idProduct}=="0002"'' are unique to your UPS. They were found earlier in the [[#Determine UPS USB parameters| Determining UPS USB parameters]] section. The rest of the line tells udev what permissions and group ownership to use and should be the same regardless of the UPS make and model.


* The lines in '''ups.conf''' define the name (in square brackets), the driver used to communicate with the UPS, and the port. For USB attached UPSs, it's almost always going to be a driver of ''usbhid-ups'' and a port of ''auto''. Make and model should not make any difference here provided it is a USB attached UPS.
Use the {{ic|udevadm}} command to tell udev to read in the changes:{{Cmd|# udevadm control --reload-rules}}


* Finally, the line in '''upsd.conf''' is there to tell NUT it should make the UPS info available on all network interfaces. The default is localhost only, which is not very useful. You can replace 0.0.0.0 with the network address of a specific interface if all interfaces is not appropriate for your situation.
{{Note|There is also a file {{Path|/lib/udev/rules.d/62-nut-usbups.rules}} that has information for all of the UPS models NUT knows about. You may be able to simply copy this rather than constructing your own rules.}}


=== Configuring udev Rules ===
== Service configuration ==


If you tried starting the '''nut-upsd''' service at this point, it would complain loudly about permissions. See the example below.
The service is called {{ic|nut-upsd}} and can be managed using the standard start|stop|restart commands using standard [[OpenRC]] commands.


<nowiki>
{{Tip|Remember to [[#Configure udev rules|configure udev rules]] and [[#Testing the configuration|test the configuration]] before proceeding further.}}
libusb1: Could not open any HID devices: insufficient permissions on everything
No matching HID UPS found
upsnotify: failed to notify about state 4: no notification tech defined, will not spam more about it
Driver failed to start (exit status=1)</nowiki>


This is due to the USB device having the wrong ownership and permissions.
Proceed to start the service as follows: {{Cmd|# rc-service nut-upsd start
  * /run/nut: creating directory
  * /run/nut: correcting owner
Using subdriver: APC HID 0.100
  * Starting UPS Server ...}}


Below is an example of how to configure udev for giving NUT access to the USB attached Smart-UPS 1000.
Notice that the directory {{Path|/run/nut}} is created automatically the first time.


<nowiki>
[[#Verifying running state|Verify the running state]] before proceeding to configure the automatic startup of the {{ic|nut-upsd}}. If everything looks good, go ahead and set the service to auto-start when the system is booted:{{Cmd|# rc-update add nut-upsd
alpine:/# cd /etc/udev/rules.d
  * service nut-upsd added to runlevel default}}
cat <<EOF >62-nut-usbups.rules
ATTR{idVendor}=="051d", ATTR{idProduct}=="0002", MODE="664", GROUP="nut"
EOF
alpine:/# udevadm control --reload-rules</nowiki>


Take a look at the line that starts with ''ATTR{idVendor}=="051d", ATTR{idProduct}=="0002"''
== Using NUT ==


These are the vendor and product IDs found in the '''dmesg''' output above. The rest of the line tells udev what permissions and group ownership to use. It should be the same regardless of the UPS make and model, but the ''idVendor'' and ''idProduct'' will be unique to your UPS.
Now the {{ic|upsc}} command can be run against the name added in {{Path|/etc/nut/ups.conf}} to gather all status information about your UPS. Based on the example used on this wiki page:{{Cmd|$ upsc SmartUPS_1000}}
One can also gather specific status information by passing them as an argument: {{Cmd|$ upsc SmartUPS_1000 battery.charge}} This is useful to monitor specific values and/or initiate actions (e.g. from a script) when specific thresholds are reached.


{{ note|There is also a file '''/lib/udev/rules.d/62-nut-usbups.rules''' that has information for all of the UPS models NUT knows about. You may be able to simply copy this rather than constructing your own rules from the information in the '''dmesg''' output. }}
[[#See also|See also]] section has documentation links to configure NUT to do useful things like send an email or initiate a graceful shutdown when the main power is lost. and to use Home Assistant to keep tabs on your UPS.  


Finally, the '''udevadm control''' command tells udev to read in the changes.
== Troubleshooting ==


=== Testing the Configuration Thus Far ===
=== Testing the configuration ===


Unplug the UPS USB cable from the host, wait a moment, and then reinsert it. Check '''dmesg''' again to make sure it was detected and the idVendor and idProduct are correct.
Unplug the UPS USB cable from the host, wait a moment, and then reinsert it. Check '''dmesg''' again to make sure it was detected and the idVendor and idProduct are correct.


Check the permissions on the files in the '''/dev/bus/usb''' subdirectories. One of these represents your UPS. If the udev rules work correctly, it should be the file with a group owner of ''nut'' and permissions of 0664. An example is shown below.
Check the permissions on the files in the {{Path|/dev/bus/usb}} subdirectories. One of these represents your UPS. If the udev rules work correctly, it should be the file with a group owner of ''nut'' and permissions of 0664. An example is shown below.{{Cmd|# ls -l /dev/bus/usb/001/003
 
  crw-rw-r-- 1 root nut 189, 2 Oct 10 00:53 /dev/bus/usb/001/003}}
alpine:/# ls -l /dev/bus/usb/001/003
  crw-rw-r-- 1 root nut 189, 2 Oct 10 00:53 /dev/bus/usb/001/003


Your directory and file names may be different, but at least one of the files should have the group ownership and permissions as shown in the example.
Your directory and file names may be different, but at least one of the files should have the group ownership and permissions as shown in the example.


The output from '''dmesg''' should tip you off as to which directory and file it is. Look at the line below from '''dmesg''' and compare the ''usb 1-3'' to the directory entry of ''/dev/bus/usb/001/003''.
The output from {{ic|dmesg}} should tip you off as to which directory and file it is. Look at the line below from {{ic|dmesg}} and compare the ''usb 1-3'' to the directory entry of the {{Path|/dev/bus/usb/001/003}}file. {{Cat|/dev/bus/usb/001/003|usb 1-3: Manufacturer: American Power Conversion}}
 
usb 1-3: Manufacturer: American Power Conversion


=== Starting NUT ===
=== Verifying running state ===
 
The service is called '''nut-upsd''' and can be started as shown below.
 
alpine:/# rc-service nut-upsd start
  * /run/nut: creating directory
  * /run/nut: correcting owner
Using subdriver: APC HID 0.100
  * Starting UPS Server ...
 
Notice that the directory '''/run/nut''' is created automatically the first time.
 
=== Verifying Running State ===


A couple quick commands will ensure the NUT service is actually running as expected. These are shown in the example below.
A couple quick commands will ensure the NUT service is actually running as expected. These are shown in the example below.
Line 134: Line 100:
This shows the service running and making the UPS status available on all network interfaces (0.0.0.0) over the default TCP port for NUT (3493).
This shows the service running and making the UPS status available on all network interfaces (0.0.0.0) over the default TCP port for NUT (3493).


=== Configuring Automatic Startup ===
=== Insufficient permissions on everything ===


If everything looks good, go ahead and set the service to auto-start when the system is booted.
<nowiki>
 
libusb1: Could not open any HID devices: insufficient permissions on everything
  alpine:/# rc-update add nut-upsd
No matching HID UPS found
  * service nut-upsd added to runlevel default
  upsnotify: failed to notify about state 4: no notification tech defined, will not spam more about it
Driver failed to start (exit status=1)</nowiki>


=== Next Steps ===
The above error message is due to the USB device having the wrong ownership and permissions. [[#Configure udev rules|Configure udev rules]] and restart the [[#Service configuration|service]].


You should now be able run the <code>upsc</code> command against the name added in <code>/etc/nut/ups.conf</code> to gather all status information about your UPS (e.g. with the example from this wiki page: <code>upsc SmartUPS_1000</code>). One can also gather specific status information by passing them as an argument (e.g. <code>upsc SmartUPS_1000 battery.charge</code>). This is useful to monitor specific values and/or initiate actions (e.g. from a script) when specific thresholds are reached.
== See also ==


NUT itself can also be configured to do useful things like send an email or initiate a graceful shutdown when the main power is lost. The [https://networkupstools.org/ NUT home page] is your source for documentation on how to do this.
* [https://networkupstools.org/ NUT home page]  
* [https://networkupstools.org/stable-hcl.html list of NUT compatible models]
* [https://www.home-assistant.io/integrations/nut/ NUT integration for Home Assistant]


There is also a [https://www.home-assistant.io/integrations/nut/ NUT integration for Home Assistant] that can be installed to keep tabs on your UPS.
[[Category:Monitoring]]

Latest revision as of 06:13, 29 September 2025

This wiki page shows how to install and configure the Network UPS Tools (NUT) package to monitor and report the statistics for a USB attached Uninterruptible Power Supply (UPS) and make the UPS status available over the network, so it can be monitored and used to trigger actions in a home automation system like Home Assistant.

The UPS model used in the examples is an APC SmartUPS 1000, but any UPS on the list of compatible models should work.

Determine UPS USB parameters

The first step is to plug in the USB cable between your UPS and your Alpine host to see how it appears to the system. Information about the UPS can be seen with the dmesg command. See the example below.

# dmesg [400269.428612] usb 1-3: new low-speed USB device number 3 using xhci_hcd [400269.580728] usb 1-3: New USB device found, idVendor=051d, idProduct=0002, bcdDevice= 0.06 [400269.580751] usb 1-3: New USB device strings: Mfr=3, Product=1, SerialNumber=2 [400269.580759] usb 1-3: Product: Smart-UPS 1000 FW:600.3.D USB FW:1.4 [400269.580765] usb 1-3: Manufacturer: American Power Conversion [400269.580771] usb 1-3: SerialNumber: AS0123456789 [400269.687883] usbcore: registered new interface driver usbhid [400269.687894] usbhid: USB HID core driver [400269.698356] hid-generic 0003:051D:0002.0001: hiddev96,hidraw0: USB HID v1.10 Device [American Power Conversion Smart-UPS 1000 FW:600.3.D USB FW:1.4] on usb-0000:00:15.0-3/input0

From this output, we can see a Smart-UPS 1000 has been detected. We can also see two important parameters: idVendor=051d and idProduct=0002. These will be used later in the udev rules, so keep them handy.

Installation

Install the nut package:

# apk add nut

Configuration

All of the configuration files delivered with the package will be in the /etc/nut subdirectory.

The following commands rename three original configuration files.

# mv /etc/nut/nut.conf /etc/nut/nut.bak # mv /etc/nut/ups.conf /etc/nut/ups.bak # mv /etc/nut/upsd.conf /etc/nut/upsd.bak

Proceed to create the three files with only the configuration parameters needed for our example USB attached APC Smart-UPS.

To instruct NUT to make the UPS status available on the network, create the /etc/nut/nut.conf file with content as follows:

Contents of /etc/nut/nut.conf

MODE=netserver

The content of /etc/nut/ups.conf define the name (in square brackets), the driver used to communicate with the UPS, and the port. For USB attached UPSs, it's almost always going to be a driver of usbhid-ups and a port of auto. Make and model should not make any difference here provided it is a USB attached UPS. Create the file /etc/nut/ups.conf with content as follows:

Contents of /etc/nut/nut.conf

[SmartUPS_1000] driver = usbhid-ups port = auto

To tell NUT to make the UPS info available on all network interfaces instead of the default i.e localhost only, which is not very useful, create the /etc/nut/upsd.conf file with content as follows:

Contents of /etc/nut/upsd.conf

LISTEN 0.0.0.0 3493
Tip: Replace 0.0.0.0 with the network address of a specific interface if all interfaces is not appropriate for your situation.

Configure udev rules

To avoid permission errors configure udev for giving NUT access to the USB attached Smart-UPS 1000. Create the file /etc/udev/rules.d/62-nut-usbups.rules as follows:

Contents of /etc/udev/rules.d/62-nut-usbups.rules

ATTR{idVendor}=="051d", ATTR{idProduct}=="0002", MODE="664", GROUP="nut"

The idVendor and idProduct in first part i.e ATTR{idVendor}=="051d", ATTR{idProduct}=="0002" are unique to your UPS. They were found earlier in the Determining UPS USB parameters section. The rest of the line tells udev what permissions and group ownership to use and should be the same regardless of the UPS make and model.

Use the udevadm command to tell udev to read in the changes:

# udevadm control --reload-rules

Note: There is also a file /lib/udev/rules.d/62-nut-usbups.rules that has information for all of the UPS models NUT knows about. You may be able to simply copy this rather than constructing your own rules.

Service configuration

The service is called nut-upsd and can be managed using the standard start|stop|restart commands using standard OpenRC commands.

Tip: Remember to configure udev rules and test the configuration before proceeding further.

Proceed to start the service as follows:

# rc-service nut-upsd start * /run/nut: creating directory * /run/nut: correcting owner Using subdriver: APC HID 0.100 * Starting UPS Server ...

Notice that the directory /run/nut is created automatically the first time.

Verify the running state before proceeding to configure the automatic startup of the nut-upsd. If everything looks good, go ahead and set the service to auto-start when the system is booted:

# rc-update add nut-upsd * service nut-upsd added to runlevel default

Using NUT

Now the upsc command can be run against the name added in /etc/nut/ups.conf to gather all status information about your UPS. Based on the example used on this wiki page:

$ upsc SmartUPS_1000

One can also gather specific status information by passing them as an argument:

$ upsc SmartUPS_1000 battery.charge

This is useful to monitor specific values and/or initiate actions (e.g. from a script) when specific thresholds are reached.

See also section has documentation links to configure NUT to do useful things like send an email or initiate a graceful shutdown when the main power is lost. and to use Home Assistant to keep tabs on your UPS.

Troubleshooting

Testing the configuration

Unplug the UPS USB cable from the host, wait a moment, and then reinsert it. Check dmesg again to make sure it was detected and the idVendor and idProduct are correct.

Check the permissions on the files in the /dev/bus/usb subdirectories. One of these represents your UPS. If the udev rules work correctly, it should be the file with a group owner of nut and permissions of 0664. An example is shown below.

# ls -l /dev/bus/usb/001/003 crw-rw-r-- 1 root nut 189, 2 Oct 10 00:53 /dev/bus/usb/001/003

Your directory and file names may be different, but at least one of the files should have the group ownership and permissions as shown in the example.

The output from dmesg should tip you off as to which directory and file it is. Look at the line below from dmesg and compare the usb 1-3 to the directory entry of the /dev/bus/usb/001/003file.

Contents of /dev/bus/usb/001/003

usb 1-3: Manufacturer: American Power Conversion

Verifying running state

A couple quick commands will ensure the NUT service is actually running as expected. These are shown in the example below.

alpine:/# rc-service nut-upsd status
* status: started
alpine:/# netstat -tln | grep 3493
tcp        0      0 0.0.0.0:3493            0.0.0.0:*               LISTEN

This shows the service running and making the UPS status available on all network interfaces (0.0.0.0) over the default TCP port for NUT (3493).

Insufficient permissions on everything

 libusb1: Could not open any HID devices: insufficient permissions on everything
 No matching HID UPS found
 upsnotify: failed to notify about state 4: no notification tech defined, will not spam more about it
 Driver failed to start (exit status=1)

The above error message is due to the USB device having the wrong ownership and permissions. Configure udev rules and restart the service.

See also