When I first built my FreeNAS machine, I bought an UPS device to give it backup power in case of a power outage. But my primary computer also had a UPS device.
Recently, in order to minimize the amount of equipment that I have, I decided I only wanted to have one UPS. After searching for solutions, I was pointed to Network UPS Tools (NUT), which is open source software that can manage UPS units and the machines they power. This way I can have my primary computer and NAS connected to the same UPS unit, and control them both during certain power events.
Before this, I also started to run PiHole on a VM with my NAS, but I quickly found two issues. First, if the VM halted for some reason, my entire network would too. Also, if I needed to restart my NAS for any reason, the network would also go down.
This finally gave me two solid reasons and goals to justify the purchase a Raspberry Pi. Luckily, the Raspberry Pi 4B 2GB model had just become the primary model at $35, so I knew I’d have plenty of performance to run these two applications.
Since I was not only looking to minimize my homelab’s physical footprint, I also wanted to keep cords and cables to a minimum. So I also decided to get a Power-Over-Ethernet Switch that would allow me to power my Raspberry Pis with just an ethernet connection. I also wanted to reduce the amount of Ethernet wire lengths to make cable management easier, so I purchased a Cat 6 crimper to create my own ethernet cable lengths.
Finally, this new RaspberryPi would allow me to run cron jobs that control scripts on remote machines from the Pi as well such as my Digital Ocean Snapshot script.
So to sum up my goals:
- Run NUT server to monitor my NAS and Windows 10 machine
- Run PiHole
- Execute cron jobs
Network UPS Tools Equipment
Below are all the items I purchased for this project.
|Raspberry Pi 4 2GB||2||$70||PiShop|
|Rasberry Pi Case||1||$5||PiShop|
|16GB SD Card||3||$17.97||Amazon|
|High Pi Case||1||$9.95||PiShop|
|SD to USB Card Reader||1||$9.99||Amazon|
The above doesn’t include shipping or the cost of a mini HDMI cable as I already had one lying around. There’s three SD cards in this list to have one as a backup.
First Raspberry Pi
The Pi and its accessories are incredibly small and easy to put together. The POE switch worked perfectly. I was able to install Raspbian on a SD card and start up the Pi with no issues with the Raspberry Pi Foundation’s Imager Tool. Once I got the basic settings just so, including assigning a static IP address. I disconnected the HDMI and connected via VNC instead, using VNC Viewer.
I typically name my devices after robots from film history. My FreeNAS is named Maria after the female protagonist in Metropolis, and I’ve maintained that naming convention for many of the Virtual Machines, networking equipment, and now my Pi. I named it Worker11811 after the character whose job was to maintain the Moloch machine.
This is an easy step, especially since I had already been running it in a VM. You simply run this code:
curl -sSL https://install.pi-hole.net | bash
That is the basic install and runs your through a few configuration options such as choosing your DNS host (I chose Cloudflare), your static IP address, etc.
Since I already had custom rules and settings from my VM, I used PiHole’s Teleporter to download the settings from the original VM, and then restore it to the newly installed PiHole.
I updated my Router’s DNS settings to point to 192.168.1.3, and boom, PiHole was working as expected.
The Pi will act as both the NUT server and client server as the Pi will act as both. First, I connected my UPS to my Pi and ran lsusb to ensure it could see the UPS.
pi@worker11811-pi:~ $ lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 003: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
No issues there. It sees my CyberPower UPS.
Installing NUT isn’t difficult on Raspbian as there is a Debian package available, and found a few excellent instructions like this one from Medium:
apt-get update && apt-get install nut nut-client nut-server
Next, I added the following lines to the sudo nano /etc/nut/ups.conf file. I found my USB driver for the UPS using this Hardware Compatibility List. It was the same driver that my FreeNAS was using, so I knew it worked well.
[ups] driver = usbhid-ups port = auto desc = "CyberPower 1350PFLCD"
Next, I created users for each of the clients that will be connecting to this NUT server by editing my /etc/nut/upsd.users file:
[admin]password = ****** actions = SET instcmds = ALL
[upsmon_worker11811] password = ****** upsmon master
[upsmon_maria] password = ******* upsmon slave
[upsmon_johnny5] password = ****** upsmon slave
As you can see, there are 4 users. The Admin, worker11811, maria, and Johnny5 (which is my primary Windows 10 machine).
Then I started the nut-client and drivers:
systemctl restart nut-client.service upsdrvctl stop upsdrvctl start
Next, I checked to see if I can see the UPS device via the NUT
pi@worker11811-pi:~ $ upsc email@example.com Init SSL without certificate database battery.charge: 100 battery.charge.low: 10 battery.charge.warning: 20 battery.mfr.date: CPS battery.runtime: 1470 battery.runtime.low: 600 battery.type: PbAcid battery.voltage: 24.0 battery.voltage.nominal: 24 device.mfr: CP1350PFCLCD device.model: CRCA102*AF1 device.serial: CPS device.type: ups driver.name: usbhid-ups driver.parameter.pollfreq: 30 driver.parameter.pollinterval: 2 driver.parameter.port: auto driver.parameter.synchronous: no driver.version: 2.7.4 driver.version.data: CyberPower HID 0.4 driver.version.internal: 0.41 input.transfer.high: 139 input.transfer.low: 88 input.voltage: 123.0 input.voltage.nominal: 120 output.voltage: 139.0 ups.beeper.status: disabled ups.delay.shutdown: 20 ups.delay.start: 30 ups.load: 22 ups.mfr: CP1350PFCLCD ups.model: CRCA102*AF1 ups.productid: 0501 ups.realpower.nominal: 810 ups.serial: CPS ups.status: OL ups.test.result: Done and warning ups.timer.shutdown: -60 ups.timer.start: -60 ups.vendorid: 0764
Additionally, you can run
which will check the UPS’s status every 30 seconds:
pi@worker11811-pi:/usr/local/bin $ upslog Network UPS Tools upslog 2.7.4 logging status of ups@localhost to - (30s intervals) Init SSL without certificate database 20200905 115423 100 123.0 20 [OL] NA NA 20200905 115453 100 123.0 23 [OL] NA NA 20200905 115505 100 123.0 23 [OL] NA NA Signal 2: exiting
Lastly, we can check to see if NUT sees the same machine as a client:
pi@worker11811-pi:~ $ upsc -c ups Init SSL without certificate database 127.0.0.1
The 127.0.0.1 stands for the home machine which is my worker11811 Raspberry Pi. We’ll be using the same command a few more times later.
Updating FreeNAS UPS Settings to become a NUT Client
Now that NUT is working, I had to update the FreeNAS settings. FreeNAS comes with NUT already, making this super easy to update. I made the following changes:
- Switched UPS Mode from Master to Slave (I hate this terminology)
- Added the Remote Host IP to 192.168.1.3 which is my Pi’s internal network address
- Added the Monitor Username and Password
After saving, I immediately noticed that my FreeNAS recognized the connection to my NUT Server on my Pi via the shell.
To double-check, I ran the same
command on the FreeNAS shell, and received the same results when I initially ran it on the Pi. Of course, we’ll run the same client command as before:
pi@worker11811-pi:~ $ upsc -c ups Init SSL without certificate database 192.168.1.9 127.0.0.1
Now it sees my FreeNAS IP address so I’m in good shape here.
Adding Windows 10 as a NUT Client
This is where the real headaches occurred for me at first. Windows support is severely lacking. I was only able to find an ancient winNUT Google Code repository and a MSI installer directly on the NUT site. After attempting to get both to work and nearly a week of frustration, I uninstalled both.
I stumbled upon this Github repo called WinNut-Client which has a super-simple interface to setup your Windows machine connection to your NUT server. After downloading the MSI file, installing, and setting up the config I had my Windows machine capturing the UPS data and was able to setup the settings to choose when and how I want this machine to shutdown. There’s even a hibernate option which I prefer over a full shutdown which I prefer if I’m away from my computer.
You can also choose how the service starts at the machine’s startup, how often it looks for updates, etc. What I didn’t see is the client appear on my NUT Server, so I opened an Issue on the Github repo to get clarification.
Monitoring the UPS with NUT
NUT comes with several CGI programs that can be viewed in a browser. However, I had issues attempting to log into http://192.168.1.3/cgi-bin/nut/upsstats.cgi. After some time, I realized that PiHole uses Litehttp web server that already uses port 80. Wherease, NUT uses Apache. I updated
and restarted Apache. Going to http://192.168.1.3:8080/cgi-bin/nut/upsstats.cgi brought up a result that reminded me of the internet’s nascent days:
Regardless, my UPS’s stats were easily revealed to me.
The 4th generation Pis run rather hot, more so with the POE hat, which even comes with a fan that sits right on top of the CPU. When inside the official case, the temperatures were reaching the high 70s in Celsius. This was quite worrying. I ended up purchasing the HighPi case which is meant to provide extra room for taller hats. I figured this would be an excellent way to hopefully get more air to the Pi. This ended up reducing the temperatures, but not to where I really prefer.
I was able to find instructions to configure the Pi to manage the POE fan speeds to keep the fan from being on all the time. Otherwise, there’s a high-pitched whine. Of course, as I was testing this, I had to restart the Pi each time. So there’s a balance between the speed of the fan and the temperatures that I feel are appropriate. The goal is generally to keep the CPU below 80 degrees as that is when the CPU begins to throttle performance.
Network downtime with reboots
The first issue I encountered was that if I need to reboot my Pi when I was working on it or installing generally updates, it would take down my network for about a minute. This was essentially the same problem I experienced prior to this project. So, I really hadn’t fixed this problem.
Second Raspberry Pi
The downtime issues is where I realized that I’d prefer to have a second PiHole machine in order to have 100% uptime. Therefore, I purchased another Pi and POE hat, but chose to remain with the official Pi case I already had. To continue the Metropolis naming scheme, I named this one Rotwang after the primary antagonist.
I ran through the same processes as before, except I chose not to run a graphic interface with this Pi, using just SSH to manage the device. After I installed PiHole, and ran the Transporter process to have mirror settings through the web interface.
I had found this Reddit post of someone sharing their script on how to keep two PiHoles synced. I don’t believe it works that well, but essentially, if one Pi goes down or is rebooted, I still have a network connection.
While writing this post, I recently stumbled upon this post about sycning two PiHoles, that might be a better option than what I have now. I expect to try it out sometime in the future. (EDIT/UPDATE [Sept. 7th, 2020]: This script works as described and is super easy to install and run.)
Backing up the Pis & Data Recovery
One thing I learned quickly is that the Pis don’t have a power off button. So if they lose power abruptly without powering down, it could corrupt the SD Card data.
I found this super-simple Pi backup script on GitHub, and it’s been working like a charm. I have these backups sent to their respective folders on my FreeNAS, so they are always in a safe place.
Even recently this has been helpful. In attempting to make some changes to one of the Pis, it wouldn’t reboot. Instead of getting mad, I was able to write the backup image to the backup SD card and reboot with no issues.
Entering into the Raspberry Pi universe has been fun and I see why these little guys are so popular. Anytime I start to find myself relying on a Virtual Machine in my FreeNAS machine, I start to consider whether or not it’s better to run that application on one of these Pis or add an additional one.
I still worry about the temperatures for both Pis, which are running in the low 70 degree Celcius range. After removing both Pis from their cases for a few days and found them to operate within the 50 degree range, which is much more reasonable to me. I am considering a Cloudlet case such as this one where I can have all the Pis setup in an array with plenty of airflow and the ability to run a POE switch near by.
Overall, I’m super happy with this setup, and I recognize that I certainly over-engineered this entirely. I spent over $150 just to have one less UPS near my gear. Honestly, I could have just added a Serial Connect from the UPS to the NAS and maintained the USB connection to my Windows machine. I’ve learned a lot and I’m happy with what I’ve accomplished.