howdoicomputer.lol/public/posts/homelab-1/index.html

230 lines
18 KiB
HTML
Raw Permalink Normal View History

2023-09-09 05:30:42 +00:00
<!DOCTYPE html>
<html lang="en">
2024-08-31 05:27:26 +00:00
<head><title>Homelab 1: Genesis &ndash; howdoicomputer</title>
2023-09-09 05:30:42 +00:00
<meta name="description" content="A dumping ground for ideas related to making, tomfoolery, and tomfoolery related to making">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" integrity="sha512-1sCRPdkRXhBV2PBLUdRb4tMg1w2YPf37qatUFeS7zlBy7jJI8Lf4VHwWfZZfpXtYSLy85pkm9GaYVYMfw5BC1A==" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/academicons/1.9.1/css/academicons.min.css" integrity="sha512-b1ASx0WHgVFL5ZQhTgiPWX+68KjS38Jk87jg7pe+qC7q9YkEtFq0z7xCglv7qGIs/68d3mAp+StfC8WKC5SSAg==" crossorigin="anonymous" />
<link rel="stylesheet" href="https://howdoicomputer.lol/css/palettes/tokyo-night-dark.css">
<link rel="stylesheet" href="https://howdoicomputer.lol/css/risotto.css">
<link rel="stylesheet" href="https://howdoicomputer.lol/css/custom.css">
</head>
<body>
<div class="page">
<header class="page__header"><nav class="page__nav main-nav">
<ul>
<h1 class="page__logo"><a href="https://howdoicomputer.lol/" class="page__logo-inner">howdoicomputer</a></h1>
<li class="main-nav__item"><a class="nav-main-item" href="https://howdoicomputer.lol/about" title="">About</a></li>
<li class="main-nav__item"><a class="nav-main-item active" href="https://howdoicomputer.lol/posts/" title="Posts">Posts</a></li>
</ul>
</nav>
</header>
<section class="page__body">
<header class="content__header">
2024-08-31 05:27:26 +00:00
<h1>Homelab 1: Genesis</h1>
2023-09-09 05:30:42 +00:00
</header>
<div class="content__body">
2024-08-31 05:27:26 +00:00
<p>This blog. The one that you are currently reading right now. Is running on a metal box that is just barely large enough to fit the average house cat. It cost ~$800 USD to build and has been christened Megamind. The HTTP request that you initiated when you visited <a href="https://howdoicomputer.lol">https://howdoicomputer.lol</a> has returned digital bits from hardware that is more than likely a couple feet from where I&rsquo;m sitting. Welcome!</p>
2023-09-09 05:30:42 +00:00
<h3 id="yeah-but-why">yeah, but why</h3>
<ul>
<li>I have a plethora of software projects that I&rsquo;ve written that need a home. Discord bots, daemons, websites, etc.</li>
<li>I needed a place to host a blog. Hi!</li>
<li>I want to replace the myriad online software services that I&rsquo;m subscribed to. Spotify, Netflix, etc.</li>
<li>I want an experimentation platform that I could use to learn new technologies or try new ideas.</li>
</ul>
<p>I wanted to build a self-hosted platform with logging, metric collection, service discovery, orchestration, etc; <a href="https://fly.io/">fly.io</a> in a box, if you will.</p>
<p>Also, I love making things. Making things is fun.</p>
<h3 id="okay-but-how">okay, but how</h3>
<p><img src="/homelab.jpg" alt="homelab"></p>
<p>If you go on the /r/homelab subreddit and sort by the most popular posts then you&rsquo;ll see setups that involve quite a bit more hardware than what my homelab currently sports. I don&rsquo;t have a full metal rack with multiple blades and switches. There are no neatly braided corridors of ethernet cabling. My homelab is a box that is filled with consumer grade hardware that sprouts a single cable that snakes to my off-the-shelf, eight year old consumer router.</p>
<p>Currently, that box is outfitted with:</p>
<ul>
<li>Ryzen 5600X</li>
<li>64 GB of non-ECC memory</li>
<li>Intel Arc GPU</li>
<li>Two WD Red 12TB drives</li>
</ul>
<p>The hardware isn&rsquo;t the interesting part, however. The interesting part is what runs <em>inside</em> the computer. It&rsquo;s essentially a Platform as a Service (PaaS) solution in a box and I love it.</p>
<h3 id="nomad-and-nix-and-zfs-oh-my">nomad and nix and zfs oh my</h3>
<p>Here are some features of my homelab:</p>
<ul>
<li>Nomad is the container orchestrator</li>
<li>A ZFS mirrored pool for data redundancy</li>
<li>Consul exists as a service mesh</li>
<li>Vault exists for secret storage</li>
<li>Traefik is for ingress</li>
<li>Prometheus for monitoring and Grafana for dashboards</li>
<li>The operating system is NixOS and I use my laptop to do flake based deployments to the underlying OS</li>
</ul>
<p>A secret that I&rsquo;ve withheld from you so far is that Megamind isn&rsquo;t my first homelab. A previous homelab that I built was a k3s cluster running on top of Raspbery Pis. It was quaint but got decommissioned when I moved apartments. I never set it up again and it currently lies in pieces in a drawer somewhere.</p>
2024-08-31 05:27:26 +00:00
<p>So why Nomad? Mostly because, at the time, I was leading an infrastructure initiative at my day job to use Nomad to orchestrate applications that are deployed to heterogenous IoT devices spread across distinct geographic regions. Nomad was a better fit than k8s for that specific use case because it was lighter-weight, easier to use, had less overhead (which was important because embedded devices don&rsquo;t have a lot of resources), and could run non-containerized applications that needed deep access to hardware. And so I wanted to dog food my own proposal. Also, Nomad is <em>a lot</em> simpler to use than Kubernetes. Nomad starts as <em>just</em> an orchestrator but gives you the option to introduce complexity later on through Vault and Consul. Every concept is almost immediately grokable and it has just been a pleasure to work with.</p>
2023-09-09 05:30:42 +00:00
<h3 id="whats-runnin">what&rsquo;s runnin</h3>
<p>Here is what is running so far:</p>
<ul>
<li>Jellyfin (movies, TV shows, etc)</li>
<li>Gitea (Git server and Docker registry)</li>
<li>Factorio server</li>
<li>FoundryVTT</li>
<li>Dufs (a UI for uploading files to the server)</li>
<li>Calibre Web (my library of ebooks)</li>
<li>Navidrome (music server)</li>
<li>Grafana and Prometheus</li>
<li>A Discord bot for looking up books</li>
<li>An Elixir/Phoenix application that I&rsquo;m working on</li>
</ul>
<h3 id="internal-paas">internal paas</h3>
<p>I write code. I like writing code. Sometimes that code becomes semi-functional pieces of software that I need to deploy. Previously, I used <a href="fly.io">fly.io</a> to host applications but have now moved those applications to my homelab.</p>
<p>Here is how they are developed and deployed:</p>
<ul>
<li>Each application has a <code>ci/</code> directory that contains a <a href="https://dagger.io/">Dagger</a> pipeline for testing the application and building a docker image. This is local for now.</li>
<li>The docker image is uploaded to <code>git.howdoicomputer.lol</code>. What is behind that domain is a Gitea instance that serves as a git host and a docker registry.</li>
<li>That application also has a <code>deploy/</code> directory that contains a <code>job.nomad</code> file. That Nomad job definition specifies the docker image that exists in Gitea and is used for the job allocation.</li>
<li>If the application has a <code>/metrics</code> endpoint, then Prometheus will be updated to scrape that endpoint and collect those metrics. This is powered by Consul.</li>
<li>If the application needs secrets then they are fetched from Vault.</li>
<li>Traefik and Consul Registry tags are used to define the ingress for the application. Most services are behind a subdomain on the <code>howdoicomputer.lol</code> domain and Traefik is what maps those subdomains to running services. If the service is not ready for production, then an IP whitelist is used to make sure that only ingress from my Tailscale VPN is allowed to access the site.</li>
<li>Logs are displayed through the Nomad web dashboard.</li>
<li>Traefik manages Let&rsquo;s Encrypt SSL certs through the DNS challenge method.</li>
</ul>
<p>This blog is developed similarily. It&rsquo;s <a href="https://gohugo.io/">Hugo</a> based so posts are markdown files that get converted into HTML files. A Dagger pipeline executes Hugo to get those files and then builds the container image - which runs Nginx - and then uploads that image to Gitea. There is a job definition in the blog&rsquo;s repo that deploys that application to Nomad.</p>
<p><img src="/blog_nomad_job.png" alt="blog_nomad_job"></p>
<p>Here is the job file for the blog:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-hcl" data-lang="hcl"><span style="display:flex;"><span><span style="color:#66d9ef">job</span> <span style="color:#e6db74">&#34;blog&#34;</span> {
</span></span><span style="display:flex;"><span> type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;service&#34;</span>
</span></span><span style="display:flex;"><span> datacenters <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;dc1&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">group</span> <span style="color:#e6db74">&#34;blog&#34;</span> {
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">network</span> {
</span></span><span style="display:flex;"><span> mode <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;bridge&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">port</span> <span style="color:#e6db74">&#34;http&#34;</span> {
</span></span><span style="display:flex;"><span> to <span style="color:#f92672">=</span> <span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">service</span> {
</span></span><span style="display:flex;"><span> name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;blog&#34;</span>
</span></span><span style="display:flex;"><span> port <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> tags <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span> &#34;traefik.enable<span style="color:#f92672">=</span><span style="color:#66d9ef">true</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-https.tls<span style="color:#f92672">=</span><span style="color:#66d9ef">true</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
2024-08-31 05:27:26 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-https.rule<span style="color:#f92672">=</span><span style="color:#66d9ef">Host</span>(<span style="color:#960050;background-color:#1e0010">`</span><span style="color:#66d9ef">howdoicomputer</span>.<span style="color:#66d9ef">lol</span><span style="color:#960050;background-color:#1e0010">`</span>)<span style="color:#960050;background-color:#1e0010">&#34;</span>,
2023-09-09 05:30:42 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-https.tls.certresolver<span style="color:#f92672">=</span><span style="color:#66d9ef">resolver</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
2024-08-31 05:27:26 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-https.tls.domains[0].main<span style="color:#f92672">=</span><span style="color:#66d9ef">howdoicomputer</span>.<span style="color:#66d9ef">lol</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
2023-09-09 05:30:42 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-https.entrypoints<span style="color:#f92672">=</span><span style="color:#66d9ef">websecure</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-http.entrypoints<span style="color:#f92672">=</span><span style="color:#66d9ef">web</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
2024-08-31 05:27:26 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-http.rule<span style="color:#f92672">=</span><span style="color:#66d9ef">Host</span>(<span style="color:#960050;background-color:#1e0010">`</span><span style="color:#66d9ef">howdoicomputer</span>.<span style="color:#66d9ef">lol</span><span style="color:#960050;background-color:#1e0010">`</span>)<span style="color:#960050;background-color:#1e0010">&#34;</span>,
2023-09-09 05:30:42 +00:00
</span></span><span style="display:flex;"><span> &#34;traefik.http.routers.blog-http.middlewares<span style="color:#f92672">=</span><span style="color:#66d9ef">redirecthttps</span><span style="color:#960050;background-color:#1e0010">&#34;</span>,
</span></span><span style="display:flex;"><span> &#34;traefik.http.middlewares.redirecthttps.redirectscheme.scheme<span style="color:#f92672">=</span><span style="color:#66d9ef">https</span><span style="color:#960050;background-color:#1e0010">&#34;</span>
</span></span><span style="display:flex;"><span> ]
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">task</span> <span style="color:#e6db74">&#34;blog&#34;</span> {
</span></span><span style="display:flex;"><span> driver <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;docker&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">config</span> {
</span></span><span style="display:flex;"><span> image <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;git.howdoicomputer.lol/howdoicomputer/blog:2&#34;</span>
</span></span><span style="display:flex;"><span> ports <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;http&#34;</span>]
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">resources</span> {
</span></span><span style="display:flex;"><span> cpu <span style="color:#f92672">=</span> <span style="color:#ae81ff">500</span>
</span></span><span style="display:flex;"><span> memory <span style="color:#f92672">=</span> <span style="color:#ae81ff">200</span>
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="nix">nix</h3>
<p>The OS is configured remotely using <a href="https://github.com/serokell/deploy-rs">deploy-rs</a> - a Rust based CLI that allows you to apply a Nix flake to a specific host. This is what I&rsquo;ve replaced Ansible with. Nix is&hellip; okay. I&rsquo;ll review Nix later but one cool feature to note here is that deploy-rs will apply a Nix configuration and if the SSH connection is broken then the previous Nix state would be rolled back to on the host.</p>
<p>What Nix currently owns:</p>
<ul>
<li>The installation of Nomad, Consul, Vault and other packages on the host.</li>
<li>The creation of the HashiStack configuration files.</li>
<li>The ZFS pool.</li>
<li>Firewall rules.</li>
<li>User creation.</li>
<li>Kernel parameters.</li>
</ul>
<p>I do really like the immutability of Nix. Something I want to explore down the line is either <a href="https://nixos.wiki/wiki/Impermanence">impermanence</a> or baking an OS image and continuously reimagining the homelab server through PXE.</p>
<h3 id="the-future">the future</h3>
<p>The future is bright! It has been incredibly fluid to roll out new services to the server. There are two additional features that I want: a CI/CD solution and an auth model for friends who want to use services.</p>
<p>For CI/CD, I&rsquo;ll most likely go with <a href="https://www.drone.io/">Drone</a>. Really, I just want a UI for Dagger pipelines. For an auth model, eh, I am not sure. LDAP? There is also the possiblity of using Oauth2 and whitelisting accounts.</p>
2024-08-31 05:27:26 +00:00
<p>For now though, my homelab is now an integral part of my life. For consumption, I use it to store a digital library of books, music, and movies. For productivity, the homelab is a cornerstone of developing applications that I want to expose to the public internet. It&rsquo;s&hellip; neat.</p>
<p><a href="https://howdoicomputer.lol/posts/homelab-2/" title="Part 2">Part 2</a></p>
2023-09-09 05:30:42 +00:00
</div>
<footer class="content__footer"></footer>
</section>
<section class="page__aside">
<div class="aside__about">
<div class="aside__about">
2024-08-31 05:27:26 +00:00
<img class="about__logo" src="https://howdoicomputer.lol/favicon.ico" alt="Logo">
2023-09-09 05:30:42 +00:00
<h1 class="about__title">howdoicomputer&#39;s blog</h1>
<p class="about__description">A dumping ground for ideas related to making, tomfoolery, and tomfoolery related to making</p>
</div>
<ul class="aside__social-links">
</ul>
</div>
<hr>
<div class="aside__content">
<p>
2023-08-27
</p>
</div>
</section>
<footer class="page__footer"><p>
</p>
<br /><br />
<p class="copyright"></p>
<p class="advertisement">Powered by <a href="https://gohugo.io/">hugo</a> and <a href="https://github.com/joeroe/risotto">risotto</a>.</p>
</footer>
</div>
</body>
</html>