Jonathan's Page

Weekend Raspberry PI W Project

Commentstech, tips, tricks, tinker3 min read

https://twitter.com/jsg2021/status/1419557705371488259

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.


Setup PI

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.

  1. Choose OS -> Raspberry Pi OS (other) -> Raspberry Pi OS Lite
  2. Select your SD card
  3. Write!

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:

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="WIFI_SSID"
scan_ssid=1
psk="WIFI_PASSWORD"
key_mgmt=WPA-PSK
}

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 pi@raspberrypi.local (default password: raspberry)

Install all updates & patches

sudo apt-get update && sudo apt-get upgrade -y

Change hostname, default password, etc...

sudo raspi-config #menu app

Reboot: sudo reboot

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-ups
    port = auto
    desc = "My UPS"

EOF

Edit /etc/nut/nut.conf and make the MODE=standalone:

sudo sed -i 's/^MODE=.*/MODE=standalone/g' /etc/nut/nut.conf

Start the server:

sudo upsdrvctl start
sudo service nut-server status

Verify what we've done so far works...

upsc myups

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 = mypasswd
    actions = SET
    instcmds = ALL

[upsmon]
    password = mypasswd
    upsmon master
EOF
Updating upsmon.conf
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:

NOTIFYCMD /etc/nut/upssched-cmd.sh

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+EXEC
NOTIFYFLAG ONBATT       SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT      SYSLOG+WALL+EXEC
# NOTIFYFLAG FSD        SYSLOG+WALL
# NOTIFYFLAG COMMOK     SYSLOG+WALL
# NOTIFYFLAG COMMBAD    SYSLOG+WALL
NOTIFYFLAG SHUTDOWN     SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT     SYSLOG+WALL+EXEC
# NOTIFYFLAG NOCOMM     SYSLOG+WALL
# NOTIFYFLAG NOPARENT   SYSLOG+WALL
#

Save & Exit. (ctrl+x y cnter)

Create upssched-cmd.sh:

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"* ]]; then
  ssh root@gateway-name-or-ip poweroff
fi
EOF

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 restart
sudo service nut-client restart

Push Notifications

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 nut

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.

© 2021 by Jonathan's Page. All rights reserved.