Unraid配置NUT连接UPS
2021 from–https://forums.unraid.net/topic/93341-tutorial-networked-nut-for-cyberpower-ups/
I should start with the disclaimer that I have no particular expertise with NUT so this guide is not definitive.
I have a Cyberpower UPS (CP685AVR) powering a Raspberry Pi and my Unraid Server.
Initially I installed apcupsd on the Pi, connected it to the UPS (via USB) and setup Unraid as slave. Install was fairly straightforward and worked well except for automatic restart after shutdown – when power’s restored connected servers must be booted manually. (NOTE: If your CyberPower UPS is connected directly to your unRAID server, enabling Turn off UPS after shutdown in settings not only won’t work but may cause the UPS to cut power without warning, forcing a parity check.)
I settled on NUT running as master on the Pi (Debian-based) connected to the UPS via USB, with Unraid and all other clients as slaves.
Overview
We can trigger shutdown one of two ways – after a set amount of time on battery or at a set battery level.
The timer method is more robust because if, after a power outage and shutdown, power’s restored and the system boots but it’s lost again, unraid may pick up the battery-level shutdown signal before the startup process completes which seems risky. And that may happen several times.
Instead we’ll set NUT to shutdown clients after 20 minutes on battery (approximately 20% of my runtime capacity) so in theory it can handle a couple of these power’s restored/power’s lost cycles.
Low battery will still trigger shutdown but the goal’s to avoid a low battery condition.
Let’s get started:
On Raspberry Pi
sudo apt install nut
# Verify UPS is visible with
lsusb
# Configure
sudo emacs /etc/nut/ups.conf
# My configuration block in ups.conf
[cyberpower]
driver = usbhid-ups
port = auto
desc = "UPS CP685AVR"
offdelay = 20
ondelay = 0
ignorelb
override.battery.charge.low = 20
override.battery.charge.warning = 40
pollinterval = 15
A few notes about these settings:
offdelay says turn UPS off X seconds after master server shuts off, required for automatic restart
ondelay should be 30 (10s greater than off delay) but a cyberpower bug requires 0 to avoid unexpected power cuts (similar to apcupsd behavior)
a shorter pollinterval is required to prevent the Pi (and maybe other debian systems) from losing contact
ignorelb allows custom overrides for battery.charge
# Start
upsdrvctl start
# Configure nut upsd
sudo emacs /etc/nut/upsd.conf
# Add network request listener replacing
LISTEN
# User setup
sudo emacs /etc/nut/upsd.users
# Add users for admin, monitoring, local and remote users replacing pwd with your preferred password
[admin]
password = pwd
actions = SET
instcmds = ALL
[local]
password = pwd
upsmon master
[remote]
password = pwd
upsmon slave
[monuser]
password = pwd
upsmon slave
# Configure monitoring
sudo emacs /etc/nut/upsmon.conf
# Change the following values:
# Increase slave shutdown wait period to 10 minutes (worst case)
HOSTSYNC 600
# Works with pollinterval setting to prevent USB disconnection
DEADTIME 25
# Alerting twice/day about a battery change is excessive, make it once
RBWARNTIME 86400
# To be safe give clients an additional 90 seconds to fully shutdown
FINALDELAY 90
# Add monitor replacing pwd with the password you specified for [local] above
MONITOR cyberpower@localhost 1 local pwd master
# Timed shutdown – see upssched.conf for details
NOTIFYCMD /sbin/upssched
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
# Set the schedules in upssched.conf:
sudo emacs /etc/nut/upssched.conf
# Verify it has the line
CMDSCRIPT /bin/upssched-cmd
# Add:
# Command pipe and lock-file
PIPEFN /var/run/nut/upssched.pipe
LOCKFN /var/run/nut/upssched.lock
# Send alerts immediately on change in line power
AT ONBATT EXECUTE onbatt
AT ONLINE EXECUTE onpower
# (Optional) Silence the beeper after 2 minutes
AT ONBATT START-TIMER mute_beeper 120
AT ONLINE CANCEL-TIMER mute_beeper
# Shutdown after 20 minutes on battery (20 60 = 1200)
AT ONBATT START-TIMER onbatt_shutdown 1200
# Cancel timer if power’s restored
AT ONLINE * CANCEL-TIMER onbatt_shutdown
# Battery replacement indicated by cron’d quick test
AT REPLBATT * EXECUTE replace_batt
# Customize the executable called by upssched
sudo emacs /bin/upssched-cmd
# …by replacing existing code with the following (substituting the password you set for admin earlier for
# START: User-specific settings
#
UPS_USERNAME="admin"
UPS_PASSWORD="
UPS_LINK="cyberpower@localhost"
# END
case $1 in
onbatt)
make sure beeper is enabled
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.enable
# alert
message="Power outage, on battery"
logger -t upssched-cmd "$message"
;;
onpower)
message="Power restored"
logger -t upssched-cmd "$message"
;;
mute_beeper)
message="(2) minute limit exceeded, muting beeper"
upscmd -u ${UPS_USERNAME} -p ${UPS_PASSWORD} ${UPS_LINK} beeper.mute
;;
onbatt_shutdown)
message="Triggering shutdown after (20) minutes on battery"
logger -t upssched-cmd "$message"
/sbin/upsmon -c fsd
;;
replace_batt)
message="Quick self-test indicates battery requires replacement"
logger -t upssched-cmd "$message"
;;
*)
logger -t upssched-cmd "Unrecognized command: $1"
;;
esac
# Verify it’s executable by all:
ls -l /bin/upssched-cmd
# Schedule the (weekly) quick test mentioned earlier
sudo crontab -e
# Add
# Weekly UPS self-test
0 2 MON /bin/upscmd -u admin -p
# Configure nut as netserver
sudo emacs /etc/nut/nut.conf
# Change MODE
MODE=netserver
Now reboot the Pi to verify the NUT services launch on startup
# Confirm services are running
sudo service nut-server status
sudo service nut-client status
# Confirm communication with UPS – this should return a bunch of info
upsc cyberpower
On Unraid
# Install NUT from CA
# Configure as follows using the Pi IP, monuser password and remote password specified earlier
# NOTE: Whether in the case of a timed shutdown or an emergency low battery shutdown
# we’re relying on the Pi (NUT server) to send the signal. Ideally the shutdown triggers here
# won’t be used.
1208822292_ScreenShot2021-01-23at5_33_32AM.thumb.png.3bb0b7cbf27e6b7b8330e729573cfe3a.png
Miscellaneous
# Test shutdown.
# NOTE: This will shutdown your system so it’s safest if you stop the array first.
# But stopping is most of the required shutdown time, so after you confirm
# this works you might want to test again without stopping the array.
sudo upsmon -c fsd
Optional
# Cyberpower uses status codes not recognized by the NUT plugin which as far as I can tell only affect display but I want my dashboard to be pretty so let’s customize the display script (NOTE: this will get overwritten, and possibly cause conflicts, on plugin update)
mkdir /boot/extras/nut
cp /usr/local/emhttp/plugins/nut/include/nut_status.php /boot/extras/nut/nut_status.php
vi /boot/extras/nut/nut_status.php
# Replace the state array with the following
$state = [
‘OL’ => ‘Online’,
‘OL CHRG’ => ‘Online: charging‘,
‘OL CHRG LB’ => ‘Online: charging‘,
‘OL DISCHRG’ => ‘Online: discharging‘,
‘OL DISCHRG LB’ => ‘Online: discharging‘,
‘OL BOOST’ => ‘Online: low voltage‘,
‘OB DISCHRG’ => ‘Offline: On battery’,
‘OB LB’ => ‘Offline: Low battery’
];
# If you prefer the look of the built-in UPS dashboard, the next two sections (presented in diff form) mimic it
# diff /usr/local/emhttp/plugins/nut/include/nut_status.php.orig /usr/local/emhttp/plugins/nut/include/nut_status.php
44,45c48,49
< $runtime = gmdate("H:i:s", $val);
< $status[2] = strtok($val/60,' ')<=5 && !in_array('ups.status: OL', $rows) ? "<td $red>$runtime</td>" : "<td $green>$runtime</td>";
---
> $runtime = strtok($val/60,' ');
> $status[2] = strtok($val/60,' ')<=5 && !in_array('ups.status: OL', $rows) ? "<td $red>".intval($runtime)."m</td>" : "<td $green>".intval($runtime)."m</td>";
49a54,56
> case 'input.voltage':
> $voltage = intval(strtok($val,' '));
> break;
64c71
< $status[3] = $power==0 ? "<td $red>${power}w</td>" : "<td $green>${power}w</td>";
---
> $status[3] = $voltage<114 ? "<td $orange>${voltage}V</td>" : "<td $green>${voltage}V</td>";
# diff /usr/local/emhttp/plugins/nut/nutFooter.page.orig /usr/local/emhttp/plugins/nut/nutFooter.page
151a152
> <span class='ups'>Input voltage:</span><span class='nut_nompower'></span><br>
154d154
< <span class='ups'>Nominal power:</span><span class='nut_nompower'></span><br>
# Set your go file to overwrite the default files with the customized version on boot
vi /boot/config/go
# Add to the end:
# Customize nut (UPS) display
cp /usr/local/emhttp/plugins/nut/include/nut_status.php /usr/local/emhttp/plugins/nut/include/nut_status.php.orig
cp /boot/extras/nut/nut_status.php /usr/local/emhttp/plugins/nut/include/nut_status.php
# display voltage instead of max power
cp /usr/local/emhttp/plugins/nut/nutFooter.page /usr/local/emhttp/plugins/nut/nutFooter.page.orig
cp /boot/extras/nut/nutFooter.page /usr/local/emhttp/plugins/nut/nutFooter.page
All done. Automatic shutdown of the servers and UPS work and (assuming proper BIOS settings) they’ll all restart when power’s restored.
Edit 7/6/2020: Increase offdelay to account for slow unraid shutdown
Edit 1/23/2020: Misc reliability tweaks, shift from battery level-based shutdown to timer-based shutdown