<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Homelab on Casey Robb</title><link>https://neozeon.io/tags/homelab/</link><description>Recent content in Homelab on Casey Robb</description><generator>Hugo</generator><language>en</language><lastBuildDate>Tue, 20 Oct 2026 19:15:52 -0600</lastBuildDate><atom:link href="https://neozeon.io/tags/homelab/index.xml" rel="self" type="application/rss+xml"/><item><title>Thirty Apps, One Repo: Anatomy of a GitOps Homelab Cluster</title><link>https://neozeon.io/posts/chaos-cluster-anatomy/</link><pubDate>Sun, 18 Oct 2026 19:30:00 -0600</pubDate><guid>https://neozeon.io/posts/chaos-cluster-anatomy/</guid><description>&lt;h2 id="thirty-apps-one-repo-anatomy-of-a-gitops-homelab-cluster"&gt;Thirty Apps, One Repo: Anatomy of a GitOps Homelab Cluster&lt;/h2&gt;
&lt;p&gt;Somewhere between running my first app on Kubernetes and running my thirtieth,
the problem changed shape. It stopped being &amp;ldquo;how do I deploy this&amp;rdquo; and became
&amp;ldquo;how do I know what my cluster &lt;em&gt;is&lt;/em&gt;, and how do I change it without
nuking &amp;amp; paving.&amp;rdquo; My answer is a single GitLab repo &lt;a href="https://gitlab.com/caseyrobb/iac"&gt;gitlab.com/caseyrobb/iac&lt;/a&gt;: one ApplicationSet
generator, one allowlist per cluster, one thin wrapper chart per app, and a
handful of infrastructure operators doing the rest. The production cluster,
&lt;code&gt;chaos&lt;/code&gt; (k0s, six nodes on mini PCs at home — no, the name is not
prophetic; mostly), runs thirty-two apps out of that repo and has never had a
&lt;code&gt;kubectl apply&lt;/code&gt; from a human.&lt;/p&gt;</description></item></channel></rss>