Bootstrapping a Homelab the Hard Way
A view into my homelab and some notes on running a small dynamic cloud on three Raspberry Pis, three mini PCs, and an old Dell laptop.
I wanted a homelab where I could experiment and break things without worrying about how long it would take to rebuild. I had three Minisforum MS-01s, a Dell Inspiron laptop gathering dust, and a couple of Raspberry Pis that I had picked up for automation and AI projects, including experiments with the AI HAT+. Three MS-01s were enough for most cluster designs, but reinstalling an OS across all three every time got old. Inspired by production private-cloud environments, I decided to make most of my compute available on demand through PXE. Today, that lab runs a Canonical OpenStack cluster.
The Bootstrap Problem#
My homelab has a chicken-and-egg problem. I want MAAS (Metal as a Service) to manage the machines, but MAAS needs a place to run. I also want Landscape to monitor and update them, but its server needs a home too. If each foundational service requires another bootstrap layer, I spend more time rebuilding the platform than using it across projects.
My answer is a three-tier chain. The only machines I install by hand are three Raspberry Pi 5s; I started with two and added a third so I could cluster them. Everything else, including the machine that deploys OpenStack, is PXE-booted and provisioned from those Pis. If I wiped the MS-01s and the Dell tomorrow, I could bring the lab back without plugging in a USB stick.

Tier 0: The Raspberry Pis#
The three Pi 5s run Ubuntu Core with MicroCloud. Ubuntu Core gives me a transactional, snap-based base system that is difficult to break accidentally. MicroCloud gives me a clustered LXD environment across the three nodes without the overhead of full virtual machines. On that cluster, I run MAAS, Landscape Server, Docker inside a system container—yes, nested containerization—and a few other services I want to keep stable.
MAAS runs on the Pis for a practical reason: it is not a high-frequency workload, and I want the provisioner on the lowest-power machines with the fewest moving parts. Three Pis draw only a handful of watts each and avoid making one x86 box the single machine that everything else needs in order to boot. The three-node MicroCloud layer can remain available if one Pi goes down, although each workload still needs its own redundancy plan.
Tier 1: The Dell Inspiron#
Once MAAS is online, it can PXE-boot and commission an x86 node, deploy Ubuntu, and make the machine available to Juju. My first node in that tier is an old Dell Inspiron laptop. It is unremarkable hardware, but it has a specific job: hosting the Juju controller and a small governor VM. In the current OpenStack deployment, it runs the services needed to build the cloud while remaining outside the cloud itself.
Tier 2: The MS-01s#
The three Minisforum MS-01s are the workhorse tier. Each provides 14 cores and 20 threads, 64 GB of RAM, two 1 TB NVMe drives, two 10 GbE SFP+ ports, and two 2.5 GbE ports. They run Canonical OpenStack in a hyperconverged topology, with control, compute, and storage services distributed across all three nodes.
Three nodes give the Ceph monitor layer enough quorum to tolerate one monitor host failing, and they support a conventional three-node HA control plane. Storage durability still depends on the pool’s replica and failure-domain settings.
The MS-01s fit this design because they combine two 10 GbE SFP+ ports with two 2.5 GbE ports. I use one SFP+ port on each node for a 10 GbE Ceph replication VLAN, while OAM and management traffic stay on the 2.5 GbE side, so the paths do not compete. With Intel AMT configured on these systems, I can also use remote KVM without adding a separate management card. It is not a full BMC, but it gives me a similar out-of-band management workflow at homelab scale.
Networking: Where Most of the Pain Actually Lives#
Most of the failures in this lab have started at Layer 2. VLANs sound simple until a node being commissioned by MAAS sees DHCP traffic but never receives an address. In one case, the switch was dropping tagged frames on an access port because of an old configuration change. I now separate traffic into logical networks: OAM and management traffic, including PXE, uses the 2.5 GbE links; Ceph replication has its own VLAN over the SFP+ uplinks; and regular household traffic stays segmented from both. That last boundary matters because nobody wants the homelab taking down the house internet.
The L2/L3 boundary is where I have burned the most hours. When commissioning fails—or Ceph traffic takes the gateway instead of a direct path, turning 0.4 ms into 7 ms of latency—the culprit is usually the switch, a forgotten trunk configuration, or another networking setting.
What Lives Outside the Cluster: NAS and the GPU Tier#
Two parts of the rack sit outside the dynamic chain but remain essential to daily use. Together with the clustered tiers, they make up what I jokingly call my “production” homelab—safely hidden in a closet.

The first is a self-built NAS with 12 TB of storage. It lives outside the cluster and holds personal files, media, backups, and the long tail of data I do not want tied to infrastructure that I wipe every month or so. I deliberately kept it out of Ceph because it has a different failure domain. I want that data to survive a full homelab redeployment, regardless of what I am doing with OpenStack.
The second is the AI/ML tier: an NVIDIA Jetson Nano and an NVIDIA DGX Spark. The DGX Spark runs MicroK8s with the GPU Operator and time-slicing enabled, and it mounts the NAS over NFS so fine-tuning runs have persistent storage. These systems are more integrated with the lab than the NAS. For larger experiments, I sometimes extend the Kubernetes cluster to run tools such as Kubeflow and schedule GPU workloads onto the Spark as a tainted node.
I wrote about my DGX Spark setup in a separate post: Kubernetes on the NVIDIA DGX Spark.
The Jetson is along for a future project involving a small ground robot and, eventually, a drone. That is a while away, and it is not doing anything useful today beyond sitting on the shelf, reminding me that it exists. It used to be part of a local-AI smart home project, but it broke, and I never got around to fixing it.

What “Production” Would Actually Mean#
I do not run any load-bearing workloads on this OpenStack cluster. A handful of VMs support the lab itself: Landscape and related patch-management components, COS (Canonical Observability Stack) for dashboards and monitoring, and PostgreSQL and MySQL databases for testing. I would only call the cluster “production” if it had workloads I depend on, enough hardware for meaningful high availability at every tier, and a genuinely heterogeneous compute layer spanning Arm and AMD systems.
That framing is why I am happy to keep the lab in its current split state. The interesting work is not making the cluster bigger; it is making the existing pieces fit together better and contributing what I learn back to the projects that power it.
Two Hundred Watts#
The whole rack idles at around 200 W—roughly the draw of a single gaming PC. That budget covers three OpenStack nodes, a MicroCloud cluster, a Juju controller, and the beginnings of a GPU tier. I think about that number whenever I consider adding hardware. Most of the time, I can learn more by improving how the existing systems fit together than by buying another box.
