Home Server Refresh
Table of Contents
I recently went through a bit of a ‘home server’ refresh and thought I’d document the experience here. I’m going to cover why I maintain home servers, why I did the refresh, what the migration was like, and the little tweaks I made along the way. Hopefully this is helpful to people who want to go through something similar in the future!
Part 1: Why Do I Have Home Servers? #
All of Part 1 could probably be summed up in a very simple sentence: I’m a nerd. That’s basically it. I’ve loved computers as a hobby my entire life, and my career has also been centred around computers in one way or another. If you’re not a nerd who loves tinkering with computers, I’m not here to convince you that you should do any of this. Go take up mountain climbing or something!
For the longer explanation, I use home servers for a couple of specific purposes:
- Running Channels to record and stream over-the-air TV to various devices.
- Running Home Assistant, a home automation server that integrates with almost every smart home device to help it all work together smoothly.
- Running my ‘RSS2Social’ script that monitors this very blog and posts to the blog’s Mastodon and Bluesky accounts.
- Running Printopia, a Mac Application that takes my non “AirPrint” printer and makes it available to my network as an AirPrint printer, so me and my family can print to the printer from any Apple device.
I accomplished this using two always-on computers:
- A 2015 MacBook Pro that ran Channels and Printopia
- A Raspberry Pi 3 that ran Home Assistant and RSS2Social
These served me well for a long time, but I eventually decided that the MacBook Pro needed to be replaced. Apple stopped providing MacOS updates for it, and the fine folks at Channels wouldn’t support that version anymore. Fair enough!
I contemplated getting the new very small, very cute (and surprisingly insanely powerful) Mac mini M4, thinking it would give me enough overhead to last a long time, and maybe even get some use as my desktop computer. But at ~ $1000 CAD after taxes, it was hard to justify the cost. In the end, I found a used (still very capable) Mac mini M1 for $450 and settled on it.
Part 2 - The Migration #
The Mac mini setup was very quick. I was going to run it (as I did the old MacBook Pro) ‘headless’ in that there would be no monitor or keyboard attached, and I’d just remote into it (over SSH or screen sharing.) I initially connected a keyboard, monitor, and mouse to set it up. The old MacBook Pro had a Time Machine backup, but I decided to just set up fresh and manually migrate and reinstall what I needed on the new one. Macs are pretty good about not letting a bunch of installed stuff slow the system down, but I like starting fresh sometimes!
To make it run headless, I had to do a couple of things:
- Make sure that it wouldn’t go to sleep
- Enable SSH and Screen Sharing
- Have it boot up in the case of power loss
- Have it log in automatically upon boot
The last two steps weren’t strictly necessary, but I wanted to make sure it would boot up and still record shows for me (or let me stream remotely) if I was out of town. It’s a bit of a security risk that it logs into the account automatically, but I feel somewhat fine about it, because it’s in my house, and it’s an area where anyone breaking in would be very unlikely to notice it. (Nevertheless, I did account for this scenario, which I’ll cover in the improvements section.)
The next steps were to start migrating stuff. Before I did this, I of course made backups of everything I wanted to migrate over. All of the media that Channels records already went onto an external hard drive attached to the MacBook, so that was taken care of. All I really needed to do was get a backup file from Channels for all my library metadata, scheduled recordings, etc. I also used Hazel, the file automation tool, to keep the downloads folder clean and do some periodic maintenance to my Channels library, so I grabbed a backup of its rules.
So all I needed to do was put the Mac into its hidey-hole, plug in the external hard drive, and install Channels, Hazel and Printopia!
Channels makes it very easy to restore from the backup file it produces. Once installed I verified that I could access it from my Apple TV and iPhone. It may have just been a placebo, but it did feel like loading images and streaming video was a lot faster when served from the Mac mini.
Oh, lastly I should mention that I installed Tailscale on the Mac mini. I’ve talked about Tailscale before, but it’s basically a way of letting you access a device as if it were on your network from another device, as long as they both have Tailscale installed and on your network. Very handy for remotely accessing the Mini, and especially handy for watching stuff from Channels while on the go.
From there, I was all set up with the Mac mini. But then I thought, hey, I have this relatively powerful computer. Why not just run everything on it, including Home Assistant and my RSS2Social script? This takes us to the next section, which is a bit of a detour.
Part 2.5 - A Brief Detour from the Pi #
The RSS2Social script is a Python script that I run as a CRON job every 15 minutes, checking for new posts and posting as appropriate. It maintains a basic database of past posts so it doesn’t (hopefully) double-post. Migrating it wasn’t super straightforward. There are a bunch of dependencies I needed to install that the script relies on, but I got it done. One challenge though is that the Mac doesn’t have the ability to use CRON to schedule jobs. There is a similar tool on Mac called ’launchd,’ but frankly, I was too lazy to learn it. So I found Lingon, which is basically a very nice graphical front-end for creating ’launchd’ jobs, which I used to set up the job for RSS2Social.
I had been running Home Assistant on the Pi 3 as a Docker container, so I figured it would be relatively painless to just spin down the Pi container, grab its latest backup file, spin it up on the Mac, and restore from the backup file. And I was right! I got it all migrated in about ten minutes. And, at first, it worked great!
Over the next few days though, I started having problems. I use HomeKit Bridge for the Home Assistant to push over a bunch of non-HomeKit compatible stuff to Apple Home. Suddenly, all of these devices showed up as not responsive in Apple Home. Then, some of the devices in Home Assistant itself wouldn’t respond!
I did a bunch of troubleshooting (mostly by asking ChatGPT what to do), tinkered with some Docker settings I only half-understood (not a great idea!), and still couldn’t get it working. After some digging, I realized that when it comes to networking anyway, Docker and Macs do not play nicely. So it was back to the Pi.
Except… that Pi was almost 10 years old at this point, and there are a few Home Assistant features (like a Matter server) that just aren’t supported on the Pi 3. So I decided to get a Pi 5, which would give me a lot of horsepower for the years to come.
I went with a basic kit that included a case, memory card, power supply, and a fan. I was honestly very impressed with the whole package, and for some reason got a weird amount of joy out of installing that little fan and assembling the case.
Once the Pi 5 was up and running, installing Home Assistant via Docker was again very easy, as was restoring from the latest backup. (I also, of course, installed Tailscale for remote access.) And once it was up and running, all of my Home Assistant and HomeKit connectivity issues. vanished! Home Assistant was now running perfectly smoothly again. In fact, it ran better than before. I definitely noticed that restarts and even automations and page loading went faster on the new little Pi. I loved it.
Part 3 - Improvements #
So after that little detour, I basically had my original setup all working again, but on beefier hardware. Now it was time for some improvements.
Improvement 1: Healthchecks.io #
First off, as mentioned, I was slightly worried about someone stealing that Mac mini and me not finding out with enough time to wipe it. So I wanted to set up a kind of ‘dead man’s switch’ that would alert me if the Mac mini hadn’t checked in in a while. I consulted ChatGPT and it suggested I use Healthchecks.io.
Healthchecks.io is a mostly free service (I think there is a paid tier that I don’t need) that will generate a unique URL for you that can be pinged from anywhere. You can set up the check such that if it doesn’t get pinged within a specified amount of time, you’d get alerted. The default is email, but there are other services as well (I set up Signal as a secondary alert system.)
So I created a checks URL for my Mac, made a curl
command out of it, and set up Lingon to run that command every 15 minutes. I then configured Healthchecks to alert me if it didn’t get a ping after 20 minutes. Setting this up was immensely gratifying. While I was at it, I set up an alert for the Pi 5 as well.
I also got the idea that it would be good to be alerted if my Home Assistant backups weren’t working. After Pipocaplyse I got very serious about regularly backing up my Home Assistant files.) I had already made a little script that backed up my Home Assistant backups to various places. So with the help of ChatGPT, I added a section that would ping a unique Healthchecks URL only if both backups were successful. These were less urgent alerts to act on than a stolen Mac, but it was nice to have the peace of mind to know that I’d be alerted if the backups stopped working so I could fix them again.
Improvement 2: Pi-hole #
Pi-hole is a self-hosted application you can install that blocks ads at the network level. Once installed, you make it your DNS server, and it will block any request that points to a known ad server. You can change your router to this DNS so all devices in your house block ads as well.
I’d experimented with Pi-hole before but bounced off it after a while when I got tired of maintaining it. But since the Pi 5 still had some headroom, I thought, why not try again?
I installed Pi-hole as a Docker container as well, so setup was very straightforward, and I confirmed that it blocked things okay. One of the things that was frustrating about PiHole in the past though is that it only worked for devices on your own network. But since I had Tailscale on the Pi, I thought… maybe?
It turns out Tailscale actually provides instructions for how to do exactly this by flipping a setting to have a specific Tailscale device act as your DNS for all your devices connected to the Tailscale network. I followed the instructions and I successfully got it working! It’s incredibly satisfying to block ads wherever I happen to be on my phone.
Wrap-Up #
So that’s it! New, beefy hardware for my home servers, along with some peace of mind improvements to make sure things are running smoothly, with ads blocked everywhere as a bonus.
I skipped over a ton of details, like specific set-up instructions, or how I migrated my SSH keys, or even set up my Terminal stuff. But most of this is Google-able. I know I mentioned before, but having ChatGPT as a companion doing all this stuff really did make everything a breeze, as I could just ask very specific questions and often get a very specific terminal command to run in just the way I wanted. (This was especially helpful for building Docker containers.)
And as much as I wanted to ditch the Pi and simplify my stack a bit, I’m honestly glad it’s there. I like keeping a little Linux in my life somewhere.