Hey all 👋
Quick recap for anyone walking in mid-movie: last time, I ragequit my garbage collector project (StopLang, RIP, still not sorry), decided Arch Linux would be the homelab OS "because I hate myself but in a fun way," and set out to Frankenstein an old Dell Inspiron into a server.
Reader. Arch won. Again.
🏴☠️ Arch, Round Two (And Some Other News)
I would like to say the Arch install went fine and I switched to Ubuntu for Strategic Reasons. That would be a lie. What actually happened was a rerun of the exact 2024 highlight reel from last episode, a bootloader that needed convincing, drivers that needed convincing, and me, at 1am, needing convincing this was a good use of a Tuesday. Turns out "Arch-nemesis" wasn't just a clever episode title, it was a prophecy, and apparently my prophecies about my own life choices self-fulfill on a pretty tight schedule.
So: Ubuntu Server, similar as my daily driver (debian), same as the "Easy Life Gang" I already confessed to joining. No shame left to lose here.
While I was in there rethinking the OS, I also did some honest math on what this box actually needed to run; a K8s cluster, several flavors of containers, a metrics stack, all at once — and concluded that "8GB of dreams" was not going to survive contact with that plan either.
The Dell Inspiron got benched — not buried, though I didn't know that at the time. In its place, for now:
- CPU: 10th-gen i5, quad-core — not a data center chip, but it can hold a conversation
- RAM: 16GB — double the dreams, still cheaper than therapy
- GPU: RTX 2050 — currently doing nothing but idling. This is foreshadowing. I don't know for what yet, but it's foreshadowing.
- Storage: 1TB SSD — room for several Kubernetes clusters and all my feelings about them
Still a laptop cosplaying as a server. Just one with a better résumé.
🐧 Ubuntu Server, Minimal, No Notes
No desktop environment, no bloat, nothing I'm going to get emotionally attached to this time. Just a prompt and my own poor decisions:
lscpu | grep -E "Model name|CPU\(s\)"
free -h
lsblk
Four cores, sixteen gigs, a terabyte of blank canvas. A reasonable enough starting point for whatever's about to happen to it.
🏗️ Building the Stack (or: How I Learned to Stop Worrying and Run Five Container Tools At Once)
Episode 1's Step 3 was, and I quote myself, embarrassingly: "No kubeadm, no fancy tools. Just pure, uncut YAML & CLI pain."
That promise survived for about as long as it took me to remember I have a job and a sleep schedule to protect. Here's what actually landed on the box. (the pure pain plan is postponed for later not scrapped)
📦 LXC/LXD — containers that pretend to be VMs
First up, LXD (built on LXC) for anything that wants to feel like a real machine instead of a single disposable process. Docker-style containers are great for "run this one thing," but sometimes you want something that boots, keeps its own init system, and behaves like a small persistent VM without the overhead of actually virtualizing hardware. That's LXD's whole pitch, and it's a genuinely different tool from everything else on this list.
sudo snap install lxd
sudo lxd init
lxd init walks you through storage backend and networking choices. I took most of the defaults and made a mental note to regret that later, which is extremely on-brand for this project.
🐳 MicroK8s - K8s, but I broke my own rule immediately
This is the "K8s or bust" step from last time. It bust, slightly — I said no fancy tools, then installed the fanciest, most single-command Kubernetes distro Canonical makes:
sudo snap install microk8s --classic
microk8s status --wait-ready
microk8s enable dns storage
MicroK8s packs an entire lightweight control plane into one snap, which felt like cheating right up until I remembered this laptop has four cores total and would like to keep a couple for itself. Efficiency won. Pride lost. I've made peace with it.
🔧 CRI-O — because the default runtime felt too easy
MicroK8s ships with containerd as its runtime out of the box, which would've been the sensible thing to just use. Instead I swapped the runtime over to CRI-O — built specifically around Kubernetes' CRI spec rather than being a general-purpose runtime that also happens to speak CRI. Mostly this meant repointing the kubelet at CRI-O's socket instead of containerd's, then losing an evening to why nothing was pulling images anymore, which feels like a homelab rite of passage at this point.
The honest reason: I wanted to actually understand the CRI boundary instead of pretending containerd is the only runtime that exists. The slightly less honest reason: it was there, and I have a problem.
🦭 Podman — for when I don't need the whole orchestra
Not everything needs to go through Kubernetes. Sometimes I just want to run one container, right now, without asking a control plane's permission first. That's Podman — daemonless, rootless by default, and CLI-compatible enough with Docker that alias docker=podman is basically a rite of passage in the container world.
sudo apt install -y podman
podman run --rm hello-world
It lives alongside the MicroK8s/CRI-O side of the house as the quick-and-dirty option, entirely separate from anything the cluster is doing.
📊 Prometheus — watching the chaos happen, in graphs
With four different ways to run a container now active on one laptop, I needed to actually see what was happening instead of vibing based on fan noise. Prometheus scrapes metrics on a schedule and stores them as time series, which beats my previous monitoring strategy of "is it hot, and did it crash."
Right now it's mostly watching node-level stuff — CPU, memory, disk. Container- and cluster-level scraping is still on the list, and a dashboard on top of all this is next, because collecting metrics nobody's looking at is functionally the same as not collecting them. But that's a problem for a laptop that isn't currently on fire.
🤔 Why Not Just Pick One Tool?
Fair question. LXD, Podman, and MicroK8s-with-CRI-O all solve "run an isolated workload" in overlapping ways, and in a real production environment picking one and defending that choice in a design doc would be the entire job.
This is not a production environment. This is a laptop that used to belong to an 8th-gen i5's better-funded cousin, sitting on a shelf in my apartment. The whole point of a homelab is that nobody's stopping me from running four competing container philosophies at once, just to see how they actually differ from the inside instead of from a comparison blog post. The only incident review here is me, at 1am, asking myself why I did this.
🚀 What's Next
Per the original mission list, Step 2 was supposed to be remote SSH access — "because reaching across the room is so 2020." Should be the easy part. Generate a key, copy it over, done in ten minutes.
Reader, it was not ten minutes. That's Episode 3.
(Step 4, the firewall, is still sitting untouched on the list, quietly judging me from a distance. One nemesis at a time.)
💬 Final Thoughts
Hardware: upgraded. Arch: lost, again, exactly as the title predicted. OS: Ubuntu, minimal, unbothered. Stack: five tools deep and actively questioning my life choices. GPU: still idling, still foreshadowing.
This episode was somehow both "I installed five pieces of infrastructure" and "I still haven't done the one thing that was supposed to be the easy step." That checks out. That's the HomeLab life, apparently.
Stay tuned, grab popcorn 🍿, and this time wish the network luck instead of the laptop. It's going to need it.
Top comments (0)