<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Homelab on Jahvon Dockery</title>
    <link>https://jahvon.dev/architecture/homelab/</link>
    <description>Recent content in Homelab on Jahvon Dockery</description>
    <image>
      <title>Jahvon Dockery</title>
      <url>https://jahvon.dev/images/og-default.png</url>
      <link>https://jahvon.dev/images/og-default.png</link>
    </image>
    <generator>Hugo -- 0.153.4</generator>
    <language>en-us</language>
    <atom:link href="https://jahvon.dev/architecture/homelab/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How flow Runs the Cluster</title>
      <link>https://jahvon.dev/architecture/homelab/flow-workflows/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://jahvon.dev/architecture/homelab/flow-workflows/</guid>
      <description>There is no GitOps controller. Every deploy is a composed executable, secrets come from the vault, and the diagnostics half exists because it is 11pm.</description>
      <content:encoded><![CDATA[<h2 id="how-flow-is-actually-used">How flow Is Actually Used</h2>
<p>This is the part worth writing down.</p>
<p>The repo <em>is</em> a flow workspace. All of its automation lives in one <code>.execs/</code> directory, split by
concern rather than by application: utilities, cluster operations, apps, infrastructure,
networking, storage, platform, labs, and aggregates. It&rsquo;s a couple thousand lines of flow YAML,
which sounds like a lot until you consider it replaced a pile of shell scripts and a much larger
pile of things I used to keep in my head.</p>
<h3 id="everything-composes-from-a-shared-library">Everything composes from a shared library</h3>
<p>The single most useful thing I did was pull the repeated parts into a <code>utils</code> namespace and
then never write them again. A deploy is a serial composition of references:</p>
<div class="highlight"><pre tabindex="0" style="color:#d6cbb4;background-color:#252b2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#7a8478">verb</span>: deploy
</span></span><span style="display:flex;"><span>  <span style="color:#7a8478">name</span>: jellyfin
</span></span><span style="display:flex;"><span>  <span style="color:#7a8478">tags</span>: [media]
</span></span><span style="display:flex;"><span>  <span style="color:#7a8478">description</span>: Deploy the Jellyfin media server to Kubernetes using homelab chart
</span></span><span style="display:flex;"><span>  <span style="color:#7a8478">serial</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#7a8478">failFast</span>: <span style="color:#e67e80">true</span>
</span></span><span style="display:flex;"><span>    <span style="color:#7a8478">dir</span>: //apps/media/jellyfin
</span></span><span style="display:flex;"><span>    <span style="color:#7a8478">execs</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#7a8478">ref</span>: install utils:helm-base
</span></span><span style="display:flex;"><span>        <span style="color:#7a8478">args</span>: [jellyfin, jellyfin]
</span></span><span style="display:flex;"><span>      - <span style="color:#7a8478">ref</span>: verify utils:deployment
</span></span><span style="display:flex;"><span>        <span style="color:#7a8478">args</span>: [jellyfin, jellyfin]
</span></span></code></pre></div><p>Every app looks like that. Adding a new one is a values file, a chart reference, and about six
lines of flow. The namespace creation, the repo add, the <code>helm upgrade --install</code>, the rollout
wait, the verification. All of it lives in <code>utils</code> and is written once.</p>
<h3 id="secrets-come-from-the-vault-not-the-repo">Secrets come from the vault, not the repo</h3>
<p>Credentials are declared as parameters and resolved at run time. Nothing is committed, and
nothing sits in my shell history:</p>
<div class="highlight"><pre tabindex="0" style="color:#d6cbb4;background-color:#252b2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#7a8478">params</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#7a8478">secretRef</span>: bring-username
</span></span><span style="display:flex;"><span>    <span style="color:#7a8478">envKey</span>: BRING_USERNAME
</span></span><span style="display:flex;"><span>  - <span style="color:#7a8478">envKey</span>: ADDITIONAL_ARGS
</span></span><span style="display:flex;"><span>    <span style="color:#7a8478">text</span>: |<span style="color:#b2c98f">
</span></span></span><span style="display:flex;"><span><span style="color:#b2c98f">      --set controllers.main.containers.bring-api.env.BRING_USERNAME=$BRING_USERNAME</span>
</span></span></code></pre></div><p>A shared <code>create utils:secret</code> executable turns those into Kubernetes secrets during the deploy.
There&rsquo;s no sealed-secrets controller, no SOPS, no external secrets operator. For a single
operator, flow&rsquo;s vault is the whole secret management story.</p>
<h3 id="aggregates-for-the-things-i-do-together">Aggregates for the things I do together</h3>
<p>I rarely want to deploy one media app. <code>flow deploy media-stack</code> runs the six of them in order
and then prints the URLs; <code>flow verify media-stack</code> checks all six in parallel. The aggregate is
just another executable that references the others.</p>
<h3 id="operations-not-just-deploys">Operations, not just deploys</h3>
<p>The half of the workspace I didn&rsquo;t expect to write is the diagnostic half: <code>check health</code>,
<code>check issues</code>, <code>show overview</code>, <code>show inventory</code>, <code>debug pod</code>, <code>debug service</code>, and
<code>export diagnostics</code>. These exist because at 11pm I do not want to remember the right
<code>kubectl get</code> incantation across four namespaces. <code>flow check health</code> tells me whether anything
is wrong, and that&rsquo;s the whole point.</p>
<p>There&rsquo;s also a small <code>labs</code> namespace with httpbin and netshoot behind <code>test dns</code> / <code>test http</code>
/ <code>exec tcpdump</code> executables, for when something is broken in a way that needs poking at from
inside the cluster.</p>
<h3 id="templates-for-new-services">Templates for new services</h3>
<p>New apps get scaffolded from flow templates with a form that asks for the app name, namespace,
chart repo, and whether it needs ingress, secrets, or monitoring. It emits the values file and
the executable stubs. It&rsquo;s the difference between adding a service being a ten-minute job and a
this-weekend job.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
