home_server:home_server_setup:other_services:nut

Prev  
 Next

NUT (Network UPS Tools) Setup

NUT is an open source network monitoring and control system. I use a Powershield Commander RT PSCRT1100 a 1100VA/880W, line interactive sinewave UPS. It turns out that this is a slightly modified version of the Voltronic Power Otima II 1.1K. Presumably the unit has been slightly modified for Powershield for the Australian market, mainly hardware plugs and presumably some firmware/software setup. In fact Voltronic Power, headquartered in Taiwan, even states they are a leading OEM/ODM manurfacturer of UPSs, AVRs and inverters. The software provided with the UPS is both propriety and bloated. I want a simple efficient command line / daemon based utility that can monitor performance, control as necessary and report on abnormal operation. Unfortunately the NUT project documentation is not simple to follow. I set this up quite some time ago, so this will not necessarily be up to date.

It turns out the nutdrv_qx driver is usually better suited for Voltronic Power UPSs than the Blazer_usb one. See NUT Voltronic Power UPS Protocol, it is also list under the Voltronic Power section, (various)USB of the NUT Hardware compatibility list.

NUT can be installed by sudo apt install nut. The configuration files are located at /etc/nut :

    nut.conf
        MODE=standalone
    ups.conf
        [KPBUPS]
        # driver = blazer_usb # works
        driver = nutdrv_qx # works with more info than blazer_usb
        port = auto
        desc = "KPTreeServer UPS"
        default.battery.voltage.high=26.9
        default.battery.voltage.low=21.5
        default.battery.charge.low=25
        default.battery.charge.warning=60
        default.battery.charge.restart=30
        default.battery.runtime.low=420
        default.battery.runtime.restart=180
    upsd.conf
        LISTEN 192.168.x.x #IP address of NUT server
        LISTEN 127.0.0.1 3493 #IPv4 NUT port
        LISTEN ::1 3493 # IPv6 NUT port 
    upsd.users
        [admin]
        password = {password}
        actions = SET
        instcmds = ALL
    upsmon.conf
        MONITOR KPBUPS@localhost 1 admin {password} master
        MINSUPPLIES 1
        SHUTDOWNCMD "/sbin/shutdown -h +0"
        NOTIFYCMD /home/baumkp/Myscripts/nut-notify.sh
        POLLFREQ 5
        POLLFREQALERT 5
        HOSTSYNC 15
        DEADTIME 15
        POWERDOWNFLAG /etc/killpower
        NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
        NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
        NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
        NOTIFYFLAG FSD SYSLOG+WALL+EXEC
        NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
        NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
        NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
        NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
        NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
        RBWARNTIME 43200
        NOCOMMWARNTIME 300
        FINALDELAY 5
    upssched.conf
        CMDSCRIPT /bin/upssched-cmd # default

Ensure ownership and permissions are as follows: sudo chown root:nut /etc/nut -R and sudo chmod 640 /etc/nut -R“\.

The output of /bin/upsc KPBUPS@localhost, (or simply upsc KPBUPS):

Init SSL without certificate database
battery.charge: 100                  #calculated value
battery.charge.low: 25               #Set value LB (Low Battery Alarm)
battery.charge.restart: 30           #Set value
battery.charge.warning: 60           #Set value
battery.energysave: no
battery.packs: 1                     #Fix value
battery.protection: yes
battery.runtime: 1680                #calculated value
battery.runtime.low: 420             #Set value
battery.runtime.restart: 180         #Set value
battery.voltage: 27.30
battery.voltage.high: 26.9           #Set value for calculation
battery.voltage.low: 21.5            #Set value for calculation
battery.voltage.nominal: 24.0        #nominal/design value
device.model: LIHVX1K1               #Fix value
device.type: ups                     #Fix value
driver.name: nutdrv_qx
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.version: 2.7.2                #Fix value
driver.version.data: Voltronic 0.01  #Fix value
driver.version.internal: 0.06        #Fix value
input.current.nominal: 4.0           #nominal/design value
input.frequency: 50.0
input.frequency.nominal: 50.0        #nominal/design value
input.phases: 1                      #nominal/design value
input.voltage: 241.7
input.voltage.nominal: 230.0         #nominal/set value
outlet.0.switchable: no
output.current: 0.9
output.current.nominal: 4            #nominal/design value
output.frequency: 50.0
output.frequency.nominal: 50.0       #nominal/design value
output.phases: 1                     #nominal/design value
output.power.maximum.percent: 22
output.power.minimum.percent: 21
output.powerfactor: 0.8              #nominal/design value
output.voltage: 241.6
output.voltage.nominal: 230.0        #nominal/set value
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.firmware: 00303.05               #Fix value
ups.firmware.aux: P00                #Fix value
ups.load: 21
ups.power.nominal: 1100              #nominal/design value
ups.productid: 5161                  #Fix value
ups.start.auto: yes
ups.start.battery: yes
ups.status: OL
ups.temperature: 19.4
ups.type: line-interactive           #nominal/design value
ups.vendorid: 0665                   #Fix value

I have been using NUT on my server and UPS now for about 7 years. In all that time I never got the upsmon part of it operational. This monitors the UPS and sends out messages and shutdown the server on UPS low battery.

It would seem that the current NUT package for Ubuntu 18.04 has been correctly configured to operate with systemd. After updating the configuration file restart the computer and confirm if working. So the following instructions are no longer relevant. Interestingly the NUT systemd configuration is still based upon similar systemd scripts and configuration.

The Ubuntu 16.04 NUT scripts seem to be based upon init.d (located in /etc/init.d), in particular /etc/init.d/nut-server and /etc/init.d/nut-client, (with /etc/init.d/nut-monitor being a link to /etc/init.d/nut-client). Systemd seems to have a method for legacy init.d scripts and creates scripts in /run/systemd/generator.late, in particular, ups-monitor.service.

To see running processes use: sudo ps -e | grep nut and sudo ps -e | grep ups*.

Turn off the existing legacy scripts and systemd handlers, as noted above; sudo update-rc.d nut-client disable, sudo update-rc.d nut-server disable and sudo systemctl disable ups-monitor.service. You may also need to disable the following systemd services: nut-client.service, nut-monitor.service and nut-server.service.

The Kepstin blog gives a good NUT and Systemd discussion Network UPS Tools (nut) and systemd. However it is written for Fedora and there are some nuances required to work with Debian/Ubuntu. For a general understanding of Systemd see DigitalOcean references: Understanding Systemd Units and Unit Files, How To Use Systemctl to Manage Systemd Services and Units, and Systemd Essentials: Working with Services, Units, and the Journal.

First we need to get the NUT driver running, “sudo vim /etc/systemd/system/nut-driver.service”

[Unit]
Description=Network UPS Tools - power device driver controller
After=network-online.target

[Service]
ExecStart=/sbin/upsdrvctl start
ExecStop=/sbin/upsdrvctl stop
Type=forking

[Install]
WantedBy=multi-user.target

My system takes a bit of time for the network system to fire up, so I delay the NUT driver startup until after the network is up, by adding the directive “After=network-online.target”.

Unfortunately when this script is run, “sudo systemctl start nut-driver.service” it reports failure as it is unable to access the directory ”/var/run/nut“. So we can create the directory with: “sudo mkdir /var/run/nut sudo chown root:nut /var/run/nut sudo chmod 770 /var/run/nut”. This allows nut-driver.service to run, but fails after a reboot. Further investigation shows that ”/var/run“ is a symlink to ”/run“ and the command “df -T” shows that /run is a temporary file system mounted in RAM that must be recreated every boot. Inspection of the init.d NUT files show they include creation of the /var/run/nut directory. In systemd .conf files must be created in the /usr/lib/tmpfiles.d that create these emphemeral directories, see “man tmpfiles.d”. So we need to create the file: “sudo vim /usr/lib/tmpfiles.d/nut-driver.conf” and populate so:

#Type Path        Mode UID  GID  Age Argument
 d    /run/nut    0770 root nut  -   -

Next in order to ensure correct handling of emergency poweroffs and test reboots correctly, check the /lib/systemd/system-shutdown/nutshutdown file exists; “sudo vim /lib/systemd/system-shutdown/nutshutdown” and populate so:

#!/bin/sh
/sbin/upsmon -K >/dev/null 2>&1 && /sbin/upsdrvctl shutdown

Next create the systemd nut server service for /sbin/upsd, configuration file, “sudo vim /etc/systemd/system/nut-server.service

[Unit]
Description=Network UPS Tools - power devices information server
After=nut-driver.service

[Service]
ExecStart=/sbin/upsd
Type=forking

[Install]
WantedBy=multi-user.target

Next create the systemd nut monitor service, /sbin/upsmon, configuration file, “sudo vim /etc/systemd/system/nut-monitor.service

[Unit]
Description=Network UPS Tools - power device monitor and shutdown controller
After=nut-server.service

[Service]
ExecStart=/sbin/upsmon
PIDFile=/run/nut/upsmon.pid
Type=forking

[Install]
WantedBy=multi-user.target
  • List all the UPS device profile variable /bin/upsc KPBUPS@localhost 2>/dev/null.
  • A script file to succinctly log the UPS data, using cron to run script every 10 minutes sudo Myscripts/UPSScan.sh 2>/dev/null,
    #!/bin/bash
    # Logging output for NUT UPS Monitor output
    
    strf='/var/log/UPSLog.Log'
    str0='/bin/upsc KPBUPS@localhost'
    str1=$($str0)
    str2=$(echo "$str1" | grep "ups.status:")
    echo $(date +"%Y-%m-%d %H:%M:%S") | awk '{printf "%s  ", $0}'           >>"$strf"
    echo "$str1" | grep "ups.temperature:" | awk '{printf "%s ", $2}'       >>"$strf"
    echo "$str1" | grep "ups.load:" | awk '{printf "%s ", $2}'              >>"$strf"
    echo "$str1" | grep "input.voltage:" | awk '{printf "%s ", $2}'         >>"$strf"
    echo "$str1" | grep "output.voltage:" | awk '{printf "%s ", $2}'        >>"$strf"
    #echo "$str1" | grep "input.voltage.nominal:" | awk '{printf "%s ", $2}'        >>"$strf"
    echo "$str1" | grep "battery.voltage:" | awk '{printf "%s ", $2}'       >>"$strf"
    echo "$str1" | grep "battery.charge:" | awk '{printf "%s ", $2}'        >>"$strf"
    echo "$str1" | grep "battery.runtime:" | awk '{printf "%s ", $2}'       >>"$strf"
    #echo "$str1" | grep "input.frequency:" | awk '{print $2}'              >>"$strf"
    echo "$str1" | grep "input.frequency:" | awk '{printf "%s ", $2}'       >>"$strf"
    echo "$str2" | awk '{                   \
            for (i=2; i<=NF; i++) {         \
                    printf("%s ", $i);      \
            }                               \
            printf("\n") }'                                                 >>"$strf"
  • A script file to rotate a log file out to a dated gzip log file, with a new empty log file, the log file with path is the script input sudo rotatelog.sh /var/log/UPSLog.Log, again can be use with cron monthly to rotate a log file.
    #!/bin/bash
    logfile=$1
    if [ ! -f $logfile ]; then
      echo "log file not found $logfile"
      exit 1
    fi
    timestamp=`date +%Y%m%d`
    newlogfile=$logfile.$timestamp
    cp $logfile $newlogfile
    cat /dev/null > $logfile
    gzip -f -9 $newlogfile
  • The NUT service (start / stop / status / restart) command:“sudo systemctl status nut-server.service”
  • To list the available UPS commands: “upscmd -l KPBUPS”
  • Some other scripts:
    • To email notifications from nut: nut-notify.sh (not tested)
      #!/bin/sh
      #echo "$*" | mailx -s "UPS Notice" baumkp@gmail.com

The NUT binaries issue a SSL error to STDERR, so the addition of 2>/dev/null suppresses this.

The parameters set in ups.conf; default.battery.voltage.high and default.battery.voltage.low are used to calculate battery runtime and battery charge level and for low battery alarming. These values can be configured to account for varying battery performance, due mainly to type, age.

List the available NUT UPS commands: upscmd -l KPBUPS

Instant commands supported on UPS [KPBUPS]:

beeper.disable - Disable the UPS beeper
beeper.enable - Enable the UPS beeper
beeper.toggle - Toggle the UPS beeper
load.off - Turn off the load immediately
load.on - Turn on the load immediately
shutdown.return - Turn off the load and return when power is back
shutdown.stayoff - Turn off the load and remain off
shutdown.stop - Stop a shutdown in progress
test.battery.start - Start a battery test
test.battery.start.deep - Start a deep battery test
test.battery.start.quick - Start a quick battery test
test.battery.stop - Stop the battery test

Example to disable the UPS beeper: upscmd beeper.disable The command will prompt for a user then password. This is a valid user and password define for the NUT installation as defined in the file /etc/nut/upsd.users as noted above.

                      T         Voltage      Battery                S
                      e     L                V     C    R t   f     t
                      m     o                o     h r  u i   r     a c
                      p     a                l     a g  n m   e     t o
                            d   in    out    t       e    e   q     u d
                      o                                             s e
YYYY-MM-DD  HH:MM:SS  C     %   VAC   VAC    VDC   %    Sec   Hz    
2020-12-01  00:20:01  20.3  11  244.7 243.9  27.30 100  3660  50.0  OL

Some known Status Code:

  • OL = On Line (running from main power supply, no adjustments)
  • OB = On Battery
  • ALARM OL RB = Alarm, On Line, Replace Battery
  • OL CAL = On Line Calibrating
  • Systemctl related commands:
    • Systemd common commands (start / stop / restart / status) (enable / disable for boot control)
    • List current Systemd operating units: sudo systemctl list-units | grep '*. Change or remove the grep statement as required.
    • Check the boot journal: journalctl -xe
  • To check running process with open for openvpn(/del, for deluge) ps -A | grep open

  • /mnt/shared/www/dokuwiki/data/pages/home_server/home_server_setup/other_services/nut.txt
  • Last modified: 2022-08-27 Sat wk34 07:04
  • by baumkp