The Architect and the Slumlord: A Homelab Philosophy
There are two ways to build a homelab. The fast way and the right way. I chose the right way, not because a homelab needs it, but because the habits formed here are the ones I reach for under pressure.
Update, July 2026: the cluster has since grown to two nodes. The constraint argument stands.
There are two ways to build a homelab.
The first way is fast. Spin up a VM, install Docker, docker compose up, expose a port, done. When something breaks, you fix it. When you want to add something, you add it. The system grows organically: a .env file here, a bind mount there, maybe a cron job to back things up if you remember. It works. Millions of homelabs run exactly like this, and they serve their owners well.
The second way is slow. You choose an immutable OS that you can't SSH into. You write Kubernetes manifests by hand. You encrypt secrets with age keys and commit them to Git. You write network policies that default to blocking everything and then painstakingly allow each connection that needs to exist. You set resource limits, health probes, and liveness checks on every single container. You build an observability pipeline before you deploy your first real application.
I chose the second way. Not because it's better. It's not, for most people. I chose it because I wanted to understand what it means to operate infrastructure, not just run it.
The Architect and the Slumlord
I have a framework I use for thinking about how I build things. I call it "The Architect vs. The Slumlord."
The Slumlord gets things done. Duct tape, shortcuts, good enough. Ship it, move on, fix it when it breaks. There's real value in this: speed matters, perfection is the enemy of done, and not everything deserves a cathedral. The Slumlord has a function.
The Architect builds things to last. The Architect writes the network policy before the deployment. The Architect versions the config, encrypts the secrets, and writes the rollback plan. The Architect spends an hour on something the Slumlord would finish in five minutes, and the Architect's version is still running six months later without anyone touching it.
A homelab is where I practice being the Architect. Not because my RSS reader needs enterprise-grade infrastructure, but because one day I'll be standing in front of a production outage, and the patterns I practiced at home will be the ones I reach for under pressure. The homelab is a rehearsal space.
Why Constraints Matter
My entire cluster runs on a single Dell laptop with 15.6 GB of RAM. That's it. No rack servers, no 128 GB nodes, no cloud VMs to burst into. Every pod competes for the same memory, the same CPU, the same disk.
This is a feature, not a limitation.
Unlimited resources teach you nothing about resource management. When you have 128 GB, you don't learn to right-size container limits. When you have 10 nodes, you never discover what happens when a DaemonSet consumes 300 MB per instance. When storage is cheap, you don't think about retention policies.
On a 15.6 GB node, I had to learn all of these things. I know that Grafana OOM-kills at 384 MB and needs 512 MB. I know that Longhorn's instance-manager consumes 5.3 GB (a third of my node) and that this might force a storage engine change. I know that Prometheus with default scrape intervals uses twice the memory it needs for my workload, and that 60-second intervals are the right tradeoff between resolution and resource consumption.
None of this shows up in documentation. It only shows up when you operate the system under real constraints and pay attention to what happens.
Everything Through Git
There is no kubectl apply in my workflow. There is no SSH. There is no "let me just quickly change this one thing." Every change to the cluster goes through Git. Flux watches the repository and reconciles every 10 minutes.
This is annoying. The feedback loop is slower than imperative commands. When I'm debugging at 11 PM and I know exactly which label needs to change, waiting 10 minutes for Flux to pick up a commit feels absurd.
But it also means:
- Every change has a commit message explaining why
- Every change can be reverted with
git revert - The cluster can be rebuilt from scratch by cloning one repository
- I never wonder "did I make that change last week or did someone else?" There is no someone else, and the Git log proves it
The discipline of GitOps is the discipline of treating infrastructure as something that deserves the same rigor as application code. Not because a homelab needs it, but because the habits formed here carry over to environments where it matters.
Default-Deny as a Worldview
Every namespace in my cluster starts with a network policy that blocks all ingress and all egress. Nothing talks to anything until I explicitly allow it. This means every new application requires me to think about its dependencies: what does it need to reach, and what needs to reach it?
The Slumlord would skip this. The Slumlord would say: it's a homelab, on a private network, behind a firewall. Who cares about network segmentation? And the Slumlord wouldn't be wrong: the threat model for a homelab behind a Cloudflare Tunnel with no open ports is pretty slim.
I write the policies anyway. Not because I think an attacker is going to compromise my RSS reader and pivot to my password manager. I write them because the practice of thinking about network boundaries, trust zones, and least-privilege access is the single most transferable security skill I've developed. When I write a conditional access policy at work, I'm doing the same thing I do at home: start from deny-all, add explicit allows, and document why each one exists.
Default-deny isn't a network policy. It's a posture. What do I allow, why, and what happens if I'm wrong?
The Stoic Angle
I read a lot of Stoic philosophy. One of the core ideas is the dichotomy of control: focus on what you can control, accept what you can't. A homelab is an almost perfect exercise in this.
I can control how my infrastructure is built. I can control whether secrets are encrypted, whether resource limits are set, whether network policies exist. I can control whether I test my backup strategy before I need it.
I cannot control whether the disk fails. I cannot control whether Talos ships a buggy update. I cannot control whether an upstream container image introduces a vulnerability. I cannot control whether my ISP goes down at midnight.
The Architect builds for the second category by excelling at the first. Disk might fail, so Longhorn replicates volumes and backups go to NFS on a separate machine. Upstream might break, so Renovate pins versions, patches auto-merge, but majors require manual review. The ISP might die, so Uptime Kuma monitors the external path and ntfy alerts me when it happens.
None of this prevents failure. It reduces the blast radius of failure and shortens the time to recovery. That's all any infrastructure can do. The rest is acceptance.
Why Not Just Use the Cloud?
I could run everything in this cluster on a $20/month VPS. Probably cheaper than the electricity the Dell laptop uses. Definitely less work.
But the point was never the services. I don't self-host Miniflux because Feedly is expensive. I don't run Vaultwarden because Bitwarden cloud is untrustworthy. I self-host because the act of building and operating the infrastructure is the thing I'm here for.
A cloud VM with Docker Compose gives me the services. The homelab gives me the understanding. The difference between "it runs" and "I know why it runs, and I know what to do when it stops" is the entire gap between an operator and an administrator.
Every outage I've debugged at home (the Cloudflare Tunnel redirect loop, the Authentik forward-auth 11-commit marathon, the Loki ruler that silently failed because of a mount path), each one gave me intuition I use professionally. Not because the specific technologies overlap (though they often do), but because the pattern of diagnosis overlaps. Something is broken. What changed? What does the error actually say? What layer is the problem at? These are universal questions, and a homelab is a safe place to practice answering them.
Who This Isn't For
If you want to self-host some services and don't care about Kubernetes, Docker Compose is the right answer. If you want high availability and don't want to operate it, a managed Kubernetes service is the right answer. If you want to learn Kubernetes but don't have the patience for immutable infrastructure, use k3s on Ubuntu: it's faster to start, easier to debug, and you can always harden later.
This approach (Talos Linux, Flux GitOps, default-deny, SOPS encryption, full observability stack on constrained hardware) is for someone who wants to build something the hard way because the hard way teaches you things the easy way can't. It's for the person who reads incident postmortems for fun and wonders "would I have caught that?" It's for the Architect.
It's slower. It's more work. It's more frustrating on a Tuesday night when all you wanted was to add a bookmark manager and instead you're debugging Cilium egress policies for 45 minutes.
But when it works, when the whole system hums, every service green, every metric collected, every secret encrypted, every change tracked in Git, there's a satisfaction that no managed service can provide. You built this. You understand it. And when it breaks, you'll fix it, because you know how every piece connects.
That's the philosophy. Build it right. Know why it works. Accept that it will break. Fix it when it does.