<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Kubernetes on inherent site</title>
		<link>https://inherently.xyz/tags/kubernetes/</link>
		<description>Recent content in Kubernetes on inherent site</description>
		<generator>Hugo</generator>
		<language>en-us</language>
			<lastBuildDate>Sun, 04 May 2025 18:26:25 +0300</lastBuildDate>
			<atom:link href="https://inherently.xyz/tags/kubernetes/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Remote Access Homelab</title>
				<link>https://inherently.xyz/blog/remote-access-homelab/</link>
				<pubDate>Sun, 04 May 2025 18:26:25 +0300</pubDate>
				<guid>https://inherently.xyz/blog/remote-access-homelab/</guid>
				<description>&lt;p&gt;One of the remaining things for my homelab to have is remote access.&#xA;I set up a couple options and faced some issues during the process which I want to document here.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tailscale&#34;&gt;Tailscale&lt;/h2&gt;&#xA;&lt;p&gt;Tailscale is wireguard-based VPN solution.&#xA;Its main idea is that you run it alongside whatever you want to be accessible in your tailscale virtual network and then you can get to it.&#xA;My primary concern was replacing something like openvpn where it can be set up so it&amp;rsquo;s almost like being connected to the local network.&#xA;In tailscale this can be achieved by making it announce that it can route to a specific subnet.&#xA;This way things like local DNS works normally (for example I can access &lt;code&gt;opnsense.home.inherently.xyz&lt;/code&gt;and see the web interface of my router).&#xA;Additionally, you can make your traffic be routed through a specific device.&#xA;This might be the router at home which will be marked as an exit node and then in the mobile app select it to be used as such.&#xA;The choice of tailscale dates back to when I was still running pfSense.&#xA;In pfSense there has been a built-in integration for quite a while that can work as an exit node and subnet router.&#xA;In OPNSense it used to require a very manual install and setup process through the FreeBSD ports system but now there is a plugin which is a lot more user-friendly.&#xA;I set it up that way and then joined my phone and my tablet to the tailnet which means I can access all of my servers remotely.&#xA;Problem solved, let&amp;rsquo;s go home, roll the outro.&#xA;Not yet.&#xA;The thing is that while this works fine for just myself, if I want someone to check out some new selfhosted service I have or connect to a database I&amp;rsquo;m hosting I don&amp;rsquo;t want them to have to set up tailscale first.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cloudflare-tunnel&#34;&gt;Cloudflare Tunnel&lt;/h2&gt;&#xA;&lt;p&gt;To address that need, I chose Cloudflare Tunnel.&#xA;This works a bit differently than Tailscale, you run cloudflared and tell it where traffic for a domain name should be redirected.&#xA;In my case it runs inside kubernetes and points to the ingress controller.&#xA;This&amp;hellip; took a while for me to get working.&#xA;It was mostly my own fault and lack of knowledge of how cloudflare works.&#xA;There are certificates that cloudflare generates which encrypt traffic between clients and cloudflare.&#xA;This process is done automatically and only for the root domain, for any subdomains you better get your wallet out.&#xA;This meant that since I was trying to access services that were something like &lt;code&gt;service.home.inherently.xyz&lt;/code&gt;, TLS was broken.&#xA;Took about 2 days to figure this out and I only managed it thanks to Kryptonian in the Home Operationsdiscord server.&#xA;The way I fixed the TLS problem was by just putting everything under the root domain which then made it work.&#xA;There is a bit more work to do because I think &lt;a href=&#34;https://github.com/onedr0p/cluster-template&#34;&gt;cluster-template&lt;/a&gt; does have a good idea with separating services that should be externally accessible by running two ingress controllers.&#xA;However, at this point it gets the job done so I&amp;rsquo;m reasonably happy with it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Access do be external.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Talos Linux Setup and Configuration</title>
				<link>https://inherently.xyz/blog/talos-linux-setup-and-configuration/</link>
				<pubDate>Tue, 11 Mar 2025 19:28:45 +0200</pubDate>
				<guid>https://inherently.xyz/blog/talos-linux-setup-and-configuration/</guid>
				<description>&lt;p&gt;After about two weeks since the first time I installed Talos, I think I&amp;rsquo;ve figured out a good setup.&#xA;In the previous post I went over the PXE setup more than the kubernetes part of it so now I&amp;rsquo;ll cover the other half.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-the-talos-configuration-works&#34;&gt;How the Talos configuration works&lt;/h2&gt;&#xA;&lt;p&gt;Following &lt;a href=&#34;https://www.talos.dev/v1.9/introduction/getting-started/&#34;&gt;the getting started guide&lt;/a&gt; tells us that to generate the configuration files we need to run something like &lt;code&gt;talosctl gen config homecluster https://10.0.50.69:6443&lt;/code&gt;.&#xA;This command will generate 3 files. These are &lt;code&gt;controlplane.yaml&lt;/code&gt;, &lt;code&gt;worker.yaml&lt;/code&gt; and &lt;code&gt;talosconfig&lt;/code&gt;.&#xA;The control-plane nodes will use the first file, the worker nodes will use the second file and the third one should be placed into &lt;code&gt;~/.talos/config&lt;/code&gt; (with an edit to specify the node IP addresses or as Talos calls them in this case, endpoints).&#xA;If we run the command we&amp;rsquo;ll get some output like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;generating PKI and tokens&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;created controlplane.yaml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;created worker.yaml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;created talosconfig&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;Then, if we try to re-run the same command we will get a message like the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;generating PKI and tokens&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;file &amp;#34;/home/angle/talos/controlplane.yaml&amp;#34; already exists, use --force to overwrite&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;If we do the &amp;ldquo;just go away and do it anyway&amp;rdquo; thing that it says and add &lt;code&gt;--force&lt;/code&gt; it will again show the previous output.&#xA;In this process, we&amp;rsquo;ve wiped all the secret tokens and certificates it generated before and cannot recover them.&#xA;For a first-time installation this is barely an inconvenience, we probably do not care.&#xA;When doing this for an existing cluster, we will also need to get a new kubeconfig since the secrets that are re-generated are also relevant for the certificate that is stored in the kubeconfig to access the cluster.&#xA;That&amp;rsquo;s one of the reasons that if you&amp;rsquo;ve had the cluster running for a couple months, this might be a bit more annoying.&lt;/p&gt;&#xA;&lt;h2 id=&#34;separate-secrets&#34;&gt;Separate secrets&lt;/h2&gt;&#xA;&lt;p&gt;The alternative is to take a more in-depth look at the documentation which will land us on a page with notes for production-level setups, specifically the section about &lt;a href=&#34;https://www.talos.dev/v1.9/introduction/prodnotes/#separating-out-secrets&#34;&gt;separating out secrets&lt;/a&gt;.&#xA;Following the examples in that page we can run something like &lt;code&gt;talosctl gen secrets -o secrets.yaml&lt;/code&gt; first and then &lt;code&gt;talosctl gen config --with-secrets secrets.yaml homecluster https://10.0.50.69:6443&lt;/code&gt;.&#xA;This way, whenever we run the command to generate the configuration files (&lt;code&gt;controlplane.yaml&lt;/code&gt;, &lt;code&gt;worker.yaml&lt;/code&gt;, &lt;code&gt;talosconfig&lt;/code&gt;) we will not also wipe the secrets.&#xA;Now, why is that process useful or even preferable?&lt;/p&gt;&#xA;&lt;p&gt;Using this approach, the secrets can be stored separately from the configuration itself, that&amp;rsquo;s the obvious part.&#xA;The less obvious part is that given the same &lt;code&gt;talosctl&lt;/code&gt;, the CLI tool, we can generate the same 3 files.&#xA;Additionally, the kubeconfig that we can receive by running &lt;code&gt;talosctl kubeconfig ~/.config/kube/config --nodes 10.0.50.72 --endpoints 10.0.50.72&lt;/code&gt; is not going to need to be updated even if we reinstall Talos.&#xA;You might then think, if we continually re-generate these 3 files, how can we ever permanently store configuration changes?&#xA;Putting them directly in &lt;code&gt;controlplane.yaml&lt;/code&gt; and &lt;code&gt;worker.yaml&lt;/code&gt; is a no-go since they&amp;rsquo;ll be overwritten by a &lt;code&gt;talosctl gen config&lt;/code&gt; command.&#xA;That&amp;rsquo;s where patches come in.&lt;/p&gt;&#xA;&lt;h2 id=&#34;patches&#34;&gt;Patches&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;code&gt;talosctl&lt;/code&gt; CLI tool has a couple helpful options for applying patches when generating configuration.&#xA;Similar to having one configuration file for control-plane nodes and one for workers, the CLI flags are the same way.&#xA;There are 3 flags: &lt;code&gt;--config-patch-control-plane&lt;/code&gt; which applies the patch only to control-plane nodes, &lt;code&gt;--config-patch-worker&lt;/code&gt; which applies the patch only to worker nodes and &lt;code&gt;--config-patch&lt;/code&gt; which applies it to both.&#xA;Using these, we can write patches and apply them as we wish to any and all of the nodes in our cluster.&#xA;All 3 of the flags accept either inline JSON patches or YAML files depending on the notation.&#xA;Now I&amp;rsquo;ll switch gears a bit and discuss my own specific setup as an example.&#xA;I have 3 patches at the moment.&#xA;First, is a baseline that configures network interfaces, defines the installation disk, sets up NTP, adds kernel parameters, enables workload scheduling on the control-plane nodes and certificate rotation for the kubelet.&#xA;The other two are specific for the openebs storage system and for the metallb bare-metal loadbalancer.&#xA;It&amp;rsquo;s important to note at this point that it merges the changes.&#xA;So if you want to remove something from the default configuration (such as the &lt;code&gt;node.kubernetes.io/exclude-from-external-load-balancers: &amp;quot;&amp;quot;&lt;/code&gt; node label) it&amp;rsquo;s not as easy as just having the key specified but being empty (for example &lt;code&gt;nodeLabels: {}&lt;/code&gt;).&#xA;To generate my configuration, I can run the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;talosctl gen config homecluster https://10.0.50.69:6443 &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--with-examples&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--with-docs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--with-secrets&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;secrets.yaml &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--config-patch&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;@patches/01_baseline-changes-patch.yaml &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--config-patch&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;@patches/02_openebs-mayastor-patch.yaml &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--config-patch&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;@patches/03_metallb-patch.yaml &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;--endpoints&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;10.0.50.71,10.0.50.72,10.0.50.73&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;Here I&amp;rsquo;ve disabled documentation and examples just so the file isn&amp;rsquo;t as cluttered.&#xA;The important part though is that the sensitive information is only stored in only one file which could be encrypted and put into version control.&#xA;From there, I could use the same version of the CLI tool to generate the final configuration file.&#xA;The goal is to be able to have some sort of GitOPS setup where all or most of what&amp;rsquo;s needed to create the Talos configuration is stored in the same &lt;a href=&#34;https://gitlab.com/insanitywholesale/infra&#34;&gt;infra repository&lt;/a&gt; as everything else.&#xA;One tool that seems to fit this exact use-case is &lt;a href=&#34;https://github.com/budimanjojo/talhelper&#34;&gt;talhelper&lt;/a&gt; but I&amp;rsquo;ve not looked into it yet.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I keep finding cool stuff about Talos and the homelab tinkering will continue until morale improves.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>PXE setup for Talos Linux with Matchbox</title>
				<link>https://inherently.xyz/blog/pxe-setup-for-talos-using-matchbox/</link>
				<pubDate>Sat, 01 Mar 2025 19:00:33 +0200</pubDate>
				<guid>https://inherently.xyz/blog/pxe-setup-for-talos-using-matchbox/</guid>
				<description>&lt;p&gt;Join my campaign of hate against installing operating systems interactively.&#xA;I usually wipe my homelab virtualization hosts every week or two.&#xA;This might sound insane but I&amp;rsquo;ve been working on automating their setup.&#xA;As explained in the previous post, friendship ended with ProxMox and kubernetes will take its place.&#xA;Specifically Talos Linux, a linux distro you can&amp;rsquo;t even SSH into.&#xA;ProxMox kind of notoriously doesn&amp;rsquo;t have a way to be sanely installed through PXE but Talos is kind of made for it.&#xA;However, PXE (and iPXE, we&amp;rsquo;ll discuss this later) is not perfectly documented and can be even harder to debug.&#xA;So in this post I&amp;rsquo;ll document what worked for me and talk about some pretty helpful resources.&lt;/p&gt;&#xA;&lt;h2 id=&#34;plan&#34;&gt;Plan&lt;/h2&gt;&#xA;&lt;h3 id=&#34;pxe&#34;&gt;PXE&lt;/h3&gt;&#xA;&lt;p&gt;So let&amp;rsquo;s start with a bit of background, then lay out what I wanted to achieve, why and what I considered &amp;ldquo;good enough&amp;rdquo;.&#xA;First off, PXE.&#xA;It stands for pre-boot execution environment and is mostly reliant on motherboards and network cards to be implemented on the client side.&#xA;It&amp;rsquo;s a stripped down environment before the computer is booted into an operating system.&#xA;Inside it, there are standards for getting information about what to execute, where to get it and what configuration to use.&#xA;PXE is the name of the general concept and the first version of the technology.&#xA;It allows booting a computer from the network by loading files from a TFTP server.&#xA;Later on, &lt;a href=&#34;https://ipxe.org/&#34;&gt;iPXE&lt;/a&gt; came around to fix some of its limitations.&#xA;One thing it&amp;rsquo;s useful for having a computer and being able to boot it from the network and install an operating system on it without having to have a USB stick on you.&#xA;With something like &lt;a href=&#34;https://syslinux.org/&#34;&gt;syslinux&lt;/a&gt; you can even create menus to be able to choose what to install and have a bunch of different options with different settings.&#xA;As computer installations grow larger, it&amp;rsquo;s easy to see how this becomes kind of essential as you can&amp;rsquo;t run around multiple datacenters any time something needs to be re-imaged.&#xA;A counter-point to that could be that servers have remote management features allowing us to load ISOs as if they&amp;rsquo;re DVDs but even then, iPXE has an advantage because you can fully automate the process.&#xA;Also my poor version of servers (read: used office PCs) do not have IPMI.&#xA;At any rate, that&amp;rsquo;s the general idea of PXE.&lt;/p&gt;&#xA;&lt;h3 id=&#34;talos&#34;&gt;Talos&lt;/h3&gt;&#xA;&lt;p&gt;How does that apply to my case then?&#xA;I want to be able to completely wipe all three systems and then effortlessly restore them.&#xA;As I plan to run kubernetes on it, the installation of applications to the cluster is taken care of using &lt;a href=&#34;https://fluxcd.io/&#34;&gt;FluxCD&lt;/a&gt; so I only really need to solve the installation part.&#xA;That&amp;rsquo;s where &lt;a href=&#34;https://www.talos.dev/&#34;&gt;Talos&lt;/a&gt; comes in.&#xA;Talos is an incredibly minimal linux distribution that is designed with the sole purpose of running kubernetes.&#xA;No SSH, no TTY, no nothing.&#xA;Sitting in front of the system only allows you to change kernel boot parameters and the network configuration.&#xA;Everyhing is done using the API which is accessible interactively through the &lt;code&gt;talosctl&lt;/code&gt; CLI utility.&#xA;This means that we can have our operating system and kubernetes configuration as code for the price of one config file.&#xA;Sign me up!&lt;/p&gt;&#xA;&lt;h3 id=&#34;matchbox&#34;&gt;Matchbox&lt;/h3&gt;&#xA;&lt;p&gt;Those are the ingredients but it can hardly be called a meal.&#xA;We need to get some kitchen utensils in this analogy to get the desired result.&#xA;Our PXE setup will need to have a little bit of logic in it so it knows what to install with what configuration.&#xA;See, Talos can be told to fetch a configuration file from an HTTP server using a kernel parameter.&#xA;A conditionally-rendered file would allow us to alter the response depending on who&amp;rsquo;s requesting it.&#xA;This is where &lt;a href=&#34;https://matchbox.psdn.io/&#34;&gt;matchbox&lt;/a&gt; slots in.&#xA;When matchbox gets a request it can see some information about the host requesting it and therefore make a determination about what to reply with.&#xA;We can then serve different options according to which system is asking such as what Talos configuration file to use.&#xA;This way the control-plane kubernetes nodes can receive the Talos &lt;code&gt;controlplane.yaml&lt;/code&gt; while worker nodes get the &lt;code&gt;worker.yaml&lt;/code&gt;.&#xA;So a brand-new host with an empty disk drives would boot up, skip the disks since they don&amp;rsquo;t have an operating system and then try booting using PXE.&#xA;Then the host would get its configuration, install the operating system, install kubernetes and become part of a cluster.&lt;/p&gt;&#xA;&lt;h3 id=&#34;definition-of-done&#34;&gt;Definition of Done&lt;/h3&gt;&#xA;&lt;p&gt;The ideal process when getting adding a host should look like:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;note down the MAC address and corresponding IP somewhere&lt;/li&gt;&#xA;&lt;li&gt;plug in the cables&lt;/li&gt;&#xA;&lt;li&gt;configure the boot device order&lt;/li&gt;&#xA;&lt;li&gt;save settings and exit&lt;/li&gt;&#xA;&lt;li&gt;play minecraft while waiting&lt;/li&gt;&#xA;&lt;li&gt;run one or zero commands&lt;/li&gt;&#xA;&lt;li&gt;host shows up in &lt;code&gt;kubectl get nodes&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;recreating it from scratch should be just as easy&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t know if I can get exactly to that point but I&amp;rsquo;m willing to put in some effort into the setup so in the future I can avoid it to a greater extent.&#xA;Some compromise is acceptable since I don&amp;rsquo;t have any IPAM infrastructure in place already so this isn&amp;rsquo;t the full and proper way to go about it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;&#xA;&lt;h3 id=&#34;how-do-i-do-x-in-y-minutes&#34;&gt;How do I do X in Y minutes&lt;/h3&gt;&#xA;&lt;p&gt;Meat and potatoes first, for quick reference here is what I did (5-6 hours of suffering omitted for brevity):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Installed &lt;code&gt;tftp-hpa&lt;/code&gt; on Arch&lt;/li&gt;&#xA;&lt;li&gt;Downloaded &lt;a href=&#34;http://boot.ipxe.org/undionly.kpxe&#34;&gt;undionly.kpxe&lt;/a&gt; and &lt;a href=&#34;http://boot.ipxe.org/ipxe.efi&#34;&gt;ipxe.efi&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Put them in &lt;code&gt;/srv/tftp&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Created &lt;code&gt;matchbox.ipxe&lt;/code&gt; with the following contents:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!ipxe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chain http://10.0.20.50:8080/boot.ipxe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Installed &lt;code&gt;matchbox&lt;/code&gt; using Docker by running the following command:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;docker&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;run&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matchbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matchbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;etc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matchbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;etc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matchbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ro&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;poseidon&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matchbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;10.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8080&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;debug&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Downloaded &lt;a href=&#34;https://github.com/siderolabs/talos/releases/download/v1.9.4/vmlinuz-amd64&#34;&gt;vmlinuz-amd64&lt;/a&gt; and &lt;a href=&#34;https://github.com/siderolabs/talos/releases/download/v1.9.4/initramfs-amd64.xz&#34;&gt;initramfs-amd64.xz&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Put them in &lt;code&gt;/var/lib/matchbox/assets&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Download &lt;code&gt;talosctl&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Run &lt;code&gt;talosctl gen config homecluster https://10.0.50.69&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Edit &lt;code&gt;controlplane.yaml&lt;/code&gt; until it looks good&lt;/li&gt;&#xA;&lt;li&gt;Put &lt;code&gt;controlplane.yaml&lt;/code&gt; in &lt;code&gt;/var/lib/matchbox/assets&lt;/code&gt; as well&lt;/li&gt;&#xA;&lt;li&gt;Create &lt;code&gt;/var/lib/matchbox/profiles/control-plane.json&lt;/code&gt;:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;control-plane&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;control-plane&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;boot&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;kernel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/assets/vmlinuz&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;initrd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/assets/initramfs.xz&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;initrd=initramfs.xz&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;init_on_alloc=1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;slab_nomerge&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;pti=on&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;console=tty0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;printk.devkmsg=on&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;talos.platform=metal&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;talos.config=http://10.0.20.50:8080/assets/controlplane.yaml&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Create &lt;code&gt;/var/lib/matchbox/groups/control-plane.json&lt;/code&gt;:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;kube01&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;kube01&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;profile&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;control-plane&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;selector&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;mac&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;18:03:73:2a:d8:a2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;In &lt;a href=&#34;https://opnsense.home.inherently.xyz/services_dhcp.php?if=opt2&#34;&gt;OPNSense (link to my router)&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Under &lt;code&gt;DHCP Static Mappings for this interface.&lt;/code&gt; add the hosts&lt;/li&gt;&#xA;&lt;li&gt;Under &lt;code&gt;TFTP server&lt;/code&gt;:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Set TFTP hostname: 10.0.20.50&lt;/li&gt;&#xA;&lt;li&gt;Set Bootfile: undionly.kpxe&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Under &lt;code&gt;Network booting&lt;/code&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Set next-server IP: 10.0.20.50&lt;/li&gt;&#xA;&lt;li&gt;Set default bios filename: undionly.kpxe&lt;/li&gt;&#xA;&lt;li&gt;Set iPXE boot filename: matchbox.ipxe&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Boot Optiplex&lt;/li&gt;&#xA;&lt;li&gt;Wait&lt;/li&gt;&#xA;&lt;li&gt;Watch text scroll on screen&lt;/li&gt;&#xA;&lt;li&gt;???&lt;/li&gt;&#xA;&lt;li&gt;No profit, I spent my whole weekend on this&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;explanation&#34;&gt;Explanation&lt;/h3&gt;&#xA;&lt;p&gt;PXE is an under-documented part of the common network services one can set up.&#xA;An amusing yet educational thing I found was a redditor&amp;rsquo;s 3-part descent into madness and consequently enlightenment:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/homelab/comments/1ahhhkh/why_does_pxe_feel_like_a_horribly_documented_mess/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button&#34;&gt;part 1&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/homelab/comments/1b1qc05/a_followup_to_my_pxe_rant_standing_up_baremetal/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button&#34;&gt;part 2&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/homelab/comments/1b3wgvm/uefipxeagents_conclusion_to_my_pxe_rant_with_a/?utm_source=share&amp;amp;utm_medium=web3x&amp;amp;utm_name=web3xcss&amp;amp;utm_term=1&amp;amp;utm_content=share_button&#34;&gt;part 3&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The matchbox documentation was also very good at explaining both the general process and giving some specific recommendations:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://matchbox.psdn.io/network-booting/&#34;&gt;Network boot environments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://matchbox.psdn.io/network-setup/&#34;&gt;Network setup&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;With those out of the way I&amp;rsquo;ll make an attemt at explaining it myself.&#xA;When a PXE client starts, it does the DHCP dance which tells it where the TFTP server is and what the name of the file it should execute is.&#xA;That file is a network boot program which can optionally load some configuration (also stored on the TFTP server).&#xA;So after all of that is figured out, the PXE client will pull the kernel and initramfs, again from the TFTP server.&#xA;In contrast, iPXE uses scripts stored on the TFTP server instead of plain configuration files so we can do fancier things with it.&#xA;However, my old desktop PCs do not have iPXE so I had to use an in-between thingy, undionly.kpxe.&#xA;What that does is load iPXE firmware (ipxe.efi) so we can access the cool new features without having to replace any hardware.&#xA;When that loads, it talks to the DHCP server as an iPXE client this time and gets told to grab the matchbox.ipxe file from the TFTP server.&#xA;That file is an iPXE script which tells the client to check the matchbox server.&#xA;When matchbox gets the request, it checks the groups it has registered and if there are any matches according to the &lt;code&gt;selector&lt;/code&gt; field, it uses the corresponding profile.&#xA;In this case, the profile is for control-plane Talos Linux nodes.&#xA;The kernel and initramfs listed in the profile are used alongside some specific kernel parameters.&#xA;The most important parameter is &lt;code&gt;talos.config=http://10.0.20.50:8080/assets/controlplane.yaml&lt;/code&gt; which tells the machine that is booting the operating system to fetch the configuration file listed there.&#xA;Of course, you will need to have generated the configuration (using &lt;code&gt;talosctl gen config homecluster https://10.0.50.69:6443&lt;/code&gt;) and moved it in the matchbox &lt;code&gt;assets&lt;/code&gt; directory (or in another HTTP server, matchbox is just convenient in this setup).&#xA;That configuration has some basic things like which disk and network settings to use.&#xA;When the machine gets this configuration, it installs Talos and then waits.&#xA;At this point the system is booted normally, no PXE involved.&lt;/p&gt;&#xA;&lt;p&gt;Following that, all we need to do is run &lt;code&gt;talosctl bootstrap --nodes 10.0.50.71 --endpoints 10.0.50.71&lt;/code&gt; and we get a kubernetes cluster.&#xA;To get the kubeconfig required to access the cluster, run &lt;code&gt;talosctl kubeconfig my-talos-kubeconfig --nodes 10.0.50.71 --endpoints 10.0.50.71&lt;/code&gt; and then check that it works by running &lt;code&gt;kubectl --kubeconfig my-talos-kubeconfig get nodes&lt;/code&gt;.&#xA;I&amp;rsquo;ve tested the whole process end-to-end twice now to ensure that nodes with blank disks and correct boot order will behave correctly and it&amp;rsquo;s almost magic.&#xA;True enough, after pressing the power button on all three systems, making some coffee, and then running the commands mentioned previously, I got this output:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ kubectl get nodes -o wide&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;NAME     STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION   CONTAINER-RUNTIME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kube01   Ready    control-plane   3h20m   v1.32.2   10.0.50.71    &amp;lt;none&amp;gt;        Talos (v1.9.4)   6.12.13-talos    containerd://2.0.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kube02   Ready    control-plane   3h20m   v1.32.2   10.0.50.72    &amp;lt;none&amp;gt;        Talos (v1.9.4)   6.12.13-talos    containerd://2.0.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kube03   Ready    control-plane   3h20m   v1.32.2   10.0.50.73    &amp;lt;none&amp;gt;        Talos (v1.9.4)   6.12.13-talos    containerd://2.0.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;And I guess that&amp;rsquo;s it.&#xA;It needed some effort and research and the approach should be adjusted according to the network situation (the matchbox docs saved the day here).&#xA;In the end though, I really like what I got working and it was a fun way to spend the weekend.&#xA;I can go from basically brand new computer with nothing on it to full cluster with a high availability control-plane using patience and a single command.&#xA;Two commands and I can install fluxcd on the cluster which will install all my applications.&#xA;Looking back at the definition of done I set in the beginning, I consider this a success.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;As the proud owner of a Talos Linux kubernetes cluster installed in a fully automated way, I am quite happy.&#xA;I can get back into running services at home and live through the pain of using kubernetes daily again.&#xA;I have a couple of ideas in mind for how to use my new container running platform but that&amp;rsquo;s for another post.&#xA;Hopefully you got a better idea of what PXE is, how it works and how I used it in this instance.&#xA;If you weren&amp;rsquo;t familiar with any of this, maybe it&amp;rsquo;s time to get your hands dirty and prepare to throw away your USB drives.&#xA;Either way, that&amp;rsquo;s all for now.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Homelab 2025 Plans</title>
				<link>https://inherently.xyz/blog/homelab-2025-plans/</link>
				<pubDate>Fri, 28 Feb 2025 22:51:33 +0200</pubDate>
				<guid>https://inherently.xyz/blog/homelab-2025-plans/</guid>
				<description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;&#xA;&lt;p&gt;After recapping the state of my homelab and writing down how it was in the end of 2024, I think it&amp;rsquo;s time to look towards the future.&#xA;Having finally finished my thesis, I now have less constant stress to deal with and a bit more time than I&amp;rsquo;ve had in the last 2 and a half years.&#xA;The main goal of rebuilding my homelab is to make it an actual production environment.&#xA;This means that a few important problems need to be solved before it&amp;rsquo;s considered done.&#xA;Along with that, I&amp;rsquo;m willing to lose a bit of flexibility in exchange for having something that actually works which is a bit odd for me to write but alas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hardware&#34;&gt;Hardware&lt;/h2&gt;&#xA;&lt;p&gt;Over the past several years I&amp;rsquo;ve invested quite a bit into the hardware that already exists.&#xA;I won&amp;rsquo;t go into great depth about it, all the details are in the previous post.&#xA;My homelab is housed in a 27U rack, includes a managed switch, a DIY router, 3 virtualization hosts and at least one NAS.&#xA;That is more than enough to at least get started running several services.&#xA;I will try to avoid investing in hardware this year with two exceptions, a VGA KVM and a good NIC for the router.&#xA;Other than those two additions, I plan to focus on software choice and configuration.&lt;/p&gt;&#xA;&lt;h2 id=&#34;software&#34;&gt;Software&lt;/h2&gt;&#xA;&lt;h3 id=&#34;kubernetes&#34;&gt;Kubernetes&lt;/h3&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going bare metal kubernetes.&#xA;This might seem counter-intuitive but it&amp;rsquo;s actually the easiest thing to get working.&#xA;I still like ProxMox, I&amp;rsquo;m happy with the terraform provider for working with ProxMox and there is now a healthy alternative one, I use ansible at work and it&amp;rsquo;s all nice but I&amp;rsquo;m looking for an even higher level of automation.&#xA;The integrations available for kubernetes are at a great point and have been for a couple of years now.&#xA;I can forego dealing with issues such as &amp;ldquo;how do I make DNS automatically update when I start running a new service&amp;rdquo; and focus more on running and using my self-hosted services.&#xA;Of course, kubernetes presents its own set of challenges and has its own quirks but I believe the tradeoff to be worth it for me.&lt;/p&gt;&#xA;&lt;p&gt;The plan right now is to go with &lt;a href=&#34;https://www.talos.dev/&#34;&gt;Talos Linux&lt;/a&gt; so my hosts are nice and lean.&#xA;The entire process of installation can be automated using the &lt;a href=&#34;https://matchbox.psdn.io/&#34;&gt;matchbox PXE server&lt;/a&gt; and a bit of configuration and the operating system has just enough to run kubernetes and that&amp;rsquo;s it.&#xA;I could of course regret this in which case I&amp;rsquo;ll go back to Debian my beloved but it remains to be seen.&#xA;Initially I&amp;rsquo;ll go with a simple ISO installation to get started and then I&amp;rsquo;ll see if I want to take it a step further.&#xA;The kubernetes-related stuff is mostly figured out, default CNI, nginx for ingress, metallb for external IPs, flux to deploy stuff and I&amp;rsquo;ll try adding renovate bot to help with maintenance.&#xA;What remains is to decide if I&amp;rsquo;m going to go with openebs or longhorn for storage but that shouldn&amp;rsquo;t be too difficult or time-consuming.&lt;/p&gt;&#xA;&lt;h3 id=&#34;router&#34;&gt;Router&lt;/h3&gt;&#xA;&lt;p&gt;The other interesting software choice is the router.&#xA;Having a dedicated machine for it seems wasteful and I&amp;rsquo;m bound to running whatever software is available for FreeBSD.&#xA;No, I&amp;rsquo;m not planning on moving away from OPNSense at the moment but I do want to start the vicious cycle again.&#xA;The plan is to have it in a VM, thus the vicious cycle, and then be able to run things like matchbox on the same machine, a different NTP server, a different DHCP or PXE server (mainly &lt;a href=&#34;https://tinkerbell.org/&#34;&gt;tinkerbell&lt;/a&gt; comes to mind), different DNS server (&lt;a href=&#34;https://github.com/hickory-dns/hickory-dns&#34;&gt;Hickory&lt;/a&gt; seems quite interesting) and so on.&#xA;Those could be containers inside other VMs or whatever else, I&amp;rsquo;m not bound to whatever is packaged for FreeBSD or even specifically for OPNSense.&#xA;This of course requires a hypervisor (ProxMox makes a comeback) and a NIC that can be passed through to a virtual machine in order to run the router.&#xA;This is a secondary concern since I do have an old machine from the core2duo days if I just want to runs some basic network infrastructure like the ones mentioned previously for experimentation purposes.&#xA;VyOS has also been on my mind but that&amp;rsquo;s a bigger jump and would require quite a bit of effort to adapt everything I have to it.&#xA;The router plans are unclear at the moment so it&amp;rsquo;s more of a backburner project.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;One must imagine Sisyphus, he rolls the rock and I rebuild my homelab.&#xA;Was there a point to writing this? I&amp;rsquo;m not sure.&#xA;These are my plans at the moment so I can get back into the hobby.&#xA;If I do go through with them, I&amp;rsquo;ll try to document the experience when I have something workable.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>State of Homelab 2024</title>
				<link>https://inherently.xyz/blog/homelab-2024/</link>
				<pubDate>Mon, 27 Jan 2025 22:38:48 +0200</pubDate>
				<guid>https://inherently.xyz/blog/homelab-2024/</guid>
				<description>&lt;p&gt;When operating a homelab there is always something new to do or something waiting to be fixed.&#xA;This post&amp;rsquo;s aim is to detail the state of my homelab at the end of 2024 and beginning of 2025.&lt;/p&gt;&#xA;&lt;h2 id=&#34;router&#34;&gt;Router&lt;/h2&gt;&#xA;&lt;p&gt;The previous post was about virtualizing pfSense inside ProxMox but this setup is no longer in use.&#xA;In its place, there is a new system running OPNSense on bare-metal.&#xA;This was done for a few reasons, the main one being that I wanted to move away from pfSense.&#xA;More than that, there was a circular dependency where the ProxMox host had to be up in order for the router to function but in order for the cluster nodes to talk to each other, the router needed to be online.&#xA;In practice this was not a huge issue but it bothered me since it made experimenting more difficult because recreating the cluster meant taking down the router as well.&#xA;I&amp;rsquo;ve lost a few things, mainly pfblocker-ng and native tailscale integration but they&amp;rsquo;re not as big of a loss as I had anticipated.&#xA;In the end I think it was worth it, over the course of the past few years the company making pfSense has acted against the best interest of pfSense users and I did not feel like using their software anymore.&lt;/p&gt;&#xA;&lt;h2 id=&#34;virtualization&#34;&gt;Virtualization&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m still running ProxMox, although now it is a 3-node cluster.&#xA;I&amp;rsquo;ve spent a pretty significant amount of time tweaking the bootstrap process from a fresh install to having the entire homelab operational.&#xA;Somewhere along the line I tried making it so non-cluster operation of multiple hosts was supported but gave up on that eventually.&#xA;Each of the nodes has a 250GB SSD used as a boot drive and for node-local storage along with a 2TB HDD used as a Ceph OSD.&#xA;Since the last post about using ansible and terraform with ProxMox, I&amp;rsquo;ve figured out the process of adding tools to the debian image in the virtual machine template.&#xA;There is also the option to deploy using GitLab CI so just making committing and pushing to the repo is enough to create a new virtual machine.&#xA;The k3s virtual machine terraform configuration was improved significantly but I&amp;rsquo;ve not adopted modules yet which seems to be the next step for organization-related improvements.&#xA;I also run all software directly on top of debian virtual machines without containers to practice writing ansible.&#xA;At work, our team runs everything in Docker so it could be a good idea to start moving to something similar at home for the sake of practice.&lt;/p&gt;&#xA;&lt;h2 id=&#34;kubernetes&#34;&gt;Kubernetes&lt;/h2&gt;&#xA;&lt;p&gt;The kubernetes cluster got a significant update.&#xA;I&amp;rsquo;ve adopted FluxCD to a greater degree, figured out secrets storage and a pretty good structure for the YAML files.&#xA;The k3s cluster has 3 control plane nodes and 3 worker nodes, one per virtualization host.&#xA;I&amp;rsquo;m using longhorn for storage with plans to try and use the Ceph cluster as an additional storage class.&#xA;The networking setup consists of MetalLB to have an IP in the subnet and then run ingress-nginx as the ingress controller on that IP.&#xA;No plans for checking out Gateway API have been made at current but it is a good and necessary step forward in the ecosystem, I plan to move to it after things are a bit less in flux.&#xA;The DNS is manual right now due to the low amount of services but I&amp;rsquo;ve tested external-dns with PiHole and I&amp;rsquo;m aware of the OPNSense webhook option, it remains to be seen what I&amp;rsquo;ll end up using.&#xA;The setup needs a bit more tender love and care but it&amp;rsquo;s running well and doing what I need it to.&#xA;I have plans to move more stuff to the cluster after the foundation is solid and not just have my own demo applications in there.&#xA;The thought has crossed my mind to completely do away with ProxMox and then run Talos Linux bare metal on the systems but I&amp;rsquo;d be losing out on some flexibility which I don&amp;rsquo;t want to commit to right now.&#xA;All in all, kubernetes is still pretty fun and the 1.30 and later releases have made good quality of life improvements.&lt;/p&gt;&#xA;&lt;h2 id=&#34;nas&#34;&gt;NAS&lt;/h2&gt;&#xA;&lt;p&gt;Since I upgraded my desktop, the old one&amp;rsquo;s internals were transplanted to a different case are now a second NAS.&#xA;I&amp;rsquo;m saving up to get a big external drive so I can have an extra copy of the current main NAS so I can freely mess with them to have a solid backup solution.&#xA;The changes in TrueNAS Scale regarding applications has left me waiting for things to settle down before I commit to a final setup.&#xA;Overall nothing exciting on this front.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hardware&#34;&gt;Hardware&lt;/h2&gt;&#xA;&lt;p&gt;I run mostly used office desktops and a basic managed switch.&#xA;I have 3 Dell Optiplex machines: 2nd gen, 3rd gen and 4th gen Intel i5 CPUs with RAM sizes ranging from 16 to 32GB each.&#xA;For storage they have a 250GB SSD and a 2TB HDD as mentioned earlier.&#xA;The router is a Fujitsu equivalent desktop with a 4th gen Intel Pentium and 8GB of RAM as well as a 500GB SSD.&#xA;My rackmount NAS is an i5 4570 with 16GB of RAM and 4x4TB HDDs in a 3-drive ZFS RAID-Z1 plus one hot spare.&#xA;My backup NAS is an i7 4770 with 32GB of RAM and 2x8TB HDDs in a 2-way ZFS mirror.&#xA;The main network switch is a Netgear GS724TV4, just a layer 2 managed gigabit switch.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I wanted to write all of this down to have a reference for myself when I inevitably change something and it might help someone else as well.&#xA;Also the blog is back(?) after more than a 2 year silence, hopefully I will not neglect it for that long again.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Flux Update</title>
				<link>https://inherently.xyz/blog/flux-update/</link>
				<pubDate>Wed, 25 Aug 2021 00:44:34 +0300</pubDate>
				<guid>https://inherently.xyz/blog/flux-update/</guid>
				<description>&lt;p&gt;I wrote about my journey of choosing a continuous deployment tool and why I ultimately ended up using &lt;a href=&#34;https://toolkit.fluxcd.io/&#34;&gt;flux&lt;/a&gt; for my homelab &lt;a href=&#34;https://inherently.xyz/blog/fluxing-my-cluster/&#34;&gt;in this post&lt;/a&gt;.&#xA;It took quite a bit of reasearch and if you&amp;rsquo;re in a similar position as I was it might prove to be helpful.&lt;/p&gt;&#xA;&lt;h2 id=&#34;longish-term-experience&#34;&gt;Long(ish)-term experience&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve been using it for about 5 months now, the first post was written about one month of use.&#xA;At that point I had been tinkering with it and attempting to get all the stuff I wanted to be deployed by it.&#xA;Some things were simple, others not so straight-forward.&lt;/p&gt;&#xA;&lt;h3 id=&#34;successes&#34;&gt;Successes&lt;/h3&gt;&#xA;&lt;h4 id=&#34;deploying-raw-manifest-applications&#34;&gt;Deploying raw manifest applications&lt;/h4&gt;&#xA;&lt;p&gt;Deploying raw kubernetes manifests was really easy.&#xA;Since I&amp;rsquo;m somewhat on the fence about Helm, I prefer using normal kubernetes manifests where possible.&#xA;This meant that for my use case mostly everything was smooth sailing after figuring out how to generate a kustomization yaml using the command-line tool.&lt;/p&gt;&#xA;&lt;h4 id=&#34;command-line-tool&#34;&gt;Command-line tool&lt;/h4&gt;&#xA;&lt;p&gt;Speaking of that, flux has a command-line tool to interact with the controllers running inside the cluster.&#xA;It&amp;rsquo;s also the way you can initialize a repository to be used as the place for flux files to be stored.&#xA;It can also be used to install flux to the cluster if the repository already exists.&lt;/p&gt;&#xA;&lt;h4 id=&#34;upgrading&#34;&gt;Upgrading&lt;/h4&gt;&#xA;&lt;p&gt;When a new version of flux comes out, you can upgrade and it will carry over to the cluster.&#xA;It&amp;rsquo;s really easy, it just upgrades its own files so when those are committed it will pull in the new version of the controllers.&lt;/p&gt;&#xA;&lt;h3 id=&#34;trouble&#34;&gt;Trouble&lt;/h3&gt;&#xA;&lt;h4 id=&#34;aggregation-yaml&#34;&gt;Aggregation yaml&lt;/h4&gt;&#xA;&lt;p&gt;For starters here is a minor one that took way too long to diagnose.&#xA;I forget exactly what this is called but essentially it is a yaml file says run deal with the listed resources.&#xA;Imagine the following directory contents:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;drwxrwxr-x 4 angle angle 4,0K Αυγ  25 01:23 .&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;drwxrwxr-x 5 angle angle 4,0K Ιουλ 21 03:42 ..&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;drwxrwxr-x 2 angle angle 4,0K Αυγ  13 15:55 helmrepos&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-&lt;span class=&#34;l&#34;&gt;rw-rw-r-- 1 angle angle  219 Ιουλ 21 03:20 infra-source.yml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-&lt;span class=&#34;l&#34;&gt;rw-rw-r-- 1 angle angle  126 Αυγ  12 11:45 kustomization.yaml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;drwxrwxr-x 2 angle angle 4,0K Αυγ  13 15:56 storage&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;kustomization.yaml&lt;/code&gt; file is as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;apiVersion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;kustomize.config.k8s.io/v1beta1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Kustomization&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;infra-source.yml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;helmrepos&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;storage&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;So it&amp;rsquo;s a way to more easily include stuff.&#xA;The issue I had is that I named the file &lt;code&gt;kustomization.yml&lt;/code&gt; instead of &lt;code&gt;kustomization.yaml&lt;/code&gt; which for some reason isn&amp;rsquo;t supported.&#xA;I believe this is a bug and not intended behavior but it was still frustrating to find and fix.&lt;/p&gt;&#xA;&lt;h4 id=&#34;logs&#34;&gt;Logs&lt;/h4&gt;&#xA;&lt;p&gt;Now on to more substantial issues.&#xA;While troubleshooting I got a bit frustrated with how flux displays errors.&#xA;The messages are fairly non-descript and there isn&amp;rsquo;t a lot of guidance for how to fix them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Despite a couple rough edges, flux has been working incredibly well.&#xA;Even before I got it fully functioning, it was amazing to be able to just install it to a newly creted cluster and have all my applications running just like that.&#xA;It&amp;rsquo;s almost magical and I&amp;rsquo;ve been enjoying it quite a lot.&#xA;If you aren&amp;rsquo;t using a continuous deployment tool, feel free to give &lt;a href=&#34;https://toolkit.fluxcd.io/&#34;&gt;flux&lt;/a&gt; a try or read the previous post to learn about some other options&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Droning On</title>
				<link>https://inherently.xyz/blog/droning-on/</link>
				<pubDate>Sat, 01 May 2021 18:54:59 +0300</pubDate>
				<guid>https://inherently.xyz/blog/droning-on/</guid>
				<description>&lt;p&gt;I described previously how the deployment of applications is automated in my homelab but didn&amp;rsquo;t touch upon how I test my own code.&#xA;The topic came up when I started trying to simulate a development pipeline who&amp;rsquo;s first step after committing code is to be run through the continuous integration system.&#xA;What should that system be though?&#xA;In this post, I&amp;rsquo;ll take you through the things I tried first and then why I went with &lt;a href=&#34;https://www.drone.io/&#34;&gt;drone&lt;/a&gt; in the end.&lt;/p&gt;&#xA;&lt;h2 id=&#34;choose-a-fighter&#34;&gt;Choose a Fighter&lt;/h2&gt;&#xA;&lt;p&gt;My quest is to ultimately end up with the skills to set up kubernetes so that it can be deployed to everything from a DIY NAS and a stack of NUCs to a warehouse full of servers backed by distributed storage.&#xA;I&amp;rsquo;m obviously more towards the first camp so that&amp;rsquo;s where my journey is at.&#xA;With that said, my goal is to have software small and lightweight enough that it can run on the former setup easily so that there can be multiple instances of it in the latter form.&#xA;The current mental model I have is developer organization with not much more than 3 NUCs + 1 NAS per team without losing the ability for continuous integration and continuous deployment.&#xA;Therefore the landscape needs to be explored and the obvious titan of the old world is &lt;a href=&#34;https://www.jenkins.io/&#34;&gt;jenkins&lt;/a&gt; with many newcomers eager to take its place.&#xA;The obvious caveats still apply, it must be open-source, able to be self-hosted, support for gitea is needed and being able to run well on kubernetes is a foregone conclusion.&lt;/p&gt;&#xA;&lt;h3 id=&#34;jenkins&#34;&gt;Jenkins&lt;/h3&gt;&#xA;&lt;p&gt;It should need no introduction, most developers are familiar with the trusty crusty old butler software.&#xA;&lt;a href=&#34;https://www.jenkins.io/&#34;&gt;Jenkins&lt;/a&gt; is probably one of the most prominent pieces of CI/CD software that was pushed to the forefront when the push for more automation and increased code quality really happened.&#xA;Sadly there are a few reasons that annoyed me from the get-go.&#xA;First, the unlocking procedure requires you to &lt;code&gt;kubectl logs &amp;lt;podname&amp;gt;&lt;/code&gt; in order to find the unlock key which I understand but nonetheless find annoying.&#xA;Second, the &lt;code&gt;Jenkinsfile&lt;/code&gt; has its own domain-specific language (DSL for short) that I find unappealing even though you won&amp;rsquo;t catch me praising YAML&amp;rsquo;s lack of curly braces.&#xA;I begrudgingly went though it and wrote a &lt;code&gt;Jenkinsfile&lt;/code&gt; to give it a fair chance but it wasn&amp;rsquo;t a nice experience.&#xA;Next, a single instance uses too much ram to the point that it can barely fit in my k3s VMs which use 2.5GB of ram each together with other software.&#xA;This is an issue because I like running at least 2 instances of most applications to be sure that everything works correctly when scaling up.&#xA;Last but not least, it&amp;rsquo;s a 2-in-1 solution which I don&amp;rsquo;t find appealing as far as architecture and since I was planning to find a standalone piece of software to do CI and another one to handle CD, it was a hard sell from the start.&#xA;As a redeeming quality it has an official kubernetes pipeline plugin which is nice so they&amp;rsquo;ve at least put thought into this use case.&#xA;Ultimately it wasn&amp;rsquo;t the right fit for me so it was time to move on.&lt;/p&gt;&#xA;&lt;h3 id=&#34;drone&#34;&gt;Drone&lt;/h3&gt;&#xA;&lt;p&gt;While pondering this I remembered an old post from one of the blogs I read, specifically &lt;a href=&#34;https://christine.website/blog/drone-kubernetes-cd-2020-07-10&#34;&gt;this one&lt;/a&gt;.&#xA;I said what the hell, why not and started looking its website.&#xA;&lt;a href=&#34;https://www.drone.io/&#34;&gt;Drone&lt;/a&gt; is a very nice and simple continuous integration tool.&#xA;From the start it seemed like it would be a good pick but you never know until you try.&#xA;I wrote some kubernetes manifests, got angry until I got them to work and a half hour later it was hooked up to my local gitea instance and ready to use.&#xA;I added a &lt;code&gt;.drone.yml&lt;/code&gt; to one of my repos, pushed the change, activated the repo from the drone dashboard, made another change to the source code, pushed it and waited to see what happened.&#xA;Instantly drone received the webhook event and got to work.&#xA;The dashboard is pretty simple (and sadly lacks a dark mode) so you just hit the thing you want to look at, click on the build and see it happen.&#xA;It supports different things running at the same time like databases if you want your tests to include that which can be run either as what drone calls &lt;code&gt;services&lt;/code&gt; aka run in the background from the beginning or if you want an ordered dependency you can use detached steps which is especially useful in microservices.&#xA;My only real complaint aside from the lack of dark mode is the inability to trigger a build manually without pushing but that&amp;rsquo;s only an issue when you first activate a repository inside drone&amp;rsquo;s dashboard.&#xA;All in all, it has been a joy to use, most of the projects I am currently developing have a &lt;code&gt;.drone.yml&lt;/code&gt; and get built at least 3 times a day when gitea mirrors the gitlab or github repo they&amp;rsquo;re mainly hosted at.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;This wasn&amp;rsquo;t as big of a journey as finding a continuous development tool because really I only found the two aforementioned options that had the basics I was looking for and one of them didn&amp;rsquo;t really fit the bill.&#xA;I&amp;rsquo;m not huge into software development, it&amp;rsquo;s mostly a hobby for me as might be obvious by now, since my main concern is infrastructure-related stuff.&#xA;With that said it&amp;rsquo;s useful to have the skills to build an application that can communicate with the kubernets api to automate something or write an ansible module and most of all it allows me to see the developer perspective.&#xA;I haven&amp;rsquo;t started looking into &lt;a href=&#34;https://github.com/mozilla/sops&#34;&gt;SOPS&lt;/a&gt; or &lt;a href=&#34;https://renovatebot.com/&#34;&gt;renovate bot&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rancher/system-upgrade-controller&#34;&gt;k3s upgrade controller&lt;/a&gt; or &lt;a href=&#34;https://velero.io&#34;&gt;velero&lt;/a&gt; but I hope to get the chance to do so in the future.&#xA;Thank you for reading, I hope you enjoyed it and maybe learned something.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Fluxing My Cluster</title>
				<link>https://inherently.xyz/blog/fluxing-my-cluster/</link>
				<pubDate>Sat, 17 Apr 2021 17:24:22 +0300</pubDate>
				<guid>https://inherently.xyz/blog/fluxing-my-cluster/</guid>
				<description>&lt;p&gt;It&amp;rsquo;s no secret that I&amp;rsquo;m a fan of automation and making life easier (even if I made it harder in the first place).&#xA;One of the issues I&amp;rsquo;ve been having in my homelab is dealing with deploying stuff to kubernetes.&#xA;Initially I wanted to just add a plugin to &lt;a href=&#34;https://www.drone.io/&#34;&gt;drone&lt;/a&gt; and be done with it.&#xA;However, that didn&amp;rsquo;t really pan out which ended up being to my benefit since I discovered &lt;a href=&#34;https://toolkit.fluxcd.io/&#34;&gt;flux&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;&#xA;&lt;p&gt;The cluster in its current state is a little sad because I end up doing too many things manually.&#xA;Whenever something changes it&amp;rsquo;s time to bring out ye old &lt;code&gt;kubectl apply -f&lt;/code&gt; in a local clone of the repo and that doesn&amp;rsquo;t spark joy.&#xA;This was obviously bad form and couldn&amp;rsquo;t continue.&#xA;What you also have to keep in mind is that I&amp;rsquo;ve chosen a 3rd-party storage plugin, &lt;a href=&#34;&#34;&gt;democratic-csi&lt;/a&gt; and assume it&amp;rsquo;s the default storageclass in the cluster.&#xA;This means that on a new cluster it&amp;rsquo;s required that before anything else, that one is added as a storageclass and set as default and &lt;code&gt;local-path&lt;/code&gt; is removed from being a default.&#xA;After that, the applications can be deployed which includes a mix of stuff I&amp;rsquo;ve written for the purposes of testing as well as 3rd-party software.&#xA;Now that the stage has been set, let&amp;rsquo;s see what I tried&lt;/p&gt;&#xA;&lt;h2 id=&#34;solutions&#34;&gt;Solutions&lt;/h2&gt;&#xA;&lt;h3 id=&#34;drone-ci-plugin&#34;&gt;Drone CI plugin&lt;/h3&gt;&#xA;&lt;p&gt;Initially the idea was that since I&amp;rsquo;ve alrady solved this for code using drone for CI (this will be discussed in a later post), I could just use a plugin and be done.&#xA;However, my experience with writing helm charts is limited and the only official plugin for deploying to kubernetes is for helm charts, not kubernetes manifests.&#xA;Furthermore, as I mentioned previously, not all software deployed on the cluster is something that I have written so even if there was an official kubernetes manifest plugin it wouldn&amp;rsquo;t cover 3rd-party software.&#xA;At this point, I was thinking of finding some all-inclusive CI/CD software that would cover everything I wanted to do.&#xA;It took no more than 10 seconds of thinking to realize that I was looking for non-modular software and discard that idea.&lt;/p&gt;&#xA;&lt;h3 id=&#34;standalone-continuous-delivery&#34;&gt;Standalone Continuous Delivery&lt;/h3&gt;&#xA;&lt;p&gt;This was the obvious choice but the software in this category is plentiful.&#xA;The main competitors were &lt;a href=&#34;https://toolkit.fluxcd.io/&#34;&gt;flux&lt;/a&gt;, &lt;a href=&#34;https://argoproj.github.io/projects/argo-cd/&#34;&gt;argo&lt;/a&gt; and &lt;a href=&#34;https://tekton.dev/&#34;&gt;tekton&lt;/a&gt;.&#xA;Their designs differ quite a bit so there is going to be quite a bit of opinion in the following analysis so just keep that in mind.&#xA;The few things they had in common were that they were all advertised as cloud-native with support for kubernetes, had a cli and were written in Go.&lt;/p&gt;&#xA;&lt;h4 id=&#34;argocd&#34;&gt;ArgoCD&lt;/h4&gt;&#xA;&lt;p&gt;I started with argo because one of the people that wrote a really good blog post on using kubernetes at home mentioned that they use it so I thought I&amp;rsquo;d try it first.&#xA;The installation process required a massive yaml file that you just &lt;code&gt;curl | kubectl apply -f&lt;/code&gt; which I wasn&amp;rsquo;t a big fan of but alright whatever.&#xA;It also had a weird unlock procedure like jenkins where you have to find a token generated at runtime to unlock it but that&amp;rsquo;s okay, just an one-time setup thing.&#xA;After spending a couple evenings with it, I wasn&amp;rsquo;t satisfied with the experience.&#xA;The docs weren&amp;rsquo;t really good at explaining all the argo custom resources and getting a basic single-pod application running took me more than 2 hours.&#xA;It was doable but this was going to be something I had to do for every application running on my cluster and the prospect didn&amp;rsquo;t seem appealing.&#xA;I&amp;rsquo;m sure with more time I could maybe become more familiar and eventually warm up to it however first impressions were bad so I decided to move on.&lt;/p&gt;&#xA;&lt;h4 id=&#34;tekton&#34;&gt;Tekton&lt;/h4&gt;&#xA;&lt;p&gt;Tekton&amp;rsquo;s marketing was interesting so I took a look at it next.&#xA;It seemed to be easier to set up and a couple random blog posts seemed to praise it so I downloaded another massive installation yaml which the guide told me to just &lt;code&gt;kubectl apply -f&lt;/code&gt; which is okay I guess.&#xA;I spent a few hours with it and it became clear you basically had to use it both for CI and CD so I put it to the side and moved on.&lt;/p&gt;&#xA;&lt;h4 id=&#34;flux&#34;&gt;Flux&lt;/h4&gt;&#xA;&lt;p&gt;So why did I mention this one first but try it last?&#xA;A few reasons.&#xA;While researching, the v1 -&amp;gt; v2 development effort was going on and v2 didn&amp;rsquo;t have a lot of features but v1 was being phased out so I didn&amp;rsquo;t know if I should spend time learning v1 while v2 was coming along or if it&amp;rsquo;s worth jumping into alpha/beta stage software to avoid using legacy versions.&#xA;By the time I did get around to it though v2 was clearly the way forward.&#xA;Not only was it officially endorsed but among people that self-host, it was already the way to go 6-12 months ago.&#xA;The docs were pretty clear, the cli was cross-platform and could be installed on a Raspberry Pi (something that argo at the time didn&amp;rsquo;t have available) and the examples worked.&#xA;In an evening I had learned basically everything I needed to in order to just drop it in, generate the flux CRDs for my existing kubernetes manifests as well as helm charts and be up and running.&#xA;The only issue I had, probably just a pet peeve of mine, was that the repo it creates on github is private by default and my goal is to have everything public and also secure (not there yet) but whatever.&#xA;Flux v2 also mentioned as the gitops toolkit is made up of several different parts that have a specific purpose which is something I certainly appreciate.&#xA;All in all, I think I&amp;rsquo;m going to stick with flux but you never know how homelab things will end up.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Flux is a really great project and I&amp;rsquo;ve enjoyed using it so far.&#xA;The problem of continuous delivery has been solved for me and I recommend checking out if you&amp;rsquo;re in a similar position.&#xA;Next up, I&amp;rsquo;m going to look at &lt;a href=&#34;https://renovatebot.com/&#34;&gt;renovate bot&lt;/a&gt; for automating image updates, &lt;a href=&#34;https://github.com/mozilla/sops&#34;&gt;SOPS&lt;/a&gt; for secret management (which &lt;a href=&#34;https://toolkit.fluxcd.io/guides/mozilla-sops/&#34;&gt;flux supports&lt;/a&gt; and &lt;a href=&#34;https://github.com/rancher/system-upgrade-controller&#34;&gt;an upgrade controller&lt;/a&gt;) to further help automate operations.&#xA;Thank you for reading, I hope you enjoyed it and maybe learned something.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Homelab Current Form</title>
				<link>https://inherently.xyz/blog/homelab-current-form/</link>
				<pubDate>Sun, 07 Feb 2021 14:35:32 +0200</pubDate>
				<guid>https://inherently.xyz/blog/homelab-current-form/</guid>
				<description>&lt;p&gt;The first part of the software changes I made was covered &lt;a href=&#34;https://inherently.xyz/blog/homelab-evolved/&#34;&gt;in the first part&lt;/a&gt; where I explained how and why I started going down this path.&lt;/p&gt;&#xA;&lt;h2 id=&#34;software-choices&#34;&gt;Software choices&lt;/h2&gt;&#xA;&lt;p&gt;This whole journey was about making my home infrastructure better.&#xA;Part of that was about having a way to more easily create the foundation on which kubernetes would run on, as well as describing my setup as code.&#xA;Proxmox is a beast in its own right. Features include being able to manage kvm virtual machines and lxc containers, an API that can be used to interact with it programmatically and most importantly being open source.&#xA;While researching what automation tools could interact with proxmox, I found a community-made terraform provider as well as a set of two ansible community modules (kvm and lxc).&#xA;After thinking about it a little bit, I wanted to use terraform in a non-cloud environment but also gather some knowledge about it so that’s what I decided to use.&#xA;I can have my provisioning requirements in a file that terraform understands and store it in git which is exactly what I was going for.&#xA;Ansible is still in the picture since it is used to set up and configure the debian environment inside the virtual machines.&#xA;Now that the hypervisor part is covered, let&amp;rsquo;s move on to running services.&lt;/p&gt;&#xA;&lt;h2 id=&#34;making-it-store-is-harder-than-making-it-run&#34;&gt;Making it store is harder than making it run&lt;/h2&gt;&#xA;&lt;p&gt;As mentioned &lt;a href=&#34;https://inherently.xyz/blog/homelab-evolved/&#34;&gt;in the first part about software changes&lt;/a&gt;, I was learning kubernetes and now I could not only wipe and recreate the cluster itself but also the entire virtual machines that it was running on.&#xA;Some time after starting to use proxmox with terraform I attempted to use rancher to manage kubernetes but ended up ditching it due to various problems with running even basic stuff on it (very likely that it’s a case of PEBCAK, I don’t think rancher is terrible or anything like that).&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-problem&#34;&gt;The problem&lt;/h3&gt;&#xA;&lt;p&gt;However the problem of shared storage continued to taunt me for the following months.&#xA;There was seemingly nothing that a simple fella could do to use a nice and simple NAS running truenas core as storage that is able to be dynamically provisioned for use by kubernetes.&#xA;Now, I hear you, &amp;ldquo;what about nfs-client-provisioner&amp;rdquo;, someone less familiar with this pile of madness might exclaim.&#xA;Indeed it does exist and barely work except the helm chart for it is deprecated and it does not work with kubernetes version 1.20 and later since it does not seem to be using CSI drivers.&lt;/p&gt;&#xA;&lt;h3 id=&#34;i-really-tried&#34;&gt;I really tried&lt;/h3&gt;&#xA;&lt;p&gt;Months of furious and frustrating testing ensued.&#xA;Not only was I trying to get applications running on kubernetes, I was also fighting with the unexpectedly complex tast of using the storage server I had available.&lt;/p&gt;&#xA;&lt;h4 id=&#34;glusterfs&#34;&gt;glusterfs&lt;/h4&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve gone through basically any and all commonly suggested options for dynamically provisioned storage.&#xA;Prette early on I tried glusterfs with heketi by making 3 LXC containers and mounting an nfs share to each one that would serve as the brick in the gluster volume.&#xA;Suffice it to say that it didn&amp;rsquo;t work and things were getting out of hand.&lt;/p&gt;&#xA;&lt;h4 id=&#34;longhorn&#34;&gt;longhorn&lt;/h4&gt;&#xA;&lt;p&gt;After a bit more research and I found out that longhorn, another project by the authors of k3s, used iscsi to communicate with kubernetes.&#xA;That could work I thought, except there was no coherent example of how to use it without using targetd for iscsi.&#xA;Longhorn was starting to look more appealing, I could just put the virtual drives of the VMs on an nfs share, run longhorn inside the VMs to pool all their storage together and call it good enough.&#xA;No, I could not give up yet.&#xA;A sub-optimal solution would do if there was no other way but I was convinced something more was out there.&#xA;My patience and hope were running out but not empty yet.&lt;/p&gt;&#xA;&lt;h4 id=&#34;success&#34;&gt;success&lt;/h4&gt;&#xA;&lt;p&gt;That all changed in early January where during my nearly daily search for possible storage solutions I hadn’t tried, I found out about &lt;a href=&#34;https://github.com/democratic-csi/democratic-csi&#34;&gt;democratic-csi&lt;/a&gt;.&#xA;This was it. Made to be used with freenas, truenas as well as DIY ZFS setups.&#xA;The silver bullet was here.&#xA;Just a few minutes of reading about it and writing my configs, a short(read: long) helm command later and&amp;hellip;success!&#xA;The test pod was using the newly created storageclass that was backed by the nfs share on truenas.&#xA;After that I rushed to deploy my standard set of gitea, droneci and minecraft to test it out and it was working for real without a hitch.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;This was a long journey and it isn’t coming to a close any time soon.&#xA;The next step is to continuous deployment but that’s an issue for another time.&#xA;To conclude as briefly as possible, I’ve no put most of the critical pieces of my homelab in a single git repo that I can use to recreate almost all of it from scratch with minimal manual intervention (there are still a few quirks like not having dynamic inventory for ansible and having to manually copy IPs but I can put that aside for now).&#xA;Despite the imperfections like not having dynamic inventory for ansible or having secrets stored unencrypted in git, I&amp;rsquo;m very happy with the setup is working.&#xA;If you missed them, make sure to check out the &lt;a href=&#34;https://inherently.xyz/blog/hardware-updates-2020/&#34;&gt;hardware updates&lt;/a&gt; and &lt;a href=&#34;https://inherently.xyz/blog/homelab-evolved/&#34;&gt;the first part about software changes&lt;/a&gt; for a better of what I&amp;rsquo;ve been up to.&lt;/p&gt;&#xA;</description>
			</item>
			<item>
				<title>Homelab Evolved</title>
				<link>https://inherently.xyz/blog/homelab-evolved/</link>
				<pubDate>Sun, 07 Feb 2021 13:53:10 +0200</pubDate>
				<guid>https://inherently.xyz/blog/homelab-evolved/</guid>
				<description>&lt;p&gt;The hardware side of the changes made to my homelab were covered &lt;a href=&#34;https://inherently.xyz/blog/hardware-updates-2020/&#34;&gt;in a previous post&lt;/a&gt; where I also alluded to some software changes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-came-before&#34;&gt;What came before&lt;/h2&gt;&#xA;&lt;p&gt;This is the first part explaining more in-depth the issues that I had and how I dealt with them.&#xA;Let&amp;rsquo;s set the stage first, my homelab was working fine in many ways.&#xA;It was nice and stable debian install running kvm virtual machines using qemu and libvirt with virt-manager to perform the simpler start/stop tasks.&#xA;There was really nothing wrong with it, I was exploring different software, running some services on the local network and even hosting a public website on it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;good-enough-is-not-good-enough&#34;&gt;Good enough is not good enough&lt;/h2&gt;&#xA;&lt;p&gt;However as someone interested in infrastructure a few things were bothering me.&#xA;Sure, I was using docker-compose with traefik for my public website and services.&#xA;Yes, I was using ansible to manage the configuration of most virtual machines.&#xA;But &amp;ldquo;good enough&amp;rdquo; and &amp;ldquo;I guess it works&amp;rdquo; doesn&amp;rsquo;t cut it.&#xA;On the upside, I really liked having ZFS snapshots on a 2x2TB mirror.&#xA;The ability to go back to a point in time where things were not broken had saved me a couple times when I inevitably broke one thing or deleted a file that could be replaced but would take a while.&#xA;My backups were also on that ZFS mirror, on a different dataset of course, and that also very useful.&#xA;I knew I wanted ZFS and that there was much room for improvement in regards to handling how I was running services. The single docker-compose virtual machine for the public stuff and another one for local stuff were mostly adequate but the manual management was not.&#xA;Not to mention that and all my precious stuff was on one box which is well below ideal.&lt;/p&gt;&#xA;&lt;h2 id=&#34;taking-the-step&#34;&gt;Taking the step&lt;/h2&gt;&#xA;&lt;p&gt;One day I decided it was time to move up in the world.&#xA;Despite using docker and docker-compose for years I had never dived into kubernetes because it seemed difficult and complex.&#xA;New syntax, new system with its own architecture and internal structure, new workflow, new everything.&#xA;I decided to set up 3 VMs and played with default k8s as well as k3s on them.&#xA;Dipping my toes into it was pretty fun and since nothing depended on it I was free to wipe it and start over.&#xA;The same issue kept cropping up, having to manually install debian thrice and set up kubernetes just to delete all of it and redo it was again, less than ideal&#xA;Initially I started writing a playbook before finding out that someone smarter had already gone down this path.&#xA;Setting up &lt;a href=&#34;https://github.com/k3s-io/k3s-ansible&#34;&gt;k3s-ansible&lt;/a&gt; was easy so there was at least kubernetes setup automation but the whole thing was too thrown together there was no shared storage.&#xA;However, I was becoming more familiar with kubernetes and learning the concepts as well as how to write yaml manifests.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;At some point it became too bothersome, a lot of manual work was involved and basic stuff like copying over ssh keys was also done mostly manually so I had to move on.&#xA;While all of this was going on, I had started planning what hardware updates I would get which you can read about here: &lt;a href=&#34;https://inherently.xyz/blog/hardware-updates-2020/&#34;&gt;Hardware Updates 2020&lt;/a&gt;&lt;/p&gt;&#xA;</description>
			</item>
	</channel>
</rss>
