Configuration of the APC UPS Daemon on my Linux server

For obvious reasons my Linux home server supplying NAS and Web services 24/7 is connected to a UPS. The UPS model (now discontinued) I use is a 700VA 230V APC Back-UPS ES-BE700G-UK. It is connected to one of the server’s USB ports via an APC-supplied cable so that the server can interrogate the UPS and so that the UPS can send unsolicited messages to the server (e.g. mains power supply interrupted, mains power supply restored, shut down the server now, and so on). The open-source APC UPS Daemon apcupsd that I installed on the server enables the server to react automatically to UPS events. apcupsd provides a shell script apccontrol and various other shell scripts to act on these events. All these scripts can be customised by the user. As users with an APC UPS that supports this functionality are likely to be interested in configuration of apcupsd, I think it might be useful for me to explain how I configured apcupsd.

An Ethernet switch and an external USB 6 TB HDD (connected to the server for automated daily backups) are in the same room as the server and also connected to the UPS. If my router were in the same room as the server then it would be connected to the same UPS as the server but, as it has to be in a different room next to the broadband provider’s master socket, it is instead connected to a separate mini UPS so that the server can still send e-mails after an interruption to the mains power supply.

Before getting into the configuration of apcupsd, I should mention that I have come across some home users who think the purpose of a UPS is solely to protect against loss of mains supply from the electricity utility company. Whilst that is one of the purposes of a UPS, home users should note that home fuses can blow and RCD consumer units can trip even when there is no interuption to the mains supply to the house from the utility company. So the argument that the local utility company is extremely reliable is not a reason to dispense with a UPS for a server. Well, not unless you are prepared to accept the risk of corruption of the OS and/or users’ data.

It is possible to configure apcupsd to perform a controlled shutdown of a server if the mains power supply to a UPS has been interrupted for a user-specified amount of time or if the UPS battery’s remaining charge has dropped to a user-specified percentage of its full capacity. If desired, it would also be possible to configure apcupsd and a server’s firmware to reboot the server automatically once mains power has been restored to the UPS following an earlier controlled shutdown of the server (see ‘Arranging for Reboot on Power-Up‘ in the APCUPSD User Manual). However, as I am often away from home on work trips and cannot immediately check what has happened, I do not want the server to reboot automatically when there is power to the server, in case the mains power supply is intermittent for whatever reason. Instead, after receiving an e-mail from the server informing me it is shutting down, I would phone home and ask a family member what has happened and, if I were satisfied everything is now OK, I would then ask them to power up the server. Therefore I configured the server’s BIOS not to reboot automatically if there is power to the server after it has been shut down.

Although apcupsd offers a mechanism to tell the UPS to go into hibernation, I am not interested in trying to get the UPS to hibernate once the OS shuts down, because I do not want to risk the UPS going into hibernation before my server has shutdown the OS completely and powered down the server. Furthermore, the server is not the only device powered by the UPS. Therefore, if there were a long delay until the mains power supply to the UPS is restored, the UPS would continue to supply power until its battery is flat. However, it is unlikely the power supply to the UPS would be down for long, so the possibility of draining the battery completely is unlikely once the server has been powered down; power to the UPS will usually be restored before the battery is flat. The power requirement of the tiny Ethernet switch is small and the external USB HDD goes to sleep automatically after a few minutes of inactivity anyway. It is more important that the server is powered down ‘gracefully’.

The mechanism an OS would use to tell a UPS to go into hibernation is the command ‘/sbin/apcupsd --killpower‘, when apcupsd runs the killpower script. My understanding of the intended process is as follows:

  1. The mains supply to the UPS ceases.
  2. The UPS tells apcupsd that the mains supply has ceased.
  3. apcupsd uses $BATTERYLEVEL, $MINUTES, and $TIMEOUT (set in /etc/apcupsd.conf) to determine when to shutdown the OS (the next step below).
  4. apcupsd runs /etc/apcupsd/doshutdown to initiate shutdown of the OS.
  5. After the OS initiates shutdown, apcupsd (which runs /etc/apcupsd/killpower) tells the UPS to go into hibernation. I think the message to tell the UPS to hibernate is sent $KILLDELAY seconds after /etc/apcupsd/doshutdown runs, where $KILLDELAY is user-configurable. In the case of Gentoo Linux, the apcupsd.powerfail init script (if the user has enabled it) tries to put the UPS into hibernation when the OS is in Runlevel 0 and the OS has almost completed shutting down (the file systems have already been mounted Read-Only).

The message telling the UPS to hibernate can be disabled by setting KILLDELAY=0 in /etc/apcupsd.conf, which I have done. And, just to be sure, I also modified the script /etc/apcups/killpower to do the same thing as the script /etc/apcupsd/doshutdown, and I configured the server’s BIOS not to boot automatically when power is supplied to the server.

I think my caution and disabling of killpower are justified, as the APCUPSD User Manual states:

KILLDELAY time in seconds
If KILLDELAY is set, apcupsd will continue running after a shutdown has been requested, and after the specified time in seconds, apcupsd will attempt to shut off the UPS the power. This directive should normally be disabled by setting the value to zero, but on some systems such as Win32 systems apcupsd cannot regain control after a shutdown to force the UPS to shut off the power. In this case, with proper consideration for the timing, the KILLDELAY directive can be useful. Please be aware, if you cause apcupsd to kill the power to your computer too early, the system and the disks may not have been properly prepared. In addition, apcupsd must continue running after the shutdown is requested, and on Unix systems, this is not normally the case as the system will terminate all processes during the shutdown.

The as-installed configuration file apcupsd.conf contained the following settings:

$ grep -v "^#\|^;\|^$" /etc/apcupsd/apcupsd.conf.original
UPSCABLE smart
UPSTYPE apcsmart
DEVICE /dev/ttyS0
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd
PWRFAILDIR /etc/apcupsd
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 5
MINUTES 3
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd.status
LOGSTATS off
DATATIME 0

The purposes of BATTERYLEVEL, MINUTES and TIMEOUT are explained in the configuration file’s comments:

[...]
#
# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so
# the first that occurs will cause the initation of a shutdown.
#

# If during a power failure, the remaining battery percentage
# (as reported by the UPS) is below or equal to BATTERYLEVEL,
# apcupsd will initiate a system shutdown.
BATTERYLEVEL 30
# Was 10 but I changed it to 30.

# If during a power failure, the remaining runtime in minutes
# (as calculated internally by the UPS) is below or equal to MINUTES,
# apcupsd, will initiate a system shutdown.
MINUTES 10
# Was 3 but I changed it to 10.

# If during a power failure, the UPS has run on batteries for TIMEOUT
# many seconds or longer, apcupsd will initiate a system shutdown.
# A value of 0 disables this timer.
#
#  Note, if you have a Smart UPS, you will most likely want to disable
#    this timer by setting it to zero. That way, you UPS will continue
#    on batteries until either the % charge remaing drops to or below BATTERYLEVEL,
#    or the remaining battery runtime drops to or below MINUTES.  Of course,
#    if you are testing, setting this to 60 causes a quick system shutdown
#    if you pull the power plug.
#  If you have an older dumb UPS, you will want to set this to less than
#    the time you know you can run on batteries.
TIMEOUT 0

[...]

 

Lead-acid batteries degrade faster if they are allowed to become flat or nearly flat, so I changed the battery level percentage to 30 instead of 10. I also changed the remaining runtime (as calculated by the UPS) from 3 minutes to 10 minutes. The resulting contents of apcupsd.conf are as follows:

$ grep -v "^#\|^;\|^$" /etc/apcupsd/apcupsd.conf
UPSNAME ES700
UPSCABLE usb
UPSTYPE usb
DEVICE
POLLTIME 60
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd
PWRFAILDIR /etc/apcupsd
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 30
MINUTES 10
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 300
STATFILE /var/log/apcupsd.status
LOGSTATS off
DATATIME 0

I also edited the apccontrol script to: a) fix a typo in a message in the script; b) comment out the command to reboot the server; c) comment out the command to shutdown the server (as my version of the doshutdown script performs that task):

$ diff /etc/apcupsd/apccontrol /etc/apcupsd/apccontrol.original 
90c90
<       echo "Battery power exhausted on UPS ${2}. Doing shutdown." | ${WALL}
---
>       echo "Battery power exhaused on UPS ${2}. Doing shutdown." | ${WALL}
103c103
< #     ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
---
>       ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
107c107
< #     ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
---
>       ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
$ cat /etc/apcupsd/apccontrol
#!/bin/sh
#
# Copyright (C) 1999-2002 Riccardo Facchetti 
#
#  for apcupsd release 3.14.10 (13 September 2011) - debian
#
# platforms/apccontrol.  Generated from apccontrol.in by configure.
#
#  Note, this is a generic file that can be used by most
#   systems. If a particular system needs to have something
#   special, start with this file, and put a copy in the
#   platform subdirectory.
#

#
# These variables are needed for set up the autoconf other variables.
#
prefix=/usr
exec_prefix=${prefix}

APCPID=/var/run/apcupsd.pid
APCUPSD=/sbin/apcupsd
SHUTDOWN=/sbin/shutdown
SCRIPTSHELL=/bin/sh
SCRIPTDIR=/etc/apcupsd
WALL=wall

#
# Concatenate all output from this script to the events file
#  Note, the following kills the script in a power fail situation
#   where the disks are mounted read-only.
# exec >>/var/log/apcupsd.events 2>&1

#
# This piece is to substitute the default behaviour with your own script,
# perl, or C program.
# You can customize every single command creating an executable file (may be a
# script or a compiled program) and calling it the same as the $1 parameter
# passed by apcupsd to this script.
#
# After executing your script, apccontrol continues with the default action.
# If you do not want apccontrol to continue, exit your script with exit 
# code 99. E.g. "exit 99".
#
# WARNING: the apccontrol file will be overwritten every time you update your
# apcupsd, doing `make install'. Your own customized scripts will _not_ be
# overwritten. If you wish to make changes to this file (discouraged), you
# should change apccontrol.sh.in and then rerun the configure process.
#
if [ -f ${SCRIPTDIR}/${1} -a -x ${SCRIPTDIR}/${1} ]
then
    ${SCRIPTDIR}/${1} ${2} ${3} ${4}
    # exit code 99 means he does not want us to do default action
    if [ $? = 99 ] ; then
        exit 0
    fi
fi

case "$1" in
    killpower)
        echo "Apccontrol doing: ${APCUPSD} --killpower on UPS ${2}" | ${WALL}
        sleep 10
        ${APCUPSD} --killpower
        echo "Apccontrol has done: ${APCUPSD} --killpower on UPS ${2}" | ${WALL}
    ;;
    commfailure)
        echo "Warning communications lost with UPS ${2}" | ${WALL}
    ;;
    commok)
        echo "Communications restored with UPS ${2}" | ${WALL}
    ;;
#
# powerout, onbattery, offbattery, mainsback events occur
#   in that order.
#
    powerout)
    ;;
    onbattery)
        echo "Power failure on UPS ${2}. Running on batteries." | ${WALL}
    ;;
    offbattery)
        echo "Power has returned on UPS ${2}..." | ${WALL}
    ;;
    mainsback)
        if [ -f /etc/apcupsd/powerfail ] ; then
           printf "Continuing with shutdown."  | ${WALL}
        fi
    ;;
    failing)
        echo "Battery power exhausted on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    timeout)
        echo "Battery time limit exceeded on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    loadlimit)
        echo "Remaining battery charge below limit on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    runlimit)
        echo "Remaining battery runtime below limit on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    doreboot)
        echo "UPS ${2} initiating Reboot Sequence" | ${WALL}
#       ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
    ;;
    doshutdown)
        echo "UPS ${2} initiated Shutdown Sequence" | ${WALL}
#       ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
    ;;
    annoyme)
        echo "Power problems with UPS ${2}. Please logoff." | ${WALL}
    ;;
    emergency)
        echo "Emergency Shutdown. Possible battery failure on UPS ${2}." | ${WALL}
    ;;
    changeme)
        echo "Emergency! Batteries have failed on UPS ${2}. Change them NOW" | ${WALL}
    ;;
    remotedown)
        echo "Remote Shutdown. Beginning Shutdown Sequence." | ${WALL}
    ;;
    startselftest)
    ;;
    endselftest)
    ;;
    battdetach)
    ;;
    battattach)
    ;;
    *)  echo "Usage: ${0##*/} command"
        echo "       warning: this script is intended to be launched by"
        echo "       apcupsd and should never be launched by users."
        exit 1
    ;;
esac

I made sure the /etc/apcupsd/hosts.conf file specifies the daemon is monitoring the server:

$ grep -v "^#\|^;\|^$" hosts.conf 
MONITOR 127.0.0.1 "Local Host"

I configured the scripts in /etc/apcupsd/ as shown in the listings below (I have obscured my e-mail address for security reasons). Note that the firewall for my server is a virtual machine (with hostname serverfw) on the server, hence the additional command to shutdown the virtual machine too.

$ cat /etc/apcupsd/annoyme 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# starts sending out 'annoy me' messages.
#
cat /home/fitzcarraldo/apcups/ups-email-annoyme.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-annoyme.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS is sending 'annoy me' messages - investigate now.

 

$ cat /etc/apcupsd/changeme 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery should be replaced.
#
cat /home/fitzcarraldo/apcups/ups-email-changeme.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-changeme.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS battery needs to be changed.

 

$ cat /etc/apcupsd/commfailure 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# loses contact with the UPS (i.e. the serial connection is not responding).
#
cat /home/fitzcarraldo/apcups/ups-email-commfailure.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-commfailure.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Host has lost communication to the UPS.

 

$ cat /etc/apcupsd/commok 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# restores contact with the UPS (i.e. the serial connection is restored).
#
cat /home/fitzcarraldo/apcups/ups-email-commok.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-commok.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Host to UPS communication has resumed.

 

$ cat /etc/apcupsd/doreboot 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# requests a reboot. We do nothing - the APC must not request a reboot.
#
# This script should never be run, as I commented it out in apccontrol.
cat /home/fitzcarraldo/apcups/ups-email-doreboot.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-doreboot.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS has requested a reboot - doing nothing.

 

$ cat /etc/apcupsd/doshutdown 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that a  shutdown is needed.
#
cat /home/fitzcarraldo/apcups/ups-email-doshutdown.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-doshutdown.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS requested shutdown, shutting down the systems.

The server has to be powered up manually after it has powered down.
It will not boot automatically when the mains power supply is restored.

 

$ cat /etc/apcupsd/emergency 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that an emergency shutdown is needed.
#
cat /home/fitzcarraldo/apcups/ups-email-emergency.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-emergency.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS emergency shutdown requested, shutting down the systems.

 

$ cat /etc/apcupsd/failing 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery charge is below the minimum level.
#
cat /home/fitzcarraldo/apcups/ups-email-failing.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-failing.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS battery is failing, shutting down the systems.

 

$ cat /etc/apcupsd/killpower 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol before
# apcupsd kills the power in the UPS. You probably
# need to edit this to mount read-only /usr and /var,
# otherwise apcupsd will not run.
#
cat /home/fitzcarraldo/apcups/ups-email-killpower.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-killpower.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The APC daemon is powering off the UPS - shutting down the systems.

Actually the APC daemon does not power off the UPS since I edited
/etc/apcupsd/killpower so that it only performs the same actions
as /etc/apcupsd/doshutdown, namely 'shutdown -h now'. This means
the UPS continues to supply output power until the battery has
run down completely if there is a long delay until the mains power
supply is restored. The server has to be powered up manually if
it has powered down; it will not boot automatically when the mains
power supply is restored.

 

$ cat /etc/apcupsd/loadlimit 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the remaining battery charge is below the min threshold.
#
cat /home/fitzcarraldo/apcups/ups-email-loadlimit.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-loadlimit.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS battery charge below threshold, shutting down the systems.

 

$ cat /etc/apcupsd/mainsback 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the mains has returned with /etc/apcupsd/powerfail
# file created.
#
cat /home/fitzcarraldo/apcups/ups-email-mainsback.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-mainsback.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Mains back on UPS.

 

$ cat /etc/apcupsd/offbattery 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when the
# UPS goes back on to the mains after a power failure.
#
cat /home/fitzcarraldo/apcups/ups-email-offbattery.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-offbattery.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power resumed to UPS. No longer running on batteries.

 

$ cat /etc/apcupsd/onbattery 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when the UPS
# goes on batteries.
#
cat /home/fitzcarraldo/apcups/ups-email-onbattery.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-onbattery.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power failure on UPS. Running on batteries.

 

$ cat /etc/apcupsd/powerout 
#!/bin/sh
cat /home/fitzcarraldo/apcups/ups-email-powerout.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-powerout.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power out on UPS.

 

$ cat /etc/apcupsd/remoteshutdown 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# is being shut down remotely - should never happen so do nothing.
#
cat /home/fitzcarraldo/apcups/ups-email-remoteshutdown.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-remoteshutdown.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Remote UPS shutdown requested - do nothing but investigate.

 

$ cat /etc/apcupsd/runlimit 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the remaining battery run time is below the threshold.
#
cat /home/fitzcarraldo/apcups/ups-email-runlimit.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-runlimit.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS remaining run time is below limit, shutting down the systems.

 

$ cat /etc/apcupsd/timeout 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery run time limit has been exceeded.
#
cat /home/fitzcarraldo/apcups/ups-email-timeout.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-timeout.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS run time limit is exceeded, shutting down the systems

 

$ cat /etc/apcupsd/ups-monitor
#!/bin/sh
case "$1" in
        poweroff | killpower)
                if [ -f /etc/apcupsd/powerfail ]; then
                        echo ""
                        echo -n "apcupsd: Ordering UPS to kill power... "
                        /etc/apcupsd/apccontrol killpower
                        echo "done."
                        echo ""
                        echo "Please ensure the UPS has powered off before rebooting."
                        echo "Otherwise, the UPS may cut the power during the reboot!"
                        echo ""
                fi
        ;;
        *)
        ;;
esac
exit 0

 

That UPS you bought for your home server may not be as useful as you think

Some years ago I decided to install a server at home for use as a NAS (network-attached storage) in my home network, and for an Internet-facing server. I live in a place where blackouts are very infrequent (perhaps a couple per year), but occasionally the mains drops out for only a second or two. I suspect these very short dropouts occur when substation switchgear operates, but have no way of being sure. Anyway, with a server running 24/7 I obviously wanted protection against any loss of the mains supply.

I ended up buying a 700VA APC Back-UPS ES-BE700G-UK, which has four mains sockets that are battery-backed and also have surge protection, plus another four mains sockets that have surge protection but are not battery-backed. Additionally, it has two RJ45 sockets to provide pass-through filtering for an Ethernet connection. It also has a USB port for connection to the server so that it can transmit unsolicited status information to the server (including requesting the server to shutdown) and can also be interrogated by the server using the apcaccess command. The APC UPS daemon works with this model of UPS, and was relatively easy to set up. APC, formerly American Power Conversion Corporation, is a subsidiary of European company Schneider Electric. My UPS was manufactured in The Philippines.

I have three devices plugged into the battery-backed sockets on the APC UPS: the server, an external 6TB USB HDD connected to the server for automated daily backups by the server, and a 5-port Ethernet switch. The battery in the UPS would provide between 15 and 20 minutes of power when the mains fails, although I have configured the UPS to trigger the server to shutdown when 30 per cent of the battery power remains, as battery life is reduced considerably if its power is allowed to drain completely. In case you’re wondering why my router is not also plugged into the UPS, due to the position of the broadband provider’s socket the router is in a different room and I have therefore had to connect it to a different UPS, an iLEPO multi-functional DC UPS (the ECO PLUS 412P, which is tiny but can keep the router powered for several hours). Obviously the router needs to be connected to a UPS, otherwise the server would not be able to send me e-mails when there is a mains power cut. Being able to receive UPS status e-mails from the server is important to me when I am away from home on work trips.

So I thought I had covered all bases, and, indeed, the UPS proved useful on several occasions. I would quite often be on a work trip and receive an e-mail from the server informing me that mains power to the UPS had been lost, then another e-mail soon after informing me that mains power to the UPS had returned. Only once did the power cut last longer than the battery capacity, and the server was shutdown automatically.

Now, the life of the 12-volt lead-acid battery in the APC UPS is supposed to last approximately three to five years. The life will depend on how many times the battery is discharged and ambient temperature.

While I was away from home on a long work trip, suddenly I could no longer connect to my server and I had not received an e-mail from the server informing me of any problem. Luckily it was near the end of my trip so I was not too inconvenienced. When I arrived home I found that the UPS was sounding an alarm and was not supplying power to the server even though there was mains supply to the UPS. It transpired that the UPS battery had suddenly died without warning and could no longer hold a charge, and this had happened while there was mains supply to the UPS, i.e. there had not been a power cut while I was away. Fortunately there was no loss of data on the server; I was able to run fsck during boot-up.

This failure was annoying on two counts. Firstly, the battery was only about thirteen months old (the manufacturing date stamped on the UPS box was only two or three months before the date I purchased the UPS). Secondly, I certainly did not expect the UPS to stop supplying power to the server while there was mains supply to the UPS. The APC white paper on UPS topologies, ‘The Different Types of UPS Systems‘, does not make this behaviour clear.

It turns out that the type of UPS topology (‘Standby’ — see the model’s Technical Specifications) in this model of UPS does not continue to provide power to connected equipment when the UPS battery either fails or is disconnected for whatever reason when there is mains power supply to the UPS. A quick search of the Web showed me that I was not alone in discovering this ‘feature’: an APC Back-UPS 350 owner posted ‘UPS Battery Backup — useless when the battery dies?‘.

From what I have read, the so-called ‘Line Interactive’ UPS topology does not suffer this shortcoming, so, the next time I have to buy a UPS for a piece of equipment that requires power 24/7, I will buy a line-interactive UPS rather than a standby UPS. But, before purchasing, I will be sure to ask the manufacturer what the precise model would do if its battery fails or is disconnected while there is mains supply to the UPS. The APC line-interactive UPSs are more expensive than the APC Back-UPS models; now I know why. It’s a pity I was not aware of the shortcoming of the Back-UPS models, as I would have spent more and bought a UPS that continues to work when the battery dies while there is mains supply. I would also hope the UPS would issue an alarm if the battery has failed or is disconnected while there is mains supply. Be sure to ask the manufacturer all these questions if you cannot tolerate a sudden loss of power to your equipment if the battery dies while there is mains supply.

Anyway, after checking that the dead battery was indeed useless I replaced it with a new Yuasa battery that has lasted nearly three years now. I will be replacing it shortly as a precaution, even though it has not had to be used much at all since I installed it. I have not replaced the APC Back-UPS model but I will be replacing the battery at least every three years just to be cautious, and of course taking the old batteries to my local waste disposal centre to be recycled properly. By the way, it is possible to purchase a 12-volt battery manufactured by one of the reputable battery manufacturers such as Yuasa with the same specification as the APC battery, for a significantly lower price than APC charges for replacement batteries (which I suspect are badged by APC in any case).