NUT is an uninterruptible power supply (UPS) monitoring system that allows the sharing of one (or more) UPS systems between several computers. It has a 'server' component, which monitors the UPS status and notifies a 'client' component when the UPS has a low battery. There can be multiple computers running the client component and each can be configured to shut down cleanly in a power failure (before the UPS batteries run out of charge).

Monitor a direct-local connected UPS

After installing the NUT Package there are six example configuration files in /etc/nut/.
Connect to your IPFire system using ssh as root.

Device Driver

Identify your UPS in the NUT Hardware Compatibility List.

Then configure the ups.conf file. For a UPS connected directly with USB it should look like this:

filename = ups.conf

[apc-1500]
    driver = usbhid-ups
    port = auto
    desc = "The white UPS in the rack"

In this example, the [apc-1500] is the name of the UPS which will be referred to later. So it is best to keep your alias simple.

The desc is a short description that you can skip.

Optional Settings

Configure these if your UPS sets the Low Battery flag too early or calculates run time in an odd way.

ignorelb

When you specify this, the driver ignores a low battery condition flag that is reported by the UPS (some devices will switch off almost immediately after setting this flag, or will report this as soon as the mains fails). Instead, it will use either of the following conditions to determine when the battery is low:

battery.charge < battery.charge.low
battery.runtime < battery.runtime.low

The idea is to set the battery.charge.low and/or battery.runtime.low levels in ups.conf to a value that gives enough time to cleanly shutdown your system:

override.battery.charge.low = 30
override.battery.runtime.low = 180

In order for this to work, your UPS should be able to (reliably) report charge and/or runtime remaining on the battery. Use with caution!

default.<variable>

Optional. Set a default value for which is used in case the UPS doesn't provide a value but will be overwritten if a value is available from the UPS:

default.input.voltage.nominal = 230

The above will report the nominal input voltage to be 230 unless the UPS tells us differently.

override.<variable>

Optional. Set a value for that overrides any value that may be read from the UPS. Used for overriding values from the UPS that are clearly wrong (some devices report wrong values for battery voltage for instance):

override.battery.voltage.nominal = 12

Use with caution! This will only change the appearance of the variable to the outside world, internally in the UPS the original value is used.

All other fields are passed through to the hardware-specific part of the driver. See those manuals (FIXME add a link to NUT documentation here) for the list of what is allowed.

Now we should be able to start only the device module of NUT and talk to the UPS
upsdrvctl start
And it should respond with the following output:

Network UPS Tools - UPS driver controller 2.6.3
Network UPS Tools - Generic HID driver 0.34 (2.6.3)
USB communication driver 0.31
Using subdriver: APC HID 0.95

This tells us that NUT was able to launch the USB driver and found a UPS with this driver.

Next, configure the daemon which collects data from the UPS and provides it to a local monitor daemon and/or to daemon from the network.

Daemon Config

The daemon is configured in upsd.conf

filename = upsd.conf

LISTEN 127.0.0.1 3493
LISTEN 192.168.10.1

In this example 192.168.10.1 is the IP-Address of the green interface. You can skip the port number 3493 as it is the default port.

To configure NUT in a standalone configuration only these lines are required as IPFire only uses IPv4.

A user account must be configured to connect to the daemon. Therefore we use the upsd.users file.

filename = upsd.users

[admin]
      password = xxxx
      actions = SET FSD
      instcmds = ALL
      upsmon master

[user]
      password = yyyy
      upsmon slave

[admin] is the username, for rest please check out the NUT manpage (FIXME add a link to man page here).

Now start the NUT daemon:
upsd{bash}

and read the status of our UPS with this command:

upsc apc-1500@localhost{bash}

we will get something like this (localhost can be skipped):

battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 50
battery.date: 2001/09/25
battery.mfr.date: 2011/07/14
battery.runtime: 1860
battery.runtime.low: 900
battery.type: PbAc
battery.voltage: 26.9
battery.voltage.nominal: 24.0
device.mfr: American Power Conversion
device.model: Back-UPS RS 1500
device.serial: xxxxxxxxxxxxxxx
device.type: ups
driver.name: usbhid-ups
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.version: 2.6.3
driver.version.data: APC HID 0.95
driver.version.internal: 0.35
input.sensitivity: medium
input.transfer.high: 264
input.transfer.low: 194
input.transfer.reason: input voltage out of range
input.voltage: 234.0
input.voltage.nominal: 230
ups.beeper.status: enabled
ups.delay.shutdown: 20
ups.firmware: 8.g9a.I
ups.firmware.aux: g9a
ups.load: 12
ups.mfr: American Power Conversion
ups.mfr.date: 2011/07/14
ups.model: Back-UPS RS 1500
ups.productid: 0002
ups.realpower.nominal: 865
ups.serial: xxxxxxxxxxxx
ups.status: OL
ups.test.result: No test initiated
ups.timer.reboot: 0
ups.timer.shutdown: -1
ups.vendorid: 051d

if you want only the value of one single line (for scripting, see later) just add the name of the value to the command, like this:
upsc apc-1500@localhost battery.charge{bash} will return 100

Next, configure the NUT monitor daemon who will be monitoring the UPS and trigger the system shutdown if desired.

Monitor daemon config

The daemon monitor will be configured with upsmon.conf:

RUN_AS_USER root

MONITOR apc-1500@localhost 1 admin xxxx master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 2
POLLFREQALERT 1
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower

NOTIFYMSG ONLINE    "UPS %s on line power"
NOTIFYMSG ONBATT    "UPS %s on battery"
NOTIFYMSG LOWBATT   "UPS %s battery is low"
NOTIFYMSG FSD       "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK    "Communications with UPS %s established"
NOTIFYMSG COMMBAD   "Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN  "Auto logout and shutdown proceeding"
NOTIFYMSG REPLBATT  "UPS %s battery needs to be replaced"
NOTIFYMSG NOCOMM    "UPS %s is unavailable"
NOTIFYMSG NOPARENT  "upsmon parent process died - shutdown impossible"

NOTIFYFLAG ONLINE   SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT   SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT  SYSLOG+WALL
NOTIFYFLAG FSD      SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK   SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD  SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM   SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL

RBWARNTIME 43200

NOCOMMWARNTIME 600

FINALDELAY 5

I will here only explain some important options to get the whole picture please take a look at the example config file.

RUN_AS_USER root for more security you may want to create a new user under which NUT will run, but this user must have access to the USB or SERIAL device, read-only access to the config file, and so on.

Or we run NUT as root, since NUT can shutdown the System anyway.

If you skip this NUT will run as user NOBODY which as no access to read the config file (config file access chown comes later down).

MONITOR apc-1500@localhost 1 admin xxxx master very important here you set up which UPS NUT should monitoring, also use the right username and password form the upsd.users file.

SHUTDOWNCMD "/sbin/shutdown -h +0" this command will be triggered if UPS sends the BL (Battery Low) flag.

NOTIFYCMD /usr/sbin/upssched only needet if you will follow this how-to to the end and want to use additional notifiying.

POLLFREQ 2 how often it will call the daemon to update the monitor status, for a local unit 1-2 second is fine, for network 5-10 should be ok (depends on how much net traffic you want to have).

POLLFREQALERT 1 same as above but will only be used if the monitor knows that the UPS is on battery, so it may be lower than our default poll frequency so we keep in touch with the UPS (important for network monitoring, you won't miss the FSD flag from master).

HOSTSYNC 15 delay which the master will wait till all the slave hosts have pulled an update (if the master system shuts down).

DEADTIME 15 time the monitor keep an UPS state to be vaild and before it set it to stale if the monitor loss connection with that UPS. (If the UPS was on battery and the deadtime runs out [no update] the monitor will trigger immediately the FSD flag (Force ShutDown) and start the shutdown sequence)

POWERDOWNFLAG /etc/killpower todo if missing will display a note form init script on system shutdown

NOTIFYMSG ONLINE    "UPS %s on line power"
NOTIFYMSG ONBATT    "UPS %s on battery"
NOTIFYMSG LOWBATT   "UPS %s battery is low"
NOTIFYMSG FSD       "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK    "Communications with UPS %s established"
NOTIFYMSG COMMBAD   "Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN  "Auto logout and shutdown proceeding"
NOTIFYMSG REPLBATT  "UPS %s battery needs to be replaced"
NOTIFYMSG NOCOMM    "UPS %s is unavailable"
NOTIFYMSG NOPARENT  "upsmon parent process died - shutdown impossible"

format of the massages that the monitor can send to wall, syslog or script:

NOTIFYFLAG ONLINE   SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT   SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT  SYSLOG+WALL
NOTIFYFLAG FSD  SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK   SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD  SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM   SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL

here you select what kind of actions the monitor will take if he notice an event, if you following this how-to you can keep this settings. For basic UPS monitoring just remove the +EXEC

NOCOMMWARNTIME 600 will repeat the trigger NOCOMM every 600 seconds

The system will now shutdown when the UPS runtime or battery charge false below the low value!

which is by APC as default very far down the road, so we will set this parameter to a higher value to keep some reserves in the UPS

upsrw apc-1500@localhost{bash}

will list all available variables you can set in your UPS

[battery.charge.low]
Remaining battery level when UPS switches to LB (percent)
Type: STRING
Value: 10

[battery.runtime.low]
Remaining battery runtime when UPS switches to LB (seconds)
Type: STRING
Value: 900

[input.sensitivity]
Input power sensitivity
Type: STRING
Value: medium

[input.transfer.high]
High voltage transfer point (V)
Type: STRING
Value: 264

[input.transfer.low]
Low voltage transfer point (V)
Type: STRING
Value: 194

[ups.delay.shutdown]
Interval to wait after shutdown with delay command (seconds)
Type: STRING
Value: 20

so we will set the parameter for minimum runtime to 15 min and the minimum charge to 40%

upsrw -s battery.runtime.low=900 apc-1500@localhost
upsrw -s battery.charge.low=40 apc-1500@localhost

after each command, it will ask for the username and password from our daemon user config upsd.users

If your UPS does not support this you may check out the value override guide in the device driver section

Schedule Config (Optional)

the NUT schedule module is basically a timer/trigger customized for the notify events of NUT

I stored the upssched-cmd file also in the /etc/nut/ folder so it will be included in the IP-Fire backup

CMDSCRIPT /etc/nut/upssched-cmd
PIPEFN /etc/nut/upssched.pipe
LOCKFN /etc/nut/upssched.lock

# ============================================================================

AT ONBATT * START-TIMER onbatt 300
AT ONLINE * CANCEL-TIMER onbatt online
AT LOWBATT * EXECUTE onbatt
AT COMMBAD * START-TIMER commbad 30
AT COMMOK * CANCEL-TIMER commbad commok
AT NOCOMM * EXECUTE commbad
AT SHUTDOWN * EXECUTE powerdown

in this file you just set up witch timer will be started at which event.

So AT ONBATT * START-TIMER onbatt 300 will start the timeronbatt with 5 min if any (*) of the UPS will paste the ONBATT event to upssched (which we configured in the upsmon.conf notifycmd=... and the flags with the +EXEC) if the timer reach zero it will execute onbatt in the upssched-cmd bash script

AT ONLINE * CANCEL-TIMER onbatt online this will cancel the timeronbatt the event ONLINE get paste, if the timer has already be running out (or timer has not run) the command online in the bash script will be executed

well and AT SHUTDOWN * EXECUTE powerdown will directly EXECUTE the script powerdown

Schedule CMD file

For this script you will need the sendmail addon (sendemail) and maybe some bash scripting knowledge :)

This script will just send an Email with the UPS Status depending on the event

#!/bin/sh
DATUM=`/bin/date
case $1 in
    onbatt)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
    -u "Server UPS Event" \
    -s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
    -o tls=yes -m "$DATUM\nThe Server runs for more than 5 min on UPS Battery now!\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
    online)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
    -u "Server UPS Event" \
    -s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
    -o tls=yes -m "$DATUM\nThe Server UPS is back on Line Power now.\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;

    commbad)
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
    -u "Server UPS Event" \
    -s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
    -o tls=yes -m "$DATUM\nThe Server lost Communication with the UPS!" &;;
    commok)
STAT=`upsc apc-1500@localhost ups.status`
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -50`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
    -u "Server UPS Event" \
    -s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
    -o tls=yes -m "$DATUM\nThe Server has re-establish Communication with the UPS.\n\nUPS Status: $STAT\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
    powerdown)
BATT=`upsc apc-1500@localhost battery.charge`
RUNTIME=`upsc apc-1500@localhost battery.runtime`
UPSLOG=`cat /var/log/messages | grep ups | tail -100`
/usr/local/bin/sendEmail -f #MAILFROM# -t #MAILTO# \
    -u "Server UPS Event" \
    -s smtp.gmail.com -xu #USERNAME# -xp #PASSWORD# \
    -o tls=yes -m "$DATUM\nThe Server Shutdown due to UPS Event!!!\n\nUPS Battery Charge: $BATT%\nUPS Runtime: $RUNTIME seconds\n\nNUT Log:\n$UPSLOG" &;;
    *)
echo "wrong parameter";;
esac

exit 0

the '&' at the and of the sendmail command is mandatory upssched will only wait a few ms for the end of the script but sendmail may take up to 3-5 seconds to send the mail, so upssched will try to hit the trigger again and will also only wait a few ms till it get a return code so in the end it will send 3-5 emails instant of only one. With the & the sendmail command will be send to background and the script returns immediately the error 0 and all are happy :)

Config NUT Mode

Finally we will set the startup mode for NUT tostandalone in the nut.conf file:

MODE=standalone

User rights (chmod)

for all files in /etc/nut/ user-rights must be set to

chown root:root /etc/nut/*
chmod 0:640 /etc/nut/*

except the upssched-cmd needs

chmod 0:740 /etc/nut/upssched-cmd{bash}

Now NUT with all sub modules can be started with /etc/init.d/nut start

The init scripts are already shipped with the packed so no further action has to be taken to autostart NUT on system boot.

To see NUT as running in the service tap of the WGI we do a restart of the system or use
/etc/init.d/nut force-reload{bash}

to only restart NUT

Plug-in for SysInfo script

Here is a quickplug-in for the sysinfo script (sysinfo)

for the head-part:

ups=`cat /var/log/messages | grep ups

for the body-part:

filename = sysinfo.sh

echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
echo "                                      What says NUT ?:"
echo ""
echo "$datum - from IP:$ip_addr"
echo "--------------------------------------------------------------------------------------------------------------------------------------------------"
# UPS entrie in logs
if [](-n $ups) ; then
 BATT=`upsc apc-1500@localhost battery.charge`
 RUNTIME=`upsc apc-1500@localhost battery.runtime`
 MFR=`upsc apc-1500@localhost ups.mfr`
 MODEL=`upsc apc-1500@localhost ups.model`
 SERIAL=`upsc apc-1500@localhost ups.serial`
 LOAD=`upsc apc-1500@localhost ups.load`
 STAT=`upsc apc-1500@localhost ups.status`
 echo "UPS MFR: $MFR"
 echo "UPS Model: $MODEL"
 echo "UPS Serial: $SERIAL"
 echo ""
 echo "UPS Load: $LOAD%"
 echo "UPS Status: $STAT"
 echo "UPS Battery Charge: $BATT%"
 echo "UPS Runtime: $RUNTIME seconds"
 echo ""
 echo "--------------------------------------------------------------------------------------------------------------------------------------------------"
 echo "NUT has this Log entry's"
 echo ""
 cat /var/log/messages | grep ups | tail -50
 echo "-----------------------------------------------------------------------------------------------------------------------------------------------"
elif [](-z $ups) ; then
 echo ""
 echo "NUT is not enable and/or has no Log entry"
 echo ""
fi
echo ""
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
echo ""

Monitor a network UPS

There Driver and Daemon Part is not needed to monitor a network UPS,
you only need to change the Monitor entry in the upsmon.conf to

MONITOR apc-1500@192.168.1.1 1 username password slave

instead of localhost enter the IP of the device where the UPS is connected and NUT is running, and use the right username and password form the upsd.users file on that device.

Also, you have to change the mode in the nut.conf to

MODE=netclient

this way NUT will only start the monitor and if you configured the Schedule module

What happens on Power Events

http://www.networkupstools.org/docs/user-manual.chunked/ar01s06.html#Shutdown_design
Here are the steps that occur when a critical power event happens:

  1. The UPS goes on battery

  2. The UPS reaches low battery (a "critical" UPS), that is to say upsc displays:

ups.status: OB LB

The exact behavior depends on the specific device and is related to:

battery.charge and battery.charge.low
battery.runtime and battery.runtime.low
  1. The upsmon master notices and sets "FSD" - the "forced shutdown" flag to tell all slave systems that it will soon power down the load.
    (If you have no slaves, skip to step 6)

  2. upsmon slave systems see "FSD" and:

      generate a NOTIFY_SHUTDOWN event
      wait FINALDELAY seconds - typically 5
      call their SHUTDOWNCMD
      disconnect from upsd
  1. The upsmon master system waits up to HOSTSYNC seconds (typically 15) for the slaves to disconnect from upsd. If any are connected after this time, upsmon stops waiting and proceeds with the shutdown process.

  2. The upsmon master:

      generates a NOTIFY_SHUTDOWN event
      waits FINALDELAY seconds - typically 5
      creates the POWERDOWNFLAG file - usually /etc/killpower
      calls the SHUTDOWNCMD
  1. On most systems, init takes over, kills your processes, syncs and unmounts some filesystems, and remounts some read-only.

  2. init then runs your shutdown script. This checks for the POWERDOWNFLAG, finds it, and tells the UPS driver(s) to power off the load.

  3. The system loses power.

  4. Time passes. The power returns and the UPS switches back on.

  5. All systems reboot and go back to work.