I've been running a homelab for about 5 years now, starting with a single Raspberry Pi to experiment with Linux. It's evolved into something quite useful, and the latest iteration is something I'm interested in sharing more about.
I fondly refer to this setup as ROSE23, with ROSE standing for "Residence Orchestration, Storage, and Entertainment", and this being the 2023 iteration. The last time I did a significant refresh was in 2020, so I'll refer to that as ROSE20. As I mentioned previously, the hardware has undergone a recent update which saw the dedicated QNAP NAS replaced by a Thunderbolt SSD enclosure.
Beyond hardware, the biggest changes to my homelab setup for the 2023 edition is the full adoption of Tailscale as the secure networking layer that connects all of the components and an ingress node running in the DigitalOcean TOR1 region. Running Tailscale on all nodes has allowed me to securely add this high-bandwidth entrypoint with a static IP (which made certain things a lot easier) while maintaining the security of the nodes running inside my house and providing an efficient exit node for securing internet traffic when I'm away from home.
The main components
Let's get into the setup, which is comprised of a few main parts:
- Mac mini M1 running Plex and NextCloud (Dockerized), plus TimeMachine backup targets.
- Connected to an OWC ThunderBay mini 4 SSD enclosure. RAID-4 with 4 2TB drives for a total usable volume of 6TB.
- Advertised as a Tailscale exit node
- DigitalOcean droplet in the TOR1 region running an NGINX reverse proxy
- Advertised as a Tailscale exit node
- Raspberry Pi 4b running HomeAssistant OS
- Connected over Ethernet for network access (and to a Philips Hue bridge for Smart home control)
- I've ordered the SkyConnect dongle to add a Thread Border Router for future smart home things.
- Ubiquiti Unifi Dream Machine bridging to a Bell ISP modem
- Connected to a NetGear 8-port unmanaged ethernet switch, which then connects to all of the above components.
- Personal devices, including iPhone 15 Pro, Apple Watch Ultra 2, iPad Pro (M2), MacBook Pro (M1 Pro), and a work laptop.
- My wife also has a MacBook Air (M1), an iPhone 11, an iPad Pro (M1), and an Apple Watch.
Yes, we are so deep in the Apple Ecosystem I don't think we could see the blue sky if we looked straight up, but it has become so well integrated that I don't really have any complaints that are severe enough to make me want to change that. I'll also fully admit that there is nothing economically efficient about the bullet points above. You could achieve many of the same capabilities with a set of devices that are half (or even less) expensive, but with how incredibly well all of this has been working, I also can't find myself complaining about the relatively high price.
You’ll also notice it’s sitting on a ‘sled’, the dimensions of which are not quite right. Those bays were designed around the outgoing NAS (which was much larger than the ThunderBay), so I need to find some time to rebuild it. Maybe next year.
Going in the same order, let's cover the software running on each of the main components:
Plex, TimeMachine, NextCloud
On the Mac mini, there are 3 main services.
Plex runs as the native Plex Media Server distribution. When first installing this as part of the ROSE20 refresh (when the Mac mini first entered the scene), the consensus on Reddit seemed to be that running Plex in Docker on Apple Silicon had poor performance, so I opted for the native install. It’s been operating perfectly well, even transcoding 4K footage in realtime, so I’m not feeling the need to move it into Docker for now. I’ll re-evaluate for the next refresh. The Plex library is stored on the ThunderBay drive (recently migrated from the ROSE20 QNAP NAS).
TimeMachine is configured using macOS’ built-in folder sharing capability. A folder on the ThunderBay is set as available for network sharing, which is the Apple-recommended way to back up one Mac to another. The other Macs in the house have added the exposed folder as a network drive using the mini’s Tailscale MagicDNS address, thereby allowing them to back up over the secure overlay network even when not on home Wifi. It’s a pretty neat trick that has been working incredibly well.
NextCloud is one of two major new software additions to the ROSE23 stack. My main use case that led to installing such a heavy suite was the desire to back up my iOS photo library. Using iCloud, all our iOS devices are backed up on Apple’s servers, but I wanted a local copy of the photos specifically. After some research, I landed on NextCloud, specifically the ‘NextCloud All-In-One’ Dockerized distribution (NCAIO). During install, I opted for a pretty minimal set of features, as I had no need for the full office suite or Talk suite. Installation took some time to get just right, as the documentation (while thorough) is very dense and took some time to put together the perfect docker-compose file and associated NGINX config for the ingress node. The Docker containers are mounted to a volume, which is mapped to a folder on the ThunderBay using the
local volume driver.
The NextCloud iOS app now backs up my entire iOS camera roll. The initial sync of my nearly 19k photos took nearly 20 hours, largely bottlenecked by the fact that the uploads needed to route through the ingress node, thus capping the uploads to our home internet’s underwhelming upload speeds of 11mbps. I’ll talk more about why this was needed below.
Closely related to NextCloud above is the new addition of NGINX running on a DigitalOcean droplet in the TOR1 region. While installing NextCloud, I learned pretty quickly that it really, REALLY does not like to run without a valid TLS certificate accessible on the public internet. I tried several times to only expose the instance on the Tailnet using
tailscale cert and Tailscale MagicDNS, but several layers of frustrating errors prompted me to make a compromise (none of which are Tailscale’s fault, for the record).
I decided to set up an ingress node on DigitalOcean to provide a static IP and public DNS record to make NextCloud happy. With my recent employment news, it made sense to deploy NGINX on the new ingress node, and well… it was pretty simple! Since NextCloud uses LetsEncrypt to manage its own certificates, the NGINX install needed to reverse proxy the encrypted TLS stream without terminating TLS itself, which is accomplished with a
stream block to tunnel TCP traffic on
http block proxies HTTP traffic on
:80 for the challenge server. Tailscale is installed on the ingress node, and the
upstream for both server blocks is set to the MagicDNS name for the Mac mini, which means that no ports are exposed on my home network, no dynamic DNS is needed, and the upstream traffic is end-to-end encrypted using WireGuard. A firewall was added to the droplet so that only HTTP/HTTPS and SSH traffic are allowed in or out of the node.
Tailscale is my favourite new addition to the stack, as it‘s added a new level of simplicity and peace of mind to the whole ordeal. Every single device (except our two Apple Watches, future post on that) now has Tailscale running on it, allowing secure communication no matter where each device is located. Our Macs back up via TimeMachine even when we’re in another country. Our tablets can stream from Plex over Starlink, and the ingress node can securely backhaul to the NextCloud server running at home.
Above and beyond the basics of creating a secure WireGuard connection between each device, the three key Tailscale features I’ve come to appreciate are MagicDNS, Exit Nodes, and ACLs.
- MagicDNS allows configurations for the various services to reference a stable name, and Tailscale will automatically route traffic correctly. Simple and super handy.
- Exit nodes allow one or more devices on the Tailnet to become effectively a VPN. When enabled on a device like my iPad, all internet traffic is diverted through the WireGuard tunnel and the selected exit node, which is an extra layer of security. Exit nodes can optionally allow additional access to the local network they’re running on, so when I’m away from home (and my phone automatically selects the Mac mini as its exit node using a Shortcut), it’s as if I never left the home network.
- Finally, ACLs allow creating routing rules between nodes, which means that I can restrict the DigitalOcean ingress node to solely access the Mac mini and no other devices, giving me an extra bit of comfort and a ‘defense in depth’ mindset.
The Raspberry Pi’s only job is to run HomeAssistant OS. This new addition came about after my frustration of how slow and unreliable Google Assistant’s control of our various smart home devices had become. About a month ago, I connected all of our devices to HomeAssistant and then re-directed Google (and HomeKit!) to use HomeAssistant instead of individual cloud-based connections, and it works great! I’ve barely dipped into the power that HA provides, but for now it’s giving us speed and reliability that the former Google-centric setup did not have. The nice thing is that HomeAssistant‘s parent company sells a USB dongle for the Raspberry Pi that includes a Thread radio, so as our current devices start getting phased out for Matter-compliant devices (that’ll be a 2024 project), it will all just work.
The full scope of our smart home is large enough for another post entirely, so for now I’ll leave it at that. The best part of HomeAssistant is simply that I no longer have to wonder if Google will fail to turn off all the lights at night with its classic ‘sorry, 3 lights aren’t responding right now’, forcing me to go all the way downstairs. For the past month, it’s worked every time. Oh, and with the Tailscale plugin for HomeAssistant OS, I can debug the entire setup remotely (since the HA iOS app uses the Raspberry Pi’s MagicDNS name as the controller address), so if my wife texts me to say something isn’t working, I can fix it from anywhere.
The other parts
Per my ’personal tech stack’ post recently, there are a number of other bits to my new approach to personal technology. The next post will be about attempting to use my watch as my primary computer, which has some interesting results. There’s an email version of this blog that only receives my absolute favourite posts, so don’t worry about being spammed. Since I’m off social media, the only way you can let me know what you think would be to text me, email me, or find me on Discord. I’ll leave that as an exercise to the reader if you have strong enough thoughts to bother 🙂.