Weekend Raspberry PI W Project
For the last ten years or so, I've been using Ubiquiti gear for my home network. I've grown from the Edge Router Lite, to the UniFi Security Gateway Pro + Cloud Key, and then most recently a UniFi Dream Machine Pro... each one of these devices need graceful shutdowns and do not like having the power dropped on them. I've been mitigating this with a fairly large UPS so the runtime is long enough I can shut them down in the event of a prolonged outage.
This year has had its fair share of electrical issues. Thankfully, like I said before, I put battery backups on all my important gear so they can weather the brownout, or gracefully shut down. This past week there were a few brownouts and the home network dropped each time. Which, was odd. After a short inspection, I found that the UPS protecting my network gear had failed and was no longer switching to battery... performing the self test instantly tripped it off. So, time to replace!
With the replacement in hand, I was reminded that none of my ubiquiti gear supported
USB - HID UPS interfaces... (and now that Ubiquiti has their own redundant power supply product, its not likely to gain that feature) ...then it hit me: A raspberry pi could monitor and
ssh into devices to shut them down. And so, this adventure begins.
I ordered a Raspberry PI Zero W kit and began researching the necessary information to get this off the ground.
The microSD card from the kit is pre-setup, but I don't want a desktop environment, so I re-imaged the sd card. The easiest way to do this is to simply use their Imager. You can download it from the link, or if you are on linux, check the system package manager for
rpi-imager (or snap).
With the Imager in hand, insert the microSD card from the kit into an SD card adapter and run.
- Choose OS -> Raspberry Pi OS (other) -> Raspberry Pi OS Lite
- Select your SD card
Once the imaging is complete, the sd card should have a boot partition. Create an empty file named
ssh there and then create a text file named
wpa_supplicant.conf with these contents:
Update the SSID and password for your network. Save, and eject the sd card. Its now ready to insert into the Raspberry Pi.
Once the pi is all assembled, plugin the USB dongle into pi with the UPS' USB data cable inserted. Plugin power and return to you main computer. It will take 30-90 seconds to come up.
Changing the defaults
The default hostname will be
raspberrypi.local. SSH into the device vi:
ssh email@example.com (default password:
Install all updates & patches
sudo apt-get update && sudo apt-get upgrade -y
Change hostname, default password, etc...
sudo raspi-config #menu app
Getting into the NUTs and bolts
I basically followed this blog post to get NUTs up and running, but I will summarize my steps here for a quick reference :)
sudo apt-get install nut
Set the driver NUT will use to communicate with the UPS:
sudo cat << EOF >> /etc/nut/ups.conf# NOTE: This is for a UPS that connects via USB[myups]driver = usbhid-upsport = autodesc = "My UPS"EOF
/etc/nut/nut.conf and make the
sudo sed -i 's/^MODE=.*/MODE=standalone/g' /etc/nut/nut.conf
Start the server:
sudo upsdrvctl startsudo service nut-server status
Verify what we've done so far works...
The above should spit out lots of info, if it doesn't, you may need to reboot the pi.
Add users to the NUT client
sudo cat << EOF >> /etc/nut/upsd.users[admin]password = mypasswdactions = SETinstcmds = ALL[upsmon]password = mypasswdupsmon masterEOF
sudo nano /etc/nut/upsmon.conf
Jump to the section with
# MONITOR .... Add the line:
MONITOR myups@localhost 1 upsmon mypasswd master
Jump to the section with
# NOTIFYCMD .... Add the line:
Jump to the section with
# NOTIFYFLAG, uncomment lines with the events you care about. At minimum,
NOTIFYFLAG LOWBATT. Add
+EXEC at the end of the lines (that flag tells it to execute the script we added with
NOTIFYCMD) Here's how my section looks:
# --------------------------------------------------------------------------# NOTIFYFLAG - change behavior of upsmon when NOTIFY events occur## By default, upsmon sends walls (global messages to all logged in users)# and writes to the syslog when things happen. You can change this.## NOTIFYFLAG <notify type> <flag>[+<flag>][+<flag>] ...#NOTIFYFLAG ONLINE SYSLOG+WALL+EXECNOTIFYFLAG ONBATT SYSLOG+WALL+EXECNOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC# NOTIFYFLAG FSD SYSLOG+WALL# NOTIFYFLAG COMMOK SYSLOG+WALL# NOTIFYFLAG COMMBAD SYSLOG+WALLNOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXECNOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC# NOTIFYFLAG NOCOMM SYSLOG+WALL# NOTIFYFLAG NOPARENT SYSLOG+WALL#
Save & Exit. (ctrl+x y cnter)
sudo cat << "EOF" >> /etc/nut/upssched-cmd.sh#!/bin/bash#curl -k -X POST \# -F token=<token> \# -F user=<user> \# -F "title=PSU Event" \# -F "message=$*" \# https://api.pushover.net/1/messages.json &> /dev/null &if [[ "$*" == *"battery is low"* ]]; thenssh root@gateway-name-or-ip powerofffiEOF
Update config file owners and permissions:
sudo chown nut:nut /etc/nut/*sudo chmod 640 /etc/nut/upsd.users /etc/nut/upsmon.conf
sudo service nut-server restartsudo service nut-client restart
Open a pushover.net account and setup an application. Get the user key and application token values and put them in the
upssched-cmd.sh and uncomment those lines (curl through https...)
Test it by just running your script from the command line:
sudo -u nut /etc/nut/upssched-cmd.sh "hi"
Generate an ID for
sudo -u nut ssh-keygen
Now that the user has an id, we can make it so that its able to connect without a password to the thing needing shut down by uploading the key:
sudo -u nut ssh-copy-id root@gateway-name-or-ip
NOTE: The Dream Machine/CloudKey/USG do not enable ssh by default. Enable it from the admin web interfaces.